blob: 1efbf78696394a10dc430ca969b24327c7fe57a5 [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); });
jiabin9c07faf2023-04-26 22:00:44 +0000207 std::transform(mPortConfigs.begin(), mPortConfigs.end(),
208 std::inserter(mInitialPortConfigIds, mInitialPortConfigIds.end()),
209 [](const auto& pcPair) { return pcPair.first; });
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800210 std::vector<AudioPatch> patches;
211 RETURN_STATUS_IF_ERROR(
212 statusTFromBinderStatus(mModule->getAudioPatches(&patches))); // OK if empty
213 std::transform(patches.begin(), patches.end(),
214 std::inserter(mPatches, mPatches.end()),
215 [](const auto& p) { return std::make_pair(p.id, p); });
Shunkai Yao51202502022-12-12 06:11:46 +0000216 return OK;
217}
218
219status_t DeviceHalAidl::setVoiceVolume(float volume) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000220 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000221 if (!mModule) return NO_INIT;
222 std::shared_ptr<ITelephony> telephony;
223 if (ndk::ScopedAStatus status = mModule->getTelephony(&telephony);
224 status.isOk() && telephony != nullptr) {
225 ITelephony::TelecomConfig inConfig{ .voiceVolume = Float{volume} }, outConfig;
226 RETURN_STATUS_IF_ERROR(
227 statusTFromBinderStatus(telephony->setTelecomConfig(inConfig, &outConfig)));
228 ALOGW_IF(outConfig.voiceVolume.has_value() && volume != outConfig.voiceVolume.value().value,
229 "%s: the resulting voice volume %f is not the same as requested %f",
230 __func__, outConfig.voiceVolume.value().value, volume);
231 }
232 return INVALID_OPERATION;
Shunkai Yao51202502022-12-12 06:11:46 +0000233}
234
235status_t DeviceHalAidl::setMasterVolume(float volume) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000236 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000237 if (!mModule) return NO_INIT;
238 return statusTFromBinderStatus(mModule->setMasterVolume(volume));
Shunkai Yao51202502022-12-12 06:11:46 +0000239}
240
241status_t DeviceHalAidl::getMasterVolume(float *volume) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000242 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000243 if (!mModule) return NO_INIT;
244 return statusTFromBinderStatus(mModule->getMasterVolume(volume));
Shunkai Yao51202502022-12-12 06:11:46 +0000245}
246
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000247status_t DeviceHalAidl::setMode(audio_mode_t mode) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000248 TIME_CHECK();
249 if (!mModule) return NO_INIT;
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000250 AudioMode audioMode = VALUE_OR_FATAL(::aidl::android::legacy2aidl_audio_mode_t_AudioMode(mode));
251 std::shared_ptr<ITelephony> telephony;
252 if (ndk::ScopedAStatus status = mModule->getTelephony(&telephony);
253 status.isOk() && telephony != nullptr) {
254 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(telephony->switchAudioMode(audioMode)));
255 }
256 return statusTFromBinderStatus(mModule->updateAudioMode(audioMode));
Shunkai Yao51202502022-12-12 06:11:46 +0000257}
258
259status_t DeviceHalAidl::setMicMute(bool state) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000260 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000261 if (!mModule) return NO_INIT;
262 return statusTFromBinderStatus(mModule->setMicMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000263}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000264
Shunkai Yao51202502022-12-12 06:11:46 +0000265status_t DeviceHalAidl::getMicMute(bool *state) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000266 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000267 if (!mModule) return NO_INIT;
268 return statusTFromBinderStatus(mModule->getMicMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000269}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000270
Shunkai Yao51202502022-12-12 06:11:46 +0000271status_t DeviceHalAidl::setMasterMute(bool state) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000272 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000273 if (!mModule) return NO_INIT;
274 return statusTFromBinderStatus(mModule->setMasterMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000275}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000276
Shunkai Yao51202502022-12-12 06:11:46 +0000277status_t DeviceHalAidl::getMasterMute(bool *state) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000278 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000279 if (!mModule) return NO_INIT;
280 return statusTFromBinderStatus(mModule->getMasterMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000281}
282
Mikhail Naganov31d46652023-01-10 18:29:25 +0000283status_t DeviceHalAidl::setParameters(const String8& kvPairs __unused) {
284 TIME_CHECK();
285 if (!mModule) return NO_INIT;
286 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000287 return OK;
288}
289
Mikhail Naganov31d46652023-01-10 18:29:25 +0000290status_t DeviceHalAidl::getParameters(const String8& keys __unused, String8 *values) {
291 TIME_CHECK();
292 values->clear();
293 if (!mModule) return NO_INIT;
294 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000295 return OK;
296}
297
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800298namespace {
299
300class Cleanup {
301 public:
302 typedef void (DeviceHalAidl::*Cleaner)(int32_t);
303
304 Cleanup(DeviceHalAidl* device, Cleaner cleaner, int32_t id) :
305 mDevice(device), mCleaner(cleaner), mId(id) {}
306 ~Cleanup() { clean(); }
307 void clean() {
308 if (mDevice != nullptr) (mDevice->*mCleaner)(mId);
309 disarm();
310 }
311 void disarm() { mDevice = nullptr; }
312
313 private:
314 DeviceHalAidl* mDevice;
315 const Cleaner mCleaner;
316 const int32_t mId;
317};
318
319} // namespace
320
321// Since the order of container elements destruction is unspecified,
322// ensure that cleanups are performed from the most recent one and upwards.
323// This is the same as if there were individual Cleanup instances on the stack,
324// however the bonus is that we can disarm all of them with just one statement.
325class DeviceHalAidl::Cleanups : public std::forward_list<Cleanup> {
326 public:
327 ~Cleanups() { for (auto& c : *this) c.clean(); }
328 void disarmAll() { for (auto& c : *this) c.disarm(); }
329};
330
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800331status_t DeviceHalAidl::getInputBufferSize(const struct audio_config* config, size_t* size) {
332 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
333 if (size == nullptr) return BAD_VALUE;
334 TIME_CHECK();
335 if (!mModule) return NO_INIT;
336 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
337 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, true /*isInput*/));
338 AudioDevice aidlDevice;
339 aidlDevice.type.type = AudioDeviceType::IN_DEFAULT;
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800340 AudioSource aidlSource = AudioSource::DEFAULT;
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800341 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::input>(0);
342 AudioPortConfig mixPortConfig;
343 Cleanups cleanups;
344 audio_config writableConfig = *config;
Mikhail Naganove93a0862023-03-15 17:06:59 -0700345 AudioPatch aidlPatch;
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800346 RETURN_STATUS_IF_ERROR(prepareToOpenStream(0 /*handle*/, aidlDevice, aidlFlags, aidlSource,
Mikhail Naganove93a0862023-03-15 17:06:59 -0700347 &writableConfig, &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800348 *size = aidlConfig.frameCount *
349 getFrameSizeInBytes(aidlConfig.base.format, aidlConfig.base.channelMask);
350 // Do not disarm cleanups to release temporary port configs.
351 return OK;
352}
353
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800354status_t DeviceHalAidl::prepareToOpenStream(
355 int32_t aidlHandle, const AudioDevice& aidlDevice, const AudioIoFlags& aidlFlags,
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800356 AudioSource aidlSource, struct audio_config* config,
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800357 Cleanups* cleanups, AudioConfig* aidlConfig, AudioPortConfig* mixPortConfig,
Mikhail Naganove93a0862023-03-15 17:06:59 -0700358 AudioPatch* aidlPatch) {
359 ALOGD("%p %s::%s: handle %d, device %s, flags %s, source %s, config %s, mix port config %s",
360 this, getClassName().c_str(), __func__, aidlHandle, aidlDevice.toString().c_str(),
361 aidlFlags.toString().c_str(), toString(aidlSource).c_str(),
362 aidlConfig->toString().c_str(), mixPortConfig->toString().c_str());
jiabin9c07faf2023-04-26 22:00:44 +0000363 resetUnusedPatchesAndPortConfigs();
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800364 const bool isInput = aidlFlags.getTag() == AudioIoFlags::Tag::input;
365 // Find / create AudioPortConfigs for the device port and the mix port,
366 // then find / create a patch between them, and open a stream on the mix port.
367 AudioPortConfig devicePortConfig;
368 bool created = false;
jiabin9c07faf2023-04-26 22:00:44 +0000369 RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(aidlDevice, aidlConfig,
370 &devicePortConfig, &created));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800371 if (created) {
372 cleanups->emplace_front(this, &DeviceHalAidl::resetPortConfig, devicePortConfig.id);
373 }
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800374 RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(*aidlConfig, aidlFlags, aidlHandle, aidlSource,
Mikhail Naganov289468a2023-03-29 10:06:15 -0700375 std::set<int32_t>{devicePortConfig.portId}, mixPortConfig, &created));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800376 if (created) {
377 cleanups->emplace_front(this, &DeviceHalAidl::resetPortConfig, mixPortConfig->id);
378 }
379 setConfigFromPortConfig(aidlConfig, *mixPortConfig);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800380 if (isInput) {
381 RETURN_STATUS_IF_ERROR(findOrCreatePatch(
Mikhail Naganove93a0862023-03-15 17:06:59 -0700382 {devicePortConfig.id}, {mixPortConfig->id}, aidlPatch, &created));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800383 } else {
384 RETURN_STATUS_IF_ERROR(findOrCreatePatch(
Mikhail Naganove93a0862023-03-15 17:06:59 -0700385 {mixPortConfig->id}, {devicePortConfig.id}, aidlPatch, &created));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800386 }
387 if (created) {
Mikhail Naganove93a0862023-03-15 17:06:59 -0700388 cleanups->emplace_front(this, &DeviceHalAidl::resetPatch, aidlPatch->id);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800389 }
390 if (aidlConfig->frameCount <= 0) {
Mikhail Naganove93a0862023-03-15 17:06:59 -0700391 aidlConfig->frameCount = aidlPatch->minimumStreamBufferSizeFrames;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800392 }
393 *config = VALUE_OR_RETURN_STATUS(
394 ::aidl::android::aidl2legacy_AudioConfig_audio_config_t(*aidlConfig, isInput));
395 return OK;
396}
397
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800398namespace {
399
400class StreamCallbackBase {
401 protected:
402 explicit StreamCallbackBase(const sp<CallbackBroker>& broker) : mBroker(broker) {}
403 public:
404 void* getCookie() const { return mCookie; }
405 void setCookie(void* cookie) { mCookie = cookie; }
406 sp<CallbackBroker> getBroker() const {
407 if (void* cookie = mCookie; cookie != nullptr) return mBroker.promote();
408 return nullptr;
409 }
410 private:
411 const wp<CallbackBroker> mBroker;
412 std::atomic<void*> mCookie;
413};
414
415template<class C>
416class StreamCallbackBaseHelper {
417 protected:
418 explicit StreamCallbackBaseHelper(const StreamCallbackBase& base) : mBase(base) {}
419 sp<C> getCb(const sp<CallbackBroker>& broker, void* cookie);
420 using CbRef = const sp<C>&;
421 ndk::ScopedAStatus runCb(const std::function<void(CbRef cb)>& f) {
422 if (auto cb = getCb(mBase.getBroker(), mBase.getCookie()); cb != nullptr) f(cb);
423 return ndk::ScopedAStatus::ok();
424 }
425 private:
426 const StreamCallbackBase& mBase;
427};
428
429template<>
430sp<StreamOutHalInterfaceCallback> StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>::getCb(
431 const sp<CallbackBroker>& broker, void* cookie) {
432 if (broker != nullptr) return broker->getStreamOutCallback(cookie);
433 return nullptr;
434}
435
436template<>
437sp<StreamOutHalInterfaceEventCallback>
438StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>::getCb(
439 const sp<CallbackBroker>& broker, void* cookie) {
440 if (broker != nullptr) return broker->getStreamOutEventCallback(cookie);
441 return nullptr;
442}
443
444template<>
445sp<StreamOutHalInterfaceLatencyModeCallback>
446StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>::getCb(
447 const sp<CallbackBroker>& broker, void* cookie) {
448 if (broker != nullptr) return broker->getStreamOutLatencyModeCallback(cookie);
449 return nullptr;
450}
451
452/*
453Note on the callback ownership.
454
455In the Binder ownership model, the server implementation is kept alive
456as long as there is any client (proxy object) alive. This is done by
457incrementing the refcount of the server-side object by the Binder framework.
458When it detects that the last client is gone, it decrements the refcount back.
459
460Thus, it is not needed to keep any references to StreamCallback on our
461side (after we have sent an instance to the client), because we are
462the server-side. The callback object will be kept alive as long as the HAL server
463holds a strong ref to IStreamCallback proxy.
464*/
465
466class OutputStreamCallbackAidl : public StreamCallbackBase,
467 public StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>,
468 public ::aidl::android::hardware::audio::core::BnStreamCallback {
469 public:
470 explicit OutputStreamCallbackAidl(const sp<CallbackBroker>& broker)
471 : StreamCallbackBase(broker),
472 StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>(
473 *static_cast<StreamCallbackBase*>(this)) {}
474 ndk::ScopedAStatus onTransferReady() override {
475 return runCb([](CbRef cb) { cb->onWriteReady(); });
476 }
477 ndk::ScopedAStatus onError() override {
478 return runCb([](CbRef cb) { cb->onError(); });
479 }
480 ndk::ScopedAStatus onDrainReady() override {
481 return runCb([](CbRef cb) { cb->onDrainReady(); });
482 }
483};
484
485class OutputStreamEventCallbackAidl :
486 public StreamCallbackBase,
487 public StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>,
488 public StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>,
489 public ::aidl::android::hardware::audio::core::BnStreamOutEventCallback {
490 public:
491 explicit OutputStreamEventCallbackAidl(const sp<CallbackBroker>& broker)
492 : StreamCallbackBase(broker),
493 StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>(
494 *static_cast<StreamCallbackBase*>(this)),
495 StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>(
496 *static_cast<StreamCallbackBase*>(this)) {}
497 ndk::ScopedAStatus onCodecFormatChanged(const std::vector<uint8_t>& in_audioMetadata) override {
498 std::basic_string<uint8_t> halMetadata(in_audioMetadata.begin(), in_audioMetadata.end());
499 return StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>::runCb(
500 [&halMetadata](auto cb) { cb->onCodecFormatChanged(halMetadata); });
501 }
502 ndk::ScopedAStatus onRecommendedLatencyModeChanged(
503 const std::vector<AudioLatencyMode>& in_modes) override {
504 auto halModes = VALUE_OR_FATAL(
505 ::aidl::android::convertContainer<std::vector<audio_latency_mode_t>>(
506 in_modes,
507 ::aidl::android::aidl2legacy_AudioLatencyMode_audio_latency_mode_t));
508 return StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>::runCb(
509 [&halModes](auto cb) { cb->onRecommendedLatencyModeChanged(halModes); });
510 }
511};
512
513} // namespace
514
Mikhail Naganov31d46652023-01-10 18:29:25 +0000515status_t DeviceHalAidl::openOutputStream(
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800516 audio_io_handle_t handle, audio_devices_t devices,
517 audio_output_flags_t flags, struct audio_config* config,
518 const char* address,
Mikhail Naganov31d46652023-01-10 18:29:25 +0000519 sp<StreamOutHalInterface>* outStream) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800520 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000521 if (!outStream || !config) {
522 return BAD_VALUE;
523 }
524 TIME_CHECK();
525 if (!mModule) return NO_INIT;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800526 int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
527 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(handle));
528 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
529 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, false /*isInput*/));
530 AudioDevice aidlDevice = VALUE_OR_RETURN_STATUS(
531 ::aidl::android::legacy2aidl_audio_device_AudioDevice(devices, address));
532 int32_t aidlOutputFlags = VALUE_OR_RETURN_STATUS(
533 ::aidl::android::legacy2aidl_audio_output_flags_t_int32_t_mask(flags));
534 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::output>(aidlOutputFlags);
535 AudioPortConfig mixPortConfig;
536 Cleanups cleanups;
Mikhail Naganove93a0862023-03-15 17:06:59 -0700537 AudioPatch aidlPatch;
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800538 RETURN_STATUS_IF_ERROR(prepareToOpenStream(aidlHandle, aidlDevice, aidlFlags,
539 AudioSource::SYS_RESERVED_INVALID /*only needed for input*/,
Mikhail Naganove93a0862023-03-15 17:06:59 -0700540 config, &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800541 ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamArguments args;
542 args.portConfigId = mixPortConfig.id;
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800543 const bool isOffload = isBitPositionFlagSet(
544 aidlOutputFlags, AudioOutputFlags::COMPRESS_OFFLOAD);
545 std::shared_ptr<OutputStreamCallbackAidl> streamCb;
546 if (isOffload) {
547 streamCb = ndk::SharedRefBase::make<OutputStreamCallbackAidl>(this);
548 }
549 auto eventCb = ndk::SharedRefBase::make<OutputStreamEventCallbackAidl>(this);
550 if (isOffload) {
551 args.offloadInfo = aidlConfig.offloadInfo;
552 args.callback = streamCb;
553 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800554 args.bufferSizeFrames = aidlConfig.frameCount;
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800555 args.eventCallback = eventCb;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800556 ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamReturn ret;
557 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openOutputStream(args, &ret)));
Mikhail Naganov712d71b2023-02-23 17:57:16 -0800558 StreamContextAidl context(ret.desc, isOffload);
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800559 if (!context.isValid()) {
560 ALOGE("%s: Failed to created a valid stream context from the descriptor: %s",
561 __func__, ret.desc.toString().c_str());
562 return NO_INIT;
563 }
Mikhail Naganove93a0862023-03-15 17:06:59 -0700564 *outStream = sp<StreamOutHalAidl>::make(*config, std::move(context), aidlPatch.latenciesMs[0],
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800565 std::move(ret.stream), this /*callbackBroker*/);
Mikhail Naganove93a0862023-03-15 17:06:59 -0700566 mStreams.insert(std::pair(*outStream, aidlPatch.id));
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800567 void* cbCookie = (*outStream).get();
568 {
569 std::lock_guard l(mLock);
570 mCallbacks.emplace(cbCookie, Callbacks{});
571 }
572 if (streamCb) streamCb->setCookie(cbCookie);
573 eventCb->setCookie(cbCookie);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800574 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000575 return OK;
576}
577
Mikhail Naganov31d46652023-01-10 18:29:25 +0000578status_t DeviceHalAidl::openInputStream(
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800579 audio_io_handle_t handle, audio_devices_t devices,
580 struct audio_config* config, audio_input_flags_t flags,
581 const char* address, audio_source_t source,
582 audio_devices_t outputDevice, const char* outputDeviceAddress,
Mikhail Naganov31d46652023-01-10 18:29:25 +0000583 sp<StreamInHalInterface>* inStream) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800584 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000585 if (!inStream || !config) {
586 return BAD_VALUE;
587 }
588 TIME_CHECK();
589 if (!mModule) return NO_INIT;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800590 int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
591 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(handle));
592 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
593 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, true /*isInput*/));
594 AudioDevice aidlDevice = VALUE_OR_RETURN_STATUS(
595 ::aidl::android::legacy2aidl_audio_device_AudioDevice(devices, address));
596 int32_t aidlInputFlags = VALUE_OR_RETURN_STATUS(
597 ::aidl::android::legacy2aidl_audio_input_flags_t_int32_t_mask(flags));
598 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::input>(aidlInputFlags);
599 AudioSource aidlSource = VALUE_OR_RETURN_STATUS(
600 ::aidl::android::legacy2aidl_audio_source_t_AudioSource(source));
601 AudioPortConfig mixPortConfig;
602 Cleanups cleanups;
Mikhail Naganove93a0862023-03-15 17:06:59 -0700603 AudioPatch aidlPatch;
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800604 RETURN_STATUS_IF_ERROR(prepareToOpenStream(aidlHandle, aidlDevice, aidlFlags, aidlSource,
Mikhail Naganove93a0862023-03-15 17:06:59 -0700605 config, &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800606 ::aidl::android::hardware::audio::core::IModule::OpenInputStreamArguments args;
607 args.portConfigId = mixPortConfig.id;
608 RecordTrackMetadata aidlTrackMetadata{
609 .source = aidlSource, .gain = 1, .channelMask = aidlConfig.base.channelMask };
610 if (outputDevice != AUDIO_DEVICE_NONE) {
611 aidlTrackMetadata.destinationDevice = VALUE_OR_RETURN_STATUS(
612 ::aidl::android::legacy2aidl_audio_device_AudioDevice(
613 outputDevice, outputDeviceAddress));
614 }
615 args.sinkMetadata.tracks.push_back(std::move(aidlTrackMetadata));
616 args.bufferSizeFrames = aidlConfig.frameCount;
617 ::aidl::android::hardware::audio::core::IModule::OpenInputStreamReturn ret;
618 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openInputStream(args, &ret)));
Mikhail Naganov712d71b2023-02-23 17:57:16 -0800619 StreamContextAidl context(ret.desc, false /*isAsynchronous*/);
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800620 if (!context.isValid()) {
621 ALOGE("%s: Failed to created a valid stream context from the descriptor: %s",
622 __func__, ret.desc.toString().c_str());
623 return NO_INIT;
624 }
Mikhail Naganove93a0862023-03-15 17:06:59 -0700625 *inStream = sp<StreamInHalAidl>::make(*config, std::move(context), aidlPatch.latenciesMs[0],
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800626 std::move(ret.stream), this /*micInfoProvider*/);
Mikhail Naganove93a0862023-03-15 17:06:59 -0700627 mStreams.insert(std::pair(*inStream, aidlPatch.id));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800628 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000629 return OK;
630}
631
632status_t DeviceHalAidl::supportsAudioPatches(bool* supportsPatches) {
633 *supportsPatches = true;
634 return OK;
635}
636
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800637status_t DeviceHalAidl::createAudioPatch(unsigned int num_sources,
638 const struct audio_port_config* sources,
639 unsigned int num_sinks,
640 const struct audio_port_config* sinks,
641 audio_patch_handle_t* patch) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800642 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000643 TIME_CHECK();
644 if (!mModule) return NO_INIT;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800645 if (num_sinks > AUDIO_PATCH_PORTS_MAX || num_sources > AUDIO_PATCH_PORTS_MAX ||
646 sources == nullptr || sinks == nullptr || patch == nullptr) {
647 return BAD_VALUE;
648 }
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800649 // When the patch handle (*patch) is AUDIO_PATCH_HANDLE_NONE, it means
650 // the framework wants to create a new patch. The handle has to be generated
651 // by the HAL. Since handles generated this way can only be unique within
652 // a HAL module, the framework generates a globally unique handle, and maps
653 // it on the <HAL module, patch handle> pair.
654 // When the patch handle is set, it meant the framework intends to update
655 // an existing patch.
656 //
657 // This behavior corresponds to HAL module behavior, with the only difference
658 // that the HAL module uses `int32_t` for patch IDs. The following assert ensures
659 // that both the framework and the HAL use the same value for "no ID":
660 static_assert(AUDIO_PATCH_HANDLE_NONE == 0);
661 int32_t halPatchId = static_cast<int32_t>(*patch);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800662
663 // Upon conversion, mix port configs contain audio configuration, while
664 // device port configs contain device address. This data is used to find
665 // or create HAL configs.
666 std::vector<AudioPortConfig> aidlSources, aidlSinks;
667 for (unsigned int i = 0; i < num_sources; ++i) {
668 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
669 sources[i].role, sources[i].type)) ==
670 ::aidl::android::AudioPortDirection::INPUT;
671 aidlSources.push_back(VALUE_OR_RETURN_STATUS(
672 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
673 sources[i], isInput, 0)));
674 }
675 for (unsigned int i = 0; i < num_sinks; ++i) {
676 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
677 sinks[i].role, sinks[i].type)) ==
678 ::aidl::android::AudioPortDirection::INPUT;
679 aidlSinks.push_back(VALUE_OR_RETURN_STATUS(
680 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
681 sinks[i], isInput, 0)));
682 }
683 Cleanups cleanups;
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800684 auto existingPatchIt = halPatchId != 0 ? mPatches.find(halPatchId): mPatches.end();
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800685 AudioPatch aidlPatch;
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800686 if (existingPatchIt != mPatches.end()) {
687 aidlPatch = existingPatchIt->second;
688 aidlPatch.sourcePortConfigIds.clear();
689 aidlPatch.sinkPortConfigIds.clear();
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800690 }
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800691 ALOGD("%s: sources: %s, sinks: %s",
692 __func__, ::android::internal::ToString(aidlSources).c_str(),
693 ::android::internal::ToString(aidlSinks).c_str());
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800694 auto fillPortConfigs = [&](
Mikhail Naganov289468a2023-03-29 10:06:15 -0700695 const std::vector<AudioPortConfig>& configs,
696 const std::set<int32_t>& destinationPortIds,
697 std::vector<int32_t>* ids, std::set<int32_t>* portIds) -> status_t {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800698 for (const auto& s : configs) {
699 AudioPortConfig portConfig;
700 bool created = false;
Mikhail Naganov289468a2023-03-29 10:06:15 -0700701 RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(
702 s, destinationPortIds, &portConfig, &created));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800703 if (created) {
704 cleanups.emplace_front(this, &DeviceHalAidl::resetPortConfig, portConfig.id);
705 }
706 ids->push_back(portConfig.id);
Mikhail Naganov289468a2023-03-29 10:06:15 -0700707 if (portIds != nullptr) {
708 portIds->insert(portConfig.portId);
709 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800710 }
711 return OK;
712 };
Mikhail Naganov289468a2023-03-29 10:06:15 -0700713 // When looking up port configs, the destinationPortId is only used for mix ports.
714 // Thus, we process device port configs first, and look up the destination port ID from them.
715 bool sourceIsDevice = std::any_of(aidlSources.begin(), aidlSources.end(),
716 [](const auto& config) { return config.ext.getTag() == AudioPortExt::device; });
717 const std::vector<AudioPortConfig>& devicePortConfigs =
718 sourceIsDevice ? aidlSources : aidlSinks;
719 std::vector<int32_t>* devicePortConfigIds =
720 sourceIsDevice ? &aidlPatch.sourcePortConfigIds : &aidlPatch.sinkPortConfigIds;
721 const std::vector<AudioPortConfig>& mixPortConfigs =
722 sourceIsDevice ? aidlSinks : aidlSources;
723 std::vector<int32_t>* mixPortConfigIds =
724 sourceIsDevice ? &aidlPatch.sinkPortConfigIds : &aidlPatch.sourcePortConfigIds;
725 std::set<int32_t> devicePortIds;
726 RETURN_STATUS_IF_ERROR(fillPortConfigs(
727 devicePortConfigs, std::set<int32_t>(), devicePortConfigIds, &devicePortIds));
728 RETURN_STATUS_IF_ERROR(fillPortConfigs(
729 mixPortConfigs, devicePortIds, mixPortConfigIds, nullptr));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800730 if (existingPatchIt != mPatches.end()) {
731 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
732 mModule->setAudioPatch(aidlPatch, &aidlPatch)));
733 existingPatchIt->second = aidlPatch;
734 } else {
735 bool created = false;
736 RETURN_STATUS_IF_ERROR(findOrCreatePatch(aidlPatch, &aidlPatch, &created));
737 // Since no cleanup of the patch is needed, 'created' is ignored.
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800738 halPatchId = aidlPatch.id;
739 *patch = static_cast<audio_patch_handle_t>(halPatchId);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800740 }
741 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000742 return OK;
743}
744
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800745status_t DeviceHalAidl::releaseAudioPatch(audio_patch_handle_t patch) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800746 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000747 TIME_CHECK();
748 if (!mModule) return NO_INIT;
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800749 static_assert(AUDIO_PATCH_HANDLE_NONE == 0);
750 if (patch == AUDIO_PATCH_HANDLE_NONE) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800751 return BAD_VALUE;
752 }
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800753 int32_t halPatchId = static_cast<int32_t>(patch);
754 auto patchIt = mPatches.find(halPatchId);
755 if (patchIt == mPatches.end()) {
756 ALOGE("%s: patch with id %d not found", __func__, halPatchId);
757 return BAD_VALUE;
758 }
759 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->resetAudioPatch(halPatchId)));
760 mPatches.erase(patchIt);
Shunkai Yao51202502022-12-12 06:11:46 +0000761 return OK;
762}
763
Mikhail Naganove93a0862023-03-15 17:06:59 -0700764status_t DeviceHalAidl::getAudioPort(struct audio_port* port) {
765 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000766 TIME_CHECK();
767 if (!mModule) return NO_INIT;
Mikhail Naganove93a0862023-03-15 17:06:59 -0700768 if (port == nullptr) {
769 return BAD_VALUE;
770 }
771 audio_port_v7 portV7;
772 audio_populate_audio_port_v7(port, &portV7);
773 RETURN_STATUS_IF_ERROR(getAudioPort(&portV7));
774 return audio_populate_audio_port(&portV7, port) ? OK : BAD_VALUE;
775}
776
777status_t DeviceHalAidl::getAudioPort(struct audio_port_v7 *port) {
778 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
779 TIME_CHECK();
780 if (!mModule) return NO_INIT;
781 if (port == nullptr) {
782 return BAD_VALUE;
783 }
784 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(port->role, port->type)) ==
785 ::aidl::android::AudioPortDirection::INPUT;
786 auto aidlPort = VALUE_OR_RETURN_STATUS(
787 ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
788 if (aidlPort.ext.getTag() != AudioPortExt::device) {
789 ALOGE("%s: provided port is not a device port (module %s): %s",
790 __func__, mInstance.c_str(), aidlPort.toString().c_str());
791 return BAD_VALUE;
792 }
793 const auto& matchDevice = aidlPort.ext.get<AudioPortExt::device>().device;
794 // It seems that we don't have to call HAL since all valid ports have been added either
795 // during initialization, or while handling connection of an external device.
796 auto portsIt = findPort(matchDevice);
797 if (portsIt == mPorts.end()) {
798 ALOGE("%s: device port for device %s is not found in the module %s",
799 __func__, matchDevice.toString().c_str(), mInstance.c_str());
800 return BAD_VALUE;
801 }
802 const int32_t fwkId = aidlPort.id;
803 aidlPort = portsIt->second;
804 aidlPort.id = fwkId;
805 *port = VALUE_OR_RETURN_STATUS(::aidl::android::aidl2legacy_AudioPort_audio_port_v7(
806 aidlPort, isInput));
807 return OK;
808}
809
810status_t DeviceHalAidl::setAudioPortConfig(const struct audio_port_config* config) {
811 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
812 TIME_CHECK();
813 if (!mModule) return NO_INIT;
814 if (config == nullptr) {
815 return BAD_VALUE;
816 }
817 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
818 config->role, config->type)) == ::aidl::android::AudioPortDirection::INPUT;
819 AudioPortConfig requestedPortConfig = VALUE_OR_RETURN_STATUS(
820 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
821 *config, isInput, 0 /*portId*/));
822 AudioPortConfig portConfig;
823 bool created = false;
Mikhail Naganov289468a2023-03-29 10:06:15 -0700824 RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(
825 requestedPortConfig, std::set<int32_t>(), &portConfig, &created));
Shunkai Yao51202502022-12-12 06:11:46 +0000826 return OK;
827}
828
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800829MicrophoneInfoProvider::Info const* DeviceHalAidl::getMicrophoneInfo() {
830 if (mMicrophones.status == Microphones::Status::UNKNOWN) {
831 TIME_CHECK();
832 std::vector<MicrophoneInfo> aidlInfo;
833 status_t status = statusTFromBinderStatus(mModule->getMicrophones(&aidlInfo));
834 if (status == OK) {
835 mMicrophones.status = Microphones::Status::QUERIED;
836 mMicrophones.info = std::move(aidlInfo);
837 } else if (status == INVALID_OPERATION) {
838 mMicrophones.status = Microphones::Status::NOT_SUPPORTED;
839 } else {
840 ALOGE("%s: Unexpected status from 'IModule.getMicrophones': %d", __func__, status);
841 return {};
842 }
843 }
844 if (mMicrophones.status == Microphones::Status::QUERIED) {
845 return &mMicrophones.info;
846 }
847 return {}; // NOT_SUPPORTED
848}
849
Shunkai Yao51202502022-12-12 06:11:46 +0000850status_t DeviceHalAidl::getMicrophones(
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800851 std::vector<audio_microphone_characteristic_t>* microphones) {
852 if (!microphones) {
853 return BAD_VALUE;
854 }
Mikhail Naganov31d46652023-01-10 18:29:25 +0000855 TIME_CHECK();
856 if (!mModule) return NO_INIT;
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800857 auto staticInfo = getMicrophoneInfo();
858 if (!staticInfo) return INVALID_OPERATION;
859 std::vector<MicrophoneDynamicInfo> emptyDynamicInfo;
860 emptyDynamicInfo.reserve(staticInfo->size());
861 std::transform(staticInfo->begin(), staticInfo->end(), std::back_inserter(emptyDynamicInfo),
862 [](const auto& info) { return MicrophoneDynamicInfo{ .id = info.id }; });
863 *microphones = VALUE_OR_RETURN_STATUS(
864 ::aidl::android::convertContainers<std::vector<audio_microphone_characteristic_t>>(
865 *staticInfo, emptyDynamicInfo,
866 ::aidl::android::aidl2legacy_MicrophoneInfos_audio_microphone_characteristic_t)
867 );
Shunkai Yao51202502022-12-12 06:11:46 +0000868 return OK;
869}
870
Mikhail Naganov31d46652023-01-10 18:29:25 +0000871status_t DeviceHalAidl::addDeviceEffect(audio_port_handle_t device __unused,
872 sp<EffectHalInterface> effect) {
Shunkai Yao51202502022-12-12 06:11:46 +0000873 if (!effect) {
874 return BAD_VALUE;
875 }
Mikhail Naganov31d46652023-01-10 18:29:25 +0000876 TIME_CHECK();
877 if (!mModule) return NO_INIT;
878 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000879 return OK;
880}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000881status_t DeviceHalAidl::removeDeviceEffect(audio_port_handle_t device __unused,
Shunkai Yao51202502022-12-12 06:11:46 +0000882 sp<EffectHalInterface> effect) {
883 if (!effect) {
884 return BAD_VALUE;
885 }
Mikhail Naganov31d46652023-01-10 18:29:25 +0000886 TIME_CHECK();
887 if (!mModule) return NO_INIT;
888 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000889 return OK;
890}
891
892status_t DeviceHalAidl::getMmapPolicyInfos(
David Li9cf5e622023-03-21 00:51:10 +0800893 media::audio::common::AudioMMapPolicyType policyType,
894 std::vector<media::audio::common::AudioMMapPolicyInfo>* policyInfos) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000895 TIME_CHECK();
David Li9cf5e622023-03-21 00:51:10 +0800896 AudioMMapPolicyType mmapPolicyType =
897 VALUE_OR_RETURN_STATUS(cpp2ndk_Enum<AudioMMapPolicyType>(policyType));
898
899 std::vector<AudioMMapPolicyInfo> mmapPolicyInfos;
900
901 if (status_t status = statusTFromBinderStatus(
902 mModule->getMmapPolicyInfos(mmapPolicyType, &mmapPolicyInfos)); status != OK) {
903 return status;
904 }
905
906 *policyInfos = VALUE_OR_RETURN_STATUS(
907 convertContainer<std::vector<media::audio::common::AudioMMapPolicyInfo>>(
908 mmapPolicyInfos, ndk2cpp_AudioMMapPolicyInfo));
Shunkai Yao51202502022-12-12 06:11:46 +0000909 return OK;
910}
911
912int32_t DeviceHalAidl::getAAudioMixerBurstCount() {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000913 TIME_CHECK();
David Li9cf5e622023-03-21 00:51:10 +0800914 int32_t mixerBurstCount = 0;
915 if (mModule->getAAudioMixerBurstCount(&mixerBurstCount).isOk()) {
916 return mixerBurstCount;
917 }
918 return 0;
Shunkai Yao51202502022-12-12 06:11:46 +0000919}
920
921int32_t DeviceHalAidl::getAAudioHardwareBurstMinUsec() {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000922 TIME_CHECK();
David Li9cf5e622023-03-21 00:51:10 +0800923 int32_t hardwareBurstMinUsec = 0;
924 if (mModule->getAAudioHardwareBurstMinUsec(&hardwareBurstMinUsec).isOk()) {
925 return hardwareBurstMinUsec;
926 }
927 return 0;
Shunkai Yao51202502022-12-12 06:11:46 +0000928}
929
930error::Result<audio_hw_sync_t> DeviceHalAidl::getHwAvSync() {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000931 TIME_CHECK();
Mikhail Naganov08a62ab2023-03-14 17:11:51 -0700932 if (!mModule) return NO_INIT;
933 int32_t aidlHwAvSync;
934 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->generateHwAvSyncId(&aidlHwAvSync)));
935 return VALUE_OR_RETURN_STATUS(
936 ::aidl::android::aidl2legacy_int32_t_audio_hw_sync_t(aidlHwAvSync));
Shunkai Yao51202502022-12-12 06:11:46 +0000937}
938
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000939status_t DeviceHalAidl::dump(int fd, const Vector<String16>& args) {
940 TIME_CHECK();
941 if (!mModule) return NO_INIT;
942 return mModule->dump(fd, Args(args).args(), args.size());
David Li9cf5e622023-03-21 00:51:10 +0800943}
Shunkai Yao51202502022-12-12 06:11:46 +0000944
Mikhail Naganov3ac95c92023-04-12 13:14:30 -0700945int32_t DeviceHalAidl::supportsBluetoothVariableLatency(bool* supports) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000946 TIME_CHECK();
Mikhail Naganov3ac95c92023-04-12 13:14:30 -0700947 if (!mModule) return NO_INIT;
948 if (supports == nullptr) {
949 return BAD_VALUE;
950 }
951 return statusTFromBinderStatus(mModule->supportsVariableLatency(supports));
Shunkai Yao51202502022-12-12 06:11:46 +0000952}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000953
Mikhail Naganove93a0862023-03-15 17:06:59 -0700954status_t DeviceHalAidl::setConnectedState(const struct audio_port_v7 *port, bool connected) {
955 TIME_CHECK();
956 if (!mModule) return NO_INIT;
957 if (port == nullptr) {
958 return BAD_VALUE;
959 }
960 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(port->role, port->type)) ==
961 ::aidl::android::AudioPortDirection::INPUT;
962 AudioPort aidlPort = VALUE_OR_RETURN_STATUS(
963 ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
964 if (aidlPort.ext.getTag() != AudioPortExt::device) {
965 ALOGE("%s: provided port is not a device port (module %s): %s",
966 __func__, mInstance.c_str(), aidlPort.toString().c_str());
967 return BAD_VALUE;
968 }
969 if (connected) {
970 AudioDevice matchDevice = aidlPort.ext.get<AudioPortExt::device>().device;
971 // Reset the device address to find the "template" port.
972 matchDevice.address = AudioDeviceAddress::make<AudioDeviceAddress::id>();
973 auto portsIt = findPort(matchDevice);
974 if (portsIt == mPorts.end()) {
975 ALOGW("%s: device port for device %s is not found in the module %s",
976 __func__, matchDevice.toString().c_str(), mInstance.c_str());
977 return BAD_VALUE;
978 }
979 // Use the ID of the "template" port, use all the information from the provided port.
980 aidlPort.id = portsIt->first;
981 AudioPort connectedPort;
982 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->connectExternalDevice(
983 aidlPort, &connectedPort)));
984 const auto [it, inserted] = mPorts.insert(std::make_pair(connectedPort.id, connectedPort));
985 LOG_ALWAYS_FATAL_IF(!inserted,
986 "%s: module %s, duplicate port ID received from HAL: %s, existing port: %s",
987 __func__, mInstance.c_str(), connectedPort.toString().c_str(),
988 it->second.toString().c_str());
989 } else { // !connected
990 AudioDevice matchDevice = aidlPort.ext.get<AudioPortExt::device>().device;
991 auto portsIt = findPort(matchDevice);
992 if (portsIt == mPorts.end()) {
993 ALOGW("%s: device port for device %s is not found in the module %s",
994 __func__, matchDevice.toString().c_str(), mInstance.c_str());
995 return BAD_VALUE;
996 }
997 // Any streams opened on the external device must be closed by this time,
998 // thus we can clean up patches and port configs that were created for them.
999 resetUnusedPatchesAndPortConfigs();
1000 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->disconnectExternalDevice(
1001 portsIt->second.id)));
1002 mPorts.erase(portsIt);
1003 }
Mikhail Naganov289468a2023-03-29 10:06:15 -07001004 return updateRoutes();
Mikhail Naganove93a0862023-03-15 17:06:59 -07001005}
1006
1007status_t DeviceHalAidl::setSimulateDeviceConnections(bool enabled) {
1008 TIME_CHECK();
1009 if (!mModule) return NO_INIT;
1010 ModuleDebug debug{ .simulateDeviceConnections = enabled };
1011 status_t status = statusTFromBinderStatus(mModule->setModuleDebug(debug));
1012 // This is important to log as it affects HAL behavior.
1013 if (status == OK) {
1014 ALOGI("%s: set enabled: %d", __func__, enabled);
1015 } else {
1016 ALOGW("%s: set enabled to %d failed: %d", __func__, enabled, status);
1017 }
1018 return status;
1019}
1020
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001021bool DeviceHalAidl::audioDeviceMatches(const AudioDevice& device, const AudioPort& p) {
1022 if (p.ext.getTag() != AudioPortExt::Tag::device) return false;
1023 return p.ext.get<AudioPortExt::Tag::device>().device == device;
1024}
1025
1026bool DeviceHalAidl::audioDeviceMatches(const AudioDevice& device, const AudioPortConfig& p) {
1027 if (p.ext.getTag() != AudioPortExt::Tag::device) return false;
1028 if (device.type.type == AudioDeviceType::IN_DEFAULT) {
1029 return p.portId == mDefaultInputPortId;
1030 } else if (device.type.type == AudioDeviceType::OUT_DEFAULT) {
1031 return p.portId == mDefaultOutputPortId;
1032 }
1033 return p.ext.get<AudioPortExt::Tag::device>().device == device;
1034}
1035
David Lia8675d42023-03-30 21:08:06 +08001036status_t DeviceHalAidl::createOrUpdatePortConfig(
1037 const AudioPortConfig& requestedPortConfig, PortConfigs::iterator* result, bool* created) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001038 TIME_CHECK();
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001039 AudioPortConfig appliedPortConfig;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001040 bool applied = false;
1041 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPortConfig(
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001042 requestedPortConfig, &appliedPortConfig, &applied)));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001043 if (!applied) {
1044 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPortConfig(
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001045 appliedPortConfig, &appliedPortConfig, &applied)));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001046 if (!applied) {
1047 ALOGE("%s: module %s did not apply suggested config %s",
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001048 __func__, mInstance.c_str(), appliedPortConfig.toString().c_str());
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001049 return NO_INIT;
1050 }
1051 }
David Lia8675d42023-03-30 21:08:06 +08001052
1053 int32_t id = appliedPortConfig.id;
1054 if (requestedPortConfig.id != 0 && requestedPortConfig.id != id) {
1055 LOG_ALWAYS_FATAL("%s: requested port config id %d changed to %d", __func__,
1056 requestedPortConfig.id, id);
1057 }
1058
1059 auto [it, inserted] = mPortConfigs.insert_or_assign(std::move(id),
1060 std::move(appliedPortConfig));
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001061 *result = it;
David Lia8675d42023-03-30 21:08:06 +08001062 *created = inserted;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001063 return OK;
1064}
1065
1066status_t DeviceHalAidl::findOrCreatePatch(
1067 const AudioPatch& requestedPatch, AudioPatch* patch, bool* created) {
1068 std::set<int32_t> sourcePortConfigIds(requestedPatch.sourcePortConfigIds.begin(),
1069 requestedPatch.sourcePortConfigIds.end());
1070 std::set<int32_t> sinkPortConfigIds(requestedPatch.sinkPortConfigIds.begin(),
1071 requestedPatch.sinkPortConfigIds.end());
1072 return findOrCreatePatch(sourcePortConfigIds, sinkPortConfigIds, patch, created);
1073}
1074
1075status_t DeviceHalAidl::findOrCreatePatch(
1076 const std::set<int32_t>& sourcePortConfigIds, const std::set<int32_t>& sinkPortConfigIds,
1077 AudioPatch* patch, bool* created) {
1078 auto patchIt = findPatch(sourcePortConfigIds, sinkPortConfigIds);
1079 if (patchIt == mPatches.end()) {
1080 TIME_CHECK();
1081 AudioPatch requestedPatch, appliedPatch;
1082 requestedPatch.sourcePortConfigIds.insert(requestedPatch.sourcePortConfigIds.end(),
1083 sourcePortConfigIds.begin(), sourcePortConfigIds.end());
1084 requestedPatch.sinkPortConfigIds.insert(requestedPatch.sinkPortConfigIds.end(),
1085 sinkPortConfigIds.begin(), sinkPortConfigIds.end());
1086 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPatch(
1087 requestedPatch, &appliedPatch)));
1088 patchIt = mPatches.insert(mPatches.end(), std::make_pair(appliedPatch.id, appliedPatch));
1089 *created = true;
1090 } else {
1091 *created = false;
1092 }
1093 *patch = patchIt->second;
1094 return OK;
1095}
1096
jiabin9c07faf2023-04-26 22:00:44 +00001097status_t DeviceHalAidl::findOrCreatePortConfig(const AudioDevice& device, const AudioConfig* config,
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001098 AudioPortConfig* portConfig, bool* created) {
1099 auto portConfigIt = findPortConfig(device);
1100 if (portConfigIt == mPortConfigs.end()) {
1101 auto portsIt = findPort(device);
1102 if (portsIt == mPorts.end()) {
1103 ALOGE("%s: device port for device %s is not found in the module %s",
1104 __func__, device.toString().c_str(), mInstance.c_str());
1105 return BAD_VALUE;
1106 }
1107 AudioPortConfig requestedPortConfig;
1108 requestedPortConfig.portId = portsIt->first;
jiabin9c07faf2023-04-26 22:00:44 +00001109 if (config != nullptr) {
1110 setPortConfigFromConfig(&requestedPortConfig, *config);
1111 }
David Lia8675d42023-03-30 21:08:06 +08001112 RETURN_STATUS_IF_ERROR(createOrUpdatePortConfig(requestedPortConfig, &portConfigIt,
1113 created));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001114 } else {
1115 *created = false;
1116 }
1117 *portConfig = portConfigIt->second;
1118 return OK;
1119}
1120
1121status_t DeviceHalAidl::findOrCreatePortConfig(
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001122 const AudioConfig& config, const std::optional<AudioIoFlags>& flags, int32_t ioHandle,
Mikhail Naganov289468a2023-03-29 10:06:15 -07001123 AudioSource source, const std::set<int32_t>& destinationPortIds,
1124 AudioPortConfig* portConfig, bool* created) {
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001125 // These flags get removed one by one in this order when retrying port finding.
1126 static const std::vector<AudioInputFlags> kOptionalInputFlags{
1127 AudioInputFlags::FAST, AudioInputFlags::RAW };
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001128 auto portConfigIt = findPortConfig(config, flags, ioHandle);
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001129 if (portConfigIt == mPortConfigs.end() && flags.has_value()) {
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001130 auto optionalInputFlagsIt = kOptionalInputFlags.begin();
1131 AudioIoFlags matchFlags = flags.value();
Mikhail Naganov289468a2023-03-29 10:06:15 -07001132 auto portsIt = findPort(config, matchFlags, destinationPortIds);
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001133 while (portsIt == mPorts.end() && matchFlags.getTag() == AudioIoFlags::Tag::input
1134 && optionalInputFlagsIt != kOptionalInputFlags.end()) {
1135 if (!isBitPositionFlagSet(
1136 matchFlags.get<AudioIoFlags::Tag::input>(), *optionalInputFlagsIt)) {
1137 ++optionalInputFlagsIt;
1138 continue;
1139 }
1140 matchFlags.set<AudioIoFlags::Tag::input>(matchFlags.get<AudioIoFlags::Tag::input>() &
1141 ~makeBitPositionFlagMask(*optionalInputFlagsIt++));
Mikhail Naganov289468a2023-03-29 10:06:15 -07001142 portsIt = findPort(config, matchFlags, destinationPortIds);
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001143 ALOGI("%s: mix port for config %s, flags %s was not found in the module %s, "
1144 "retried with flags %s", __func__, config.toString().c_str(),
1145 flags.value().toString().c_str(), mInstance.c_str(),
1146 matchFlags.toString().c_str());
1147 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001148 if (portsIt == mPorts.end()) {
1149 ALOGE("%s: mix port for config %s, flags %s is not found in the module %s",
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001150 __func__, config.toString().c_str(), matchFlags.toString().c_str(),
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001151 mInstance.c_str());
1152 return BAD_VALUE;
1153 }
1154 AudioPortConfig requestedPortConfig;
1155 requestedPortConfig.portId = portsIt->first;
1156 setPortConfigFromConfig(&requestedPortConfig, config);
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001157 requestedPortConfig.ext = AudioPortMixExt{ .handle = ioHandle };
Mikhail Naganovd8d01f72023-03-09 16:24:40 -08001158 if (matchFlags.getTag() == AudioIoFlags::Tag::input
1159 && source != AudioSource::SYS_RESERVED_INVALID) {
1160 requestedPortConfig.ext.get<AudioPortExt::Tag::mix>().usecase =
1161 AudioPortMixExtUseCase::make<AudioPortMixExtUseCase::Tag::source>(source);
1162 }
David Lia8675d42023-03-30 21:08:06 +08001163 RETURN_STATUS_IF_ERROR(createOrUpdatePortConfig(requestedPortConfig, &portConfigIt,
1164 created));
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001165 } else if (!flags.has_value()) {
1166 ALOGW("%s: mix port config for %s, handle %d not found in the module %s, "
1167 "and was not created as flags are not specified",
1168 __func__, config.toString().c_str(), ioHandle, mInstance.c_str());
1169 return BAD_VALUE;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001170 } else {
David Lia8675d42023-03-30 21:08:06 +08001171 AudioPortConfig requestedPortConfig = portConfigIt->second;
1172 if (requestedPortConfig.ext.getTag() == AudioPortExt::Tag::mix) {
1173 AudioPortMixExt& mixExt = requestedPortConfig.ext.get<AudioPortExt::Tag::mix>();
1174 if (mixExt.usecase.getTag() == AudioPortMixExtUseCase::Tag::source &&
1175 source != AudioSource::SYS_RESERVED_INVALID) {
1176 mixExt.usecase.get<AudioPortMixExtUseCase::Tag::source>() = source;
1177 }
1178 }
1179
1180 if (requestedPortConfig != portConfigIt->second) {
1181 RETURN_STATUS_IF_ERROR(createOrUpdatePortConfig(requestedPortConfig, &portConfigIt,
1182 created));
1183 } else {
1184 *created = false;
1185 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001186 }
1187 *portConfig = portConfigIt->second;
1188 return OK;
1189}
1190
1191status_t DeviceHalAidl::findOrCreatePortConfig(
Mikhail Naganov289468a2023-03-29 10:06:15 -07001192 const AudioPortConfig& requestedPortConfig, const std::set<int32_t>& destinationPortIds,
1193 AudioPortConfig* portConfig, bool* created) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001194 using Tag = AudioPortExt::Tag;
1195 if (requestedPortConfig.ext.getTag() == Tag::mix) {
1196 if (const auto& p = requestedPortConfig;
1197 !p.sampleRate.has_value() || !p.channelMask.has_value() ||
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001198 !p.format.has_value()) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001199 ALOGW("%s: provided mix port config is not fully specified: %s",
1200 __func__, p.toString().c_str());
1201 return BAD_VALUE;
1202 }
1203 AudioConfig config;
1204 setConfigFromPortConfig(&config, requestedPortConfig);
Mikhail Naganovd8d01f72023-03-09 16:24:40 -08001205 AudioSource source = requestedPortConfig.ext.get<Tag::mix>().usecase.getTag() ==
1206 AudioPortMixExtUseCase::Tag::source ?
1207 requestedPortConfig.ext.get<Tag::mix>().usecase.
1208 get<AudioPortMixExtUseCase::Tag::source>() : AudioSource::SYS_RESERVED_INVALID;
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001209 return findOrCreatePortConfig(config, requestedPortConfig.flags,
Mikhail Naganov289468a2023-03-29 10:06:15 -07001210 requestedPortConfig.ext.get<Tag::mix>().handle, source, destinationPortIds,
1211 portConfig, created);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001212 } else if (requestedPortConfig.ext.getTag() == Tag::device) {
1213 return findOrCreatePortConfig(
jiabin9c07faf2023-04-26 22:00:44 +00001214 requestedPortConfig.ext.get<Tag::device>().device, nullptr /*config*/,
1215 portConfig, created);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001216 }
1217 ALOGW("%s: unsupported audio port config: %s",
1218 __func__, requestedPortConfig.toString().c_str());
1219 return BAD_VALUE;
1220}
1221
1222DeviceHalAidl::Patches::iterator DeviceHalAidl::findPatch(
1223 const std::set<int32_t>& sourcePortConfigIds, const std::set<int32_t>& sinkPortConfigIds) {
1224 return std::find_if(mPatches.begin(), mPatches.end(),
1225 [&](const auto& pair) {
1226 const auto& p = pair.second;
1227 std::set<int32_t> patchSrcs(
1228 p.sourcePortConfigIds.begin(), p.sourcePortConfigIds.end());
1229 std::set<int32_t> patchSinks(
1230 p.sinkPortConfigIds.begin(), p.sinkPortConfigIds.end());
1231 return sourcePortConfigIds == patchSrcs && sinkPortConfigIds == patchSinks; });
1232}
1233
1234DeviceHalAidl::Ports::iterator DeviceHalAidl::findPort(const AudioDevice& device) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001235 if (device.type.type == AudioDeviceType::IN_DEFAULT) {
1236 return mPorts.find(mDefaultInputPortId);
1237 } else if (device.type.type == AudioDeviceType::OUT_DEFAULT) {
1238 return mPorts.find(mDefaultOutputPortId);
1239 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001240 return std::find_if(mPorts.begin(), mPorts.end(),
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001241 [&](const auto& pair) { return audioDeviceMatches(device, pair.second); });
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001242}
1243
1244DeviceHalAidl::Ports::iterator DeviceHalAidl::findPort(
Mikhail Naganov289468a2023-03-29 10:06:15 -07001245 const AudioConfig& config, const AudioIoFlags& flags,
1246 const std::set<int32_t>& destinationPortIds) {
Mikhail Naganove93a0862023-03-15 17:06:59 -07001247 auto belongsToProfile = [&config](const AudioProfile& prof) {
1248 return (isDefaultAudioFormat(config.base.format) || prof.format == config.base.format) &&
1249 (config.base.channelMask.getTag() == AudioChannelLayout::none ||
1250 std::find(prof.channelMasks.begin(), prof.channelMasks.end(),
1251 config.base.channelMask) != prof.channelMasks.end()) &&
1252 (config.base.sampleRate == 0 ||
1253 std::find(prof.sampleRates.begin(), prof.sampleRates.end(),
1254 config.base.sampleRate) != prof.sampleRates.end());
1255 };
jiabin9c07faf2023-04-26 22:00:44 +00001256 static const std::vector<AudioOutputFlags> kOptionalOutputFlags{AudioOutputFlags::BIT_PERFECT};
1257 int optionalFlags = 0;
1258 auto flagMatches = [&flags, &optionalFlags](const AudioIoFlags& portFlags) {
1259 // Ports should be able to match if the optional flags are not requested.
1260 return portFlags == flags ||
1261 (portFlags.getTag() == AudioIoFlags::Tag::output &&
1262 AudioIoFlags::make<AudioIoFlags::Tag::output>(
1263 portFlags.get<AudioIoFlags::Tag::output>() &
1264 ~optionalFlags) == flags);
1265 };
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001266 auto matcher = [&](const auto& pair) {
1267 const auto& p = pair.second;
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001268 return p.ext.getTag() == AudioPortExt::Tag::mix &&
jiabin9c07faf2023-04-26 22:00:44 +00001269 flagMatches(p.flags) &&
Mikhail Naganov289468a2023-03-29 10:06:15 -07001270 (destinationPortIds.empty() ||
1271 std::any_of(destinationPortIds.begin(), destinationPortIds.end(),
1272 [&](const int32_t destId) { return mRoutingMatrix.count(
1273 std::make_pair(p.id, destId)) != 0; })) &&
Mikhail Naganove93a0862023-03-15 17:06:59 -07001274 (p.profiles.empty() ||
1275 std::find_if(p.profiles.begin(), p.profiles.end(), belongsToProfile) !=
1276 p.profiles.end()); };
jiabin9c07faf2023-04-26 22:00:44 +00001277 auto result = std::find_if(mPorts.begin(), mPorts.end(), matcher);
1278 if (result == mPorts.end() && flags.getTag() == AudioIoFlags::Tag::output) {
1279 auto optionalOutputFlagsIt = kOptionalOutputFlags.begin();
1280 while (result == mPorts.end() && optionalOutputFlagsIt != kOptionalOutputFlags.end()) {
1281 if (isBitPositionFlagSet(
1282 flags.get<AudioIoFlags::Tag::output>(), *optionalOutputFlagsIt)) {
1283 // If the flag is set by the request, it must be matched.
1284 ++optionalOutputFlagsIt;
1285 continue;
1286 }
1287 optionalFlags |= makeBitPositionFlagMask(*optionalOutputFlagsIt++);
1288 result = std::find_if(mPorts.begin(), mPorts.end(), matcher);
1289 ALOGI("%s: port for config %s, flags %s was not found in the module %s, "
1290 "retried with excluding optional flags %#x", __func__, config.toString().c_str(),
1291 flags.toString().c_str(), mInstance.c_str(), optionalFlags);
1292 }
1293 }
1294 return result;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001295}
1296
1297DeviceHalAidl::PortConfigs::iterator DeviceHalAidl::findPortConfig(const AudioDevice& device) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001298 return std::find_if(mPortConfigs.begin(), mPortConfigs.end(),
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001299 [&](const auto& pair) { return audioDeviceMatches(device, pair.second); });
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001300}
1301
1302DeviceHalAidl::PortConfigs::iterator DeviceHalAidl::findPortConfig(
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001303 const AudioConfig& config, const std::optional<AudioIoFlags>& flags, int32_t ioHandle) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001304 using Tag = AudioPortExt::Tag;
1305 return std::find_if(mPortConfigs.begin(), mPortConfigs.end(),
1306 [&](const auto& pair) {
1307 const auto& p = pair.second;
1308 LOG_ALWAYS_FATAL_IF(p.ext.getTag() == Tag::mix &&
1309 !p.sampleRate.has_value() || !p.channelMask.has_value() ||
1310 !p.format.has_value() || !p.flags.has_value(),
1311 "%s: stored mix port config is not fully specified: %s",
1312 __func__, p.toString().c_str());
1313 return p.ext.getTag() == Tag::mix &&
1314 isConfigEqualToPortConfig(config, p) &&
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001315 (!flags.has_value() || p.flags.value() == flags.value()) &&
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001316 p.ext.template get<Tag::mix>().handle == ioHandle; });
1317}
Mikhail Naganove93a0862023-03-15 17:06:59 -07001318
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001319void DeviceHalAidl::resetPatch(int32_t patchId) {
1320 if (auto it = mPatches.find(patchId); it != mPatches.end()) {
1321 mPatches.erase(it);
1322 TIME_CHECK();
1323 if (ndk::ScopedAStatus status = mModule->resetAudioPatch(patchId); !status.isOk()) {
1324 ALOGE("%s: error while resetting patch %d: %s",
1325 __func__, patchId, status.getDescription().c_str());
1326 }
1327 return;
1328 }
1329 ALOGE("%s: patch id %d not found", __func__, patchId);
1330}
1331
1332void DeviceHalAidl::resetPortConfig(int32_t portConfigId) {
1333 if (auto it = mPortConfigs.find(portConfigId); it != mPortConfigs.end()) {
1334 mPortConfigs.erase(it);
1335 TIME_CHECK();
1336 if (ndk::ScopedAStatus status = mModule->resetAudioPortConfig(portConfigId);
1337 !status.isOk()) {
1338 ALOGE("%s: error while resetting port config %d: %s",
1339 __func__, portConfigId, status.getDescription().c_str());
1340 }
1341 return;
1342 }
1343 ALOGE("%s: port config id %d not found", __func__, portConfigId);
1344}
1345
Mikhail Naganove93a0862023-03-15 17:06:59 -07001346void DeviceHalAidl::resetUnusedPatches() {
1347 // Since patches can be created independently of streams via 'createAudioPatch',
1348 // here we only clean up patches for released streams.
1349 for (auto it = mStreams.begin(); it != mStreams.end(); ) {
1350 if (auto streamSp = it->first.promote(); streamSp) {
1351 ++it;
1352 } else {
1353 resetPatch(it->second);
1354 it = mStreams.erase(it);
1355 }
1356 }
1357}
1358
1359void DeviceHalAidl::resetUnusedPatchesAndPortConfigs() {
1360 resetUnusedPatches();
1361 resetUnusedPortConfigs();
1362}
1363
1364void DeviceHalAidl::resetUnusedPortConfigs() {
1365 // The assumption is that port configs are used to create patches
1366 // (or to open streams, but that involves creation of patches, too). Thus,
1367 // orphaned port configs can and should be reset.
1368 std::set<int32_t> portConfigIds;
1369 std::transform(mPortConfigs.begin(), mPortConfigs.end(),
1370 std::inserter(portConfigIds, portConfigIds.end()),
1371 [](const auto& pcPair) { return pcPair.first; });
1372 for (const auto& p : mPatches) {
1373 for (int32_t id : p.second.sourcePortConfigIds) portConfigIds.erase(id);
1374 for (int32_t id : p.second.sinkPortConfigIds) portConfigIds.erase(id);
1375 }
jiabin9c07faf2023-04-26 22:00:44 +00001376 for (int32_t id : mInitialPortConfigIds) {
1377 portConfigIds.erase(id);
1378 }
Mikhail Naganove93a0862023-03-15 17:06:59 -07001379 for (int32_t id : portConfigIds) resetPortConfig(id);
1380}
1381
Mikhail Naganov289468a2023-03-29 10:06:15 -07001382status_t DeviceHalAidl::updateRoutes() {
1383 TIME_CHECK();
1384 std::vector<AudioRoute> routes;
1385 RETURN_STATUS_IF_ERROR(
1386 statusTFromBinderStatus(mModule->getAudioRoutes(&routes)));
1387 ALOGW_IF(routes.empty(), "%s: module %s returned an empty list of audio routes",
1388 __func__, mInstance.c_str());
1389 mRoutingMatrix.clear();
1390 for (const auto& r : routes) {
1391 for (auto portId : r.sourcePortIds) {
1392 mRoutingMatrix.emplace(r.sinkPortId, portId);
1393 mRoutingMatrix.emplace(portId, r.sinkPortId);
1394 }
1395 }
1396 return OK;
1397}
1398
Mikhail Naganovdfd594e2023-02-08 16:59:41 -08001399void DeviceHalAidl::clearCallbacks(void* cookie) {
1400 std::lock_guard l(mLock);
1401 mCallbacks.erase(cookie);
1402}
1403
1404sp<StreamOutHalInterfaceCallback> DeviceHalAidl::getStreamOutCallback(void* cookie) {
1405 return getCallbackImpl(cookie, &Callbacks::out);
1406}
1407
1408void DeviceHalAidl::setStreamOutCallback(
1409 void* cookie, const sp<StreamOutHalInterfaceCallback>& cb) {
1410 setCallbackImpl(cookie, &Callbacks::out, cb);
1411}
1412
1413sp<StreamOutHalInterfaceEventCallback> DeviceHalAidl::getStreamOutEventCallback(
1414 void* cookie) {
1415 return getCallbackImpl(cookie, &Callbacks::event);
1416}
1417
1418void DeviceHalAidl::setStreamOutEventCallback(
1419 void* cookie, const sp<StreamOutHalInterfaceEventCallback>& cb) {
1420 setCallbackImpl(cookie, &Callbacks::event, cb);
1421}
1422
1423sp<StreamOutHalInterfaceLatencyModeCallback> DeviceHalAidl::getStreamOutLatencyModeCallback(
1424 void* cookie) {
1425 return getCallbackImpl(cookie, &Callbacks::latency);
1426}
1427
1428void DeviceHalAidl::setStreamOutLatencyModeCallback(
1429 void* cookie, const sp<StreamOutHalInterfaceLatencyModeCallback>& cb) {
1430 setCallbackImpl(cookie, &Callbacks::latency, cb);
1431}
1432
1433template<class C>
1434sp<C> DeviceHalAidl::getCallbackImpl(void* cookie, wp<C> DeviceHalAidl::Callbacks::* field) {
1435 std::lock_guard l(mLock);
1436 if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
1437 return ((it->second).*field).promote();
1438 }
1439 return nullptr;
1440}
1441template<class C>
1442void DeviceHalAidl::setCallbackImpl(
1443 void* cookie, wp<C> DeviceHalAidl::Callbacks::* field, const sp<C>& cb) {
1444 std::lock_guard l(mLock);
1445 if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
1446 (it->second).*field = cb;
1447 }
1448}
1449
Mikhail Naganov31d46652023-01-10 18:29:25 +00001450} // namespace android