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