blob: 62533cbad211732cc0bae9a82cf22436b6245856 [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 Naganovf56ce782023-01-25 11:29:11 -080039using aidl::android::media::audio::common::AudioConfig;
40using aidl::android::media::audio::common::AudioDevice;
David Li9cf5e622023-03-21 00:51:10 +080041using aidl::android::media::audio::common::AudioDeviceAddress;
Mikhail Naganov8bd806e2023-01-30 12:33:18 -080042using aidl::android::media::audio::common::AudioDeviceType;
43using aidl::android::media::audio::common::AudioInputFlags;
Mikhail Naganovf56ce782023-01-25 11:29:11 -080044using aidl::android::media::audio::common::AudioIoFlags;
Mikhail Naganovb0c55252023-02-08 16:59:41 -080045using aidl::android::media::audio::common::AudioLatencyMode;
David Li9cf5e622023-03-21 00:51:10 +080046using aidl::android::media::audio::common::AudioMMapPolicy;
47using aidl::android::media::audio::common::AudioMMapPolicyInfo;
48using aidl::android::media::audio::common::AudioMMapPolicyType;
Mikhail Naganovfab697c2023-01-11 19:33:13 +000049using aidl::android::media::audio::common::AudioMode;
Mikhail Naganovf56ce782023-01-25 11:29:11 -080050using aidl::android::media::audio::common::AudioOutputFlags;
51using aidl::android::media::audio::common::AudioPort;
52using aidl::android::media::audio::common::AudioPortConfig;
Mikhail Naganov8bd806e2023-01-30 12:33:18 -080053using aidl::android::media::audio::common::AudioPortDeviceExt;
David Li9cf5e622023-03-21 00:51:10 +080054using aidl::android::media::audio::common::AudioPortExt;
Mikhail Naganov1a44bc62023-02-16 17:35:06 -080055using aidl::android::media::audio::common::AudioPortMixExt;
Mikhail Naganovd8d01f72023-03-09 16:24:40 -080056using aidl::android::media::audio::common::AudioPortMixExtUseCase;
Mikhail Naganovf56ce782023-01-25 11:29:11 -080057using aidl::android::media::audio::common::AudioSource;
Mikhail Naganovfab697c2023-01-11 19:33:13 +000058using aidl::android::media::audio::common::Float;
David Li9cf5e622023-03-21 00:51:10 +080059using aidl::android::media::audio::common::Int;
60using aidl::android::media::audio::common::MicrophoneDynamicInfo;
61using aidl::android::media::audio::common::MicrophoneInfo;
Mikhail Naganov6352e822023-03-09 18:22:36 -080062using aidl::android::hardware::audio::common::getFrameSizeInBytes;
63using aidl::android::hardware::audio::common::isBitPositionFlagSet;
64using aidl::android::hardware::audio::common::makeBitPositionFlagMask;
Mikhail Naganovf56ce782023-01-25 11:29:11 -080065using aidl::android::hardware::audio::common::RecordTrackMetadata;
66using aidl::android::hardware::audio::core::AudioPatch;
Mikhail Naganovfab697c2023-01-11 19:33:13 +000067using aidl::android::hardware::audio::core::IModule;
68using aidl::android::hardware::audio::core::ITelephony;
69using aidl::android::hardware::audio::core::StreamDescriptor;
Mikhail Naganov31d46652023-01-10 18:29:25 +000070
71namespace android {
72
Mikhail Naganovf56ce782023-01-25 11:29:11 -080073namespace {
74
75bool isConfigEqualToPortConfig(const AudioConfig& config, const AudioPortConfig& portConfig) {
76 return portConfig.sampleRate.value().value == config.base.sampleRate &&
77 portConfig.channelMask.value() == config.base.channelMask &&
78 portConfig.format.value() == config.base.format;
79}
80
81void setConfigFromPortConfig(AudioConfig* config, const AudioPortConfig& portConfig) {
82 config->base.sampleRate = portConfig.sampleRate.value().value;
83 config->base.channelMask = portConfig.channelMask.value();
84 config->base.format = portConfig.format.value();
85}
86
87void setPortConfigFromConfig(AudioPortConfig* portConfig, const AudioConfig& config) {
88 portConfig->sampleRate = Int{ .value = config.base.sampleRate };
89 portConfig->channelMask = config.base.channelMask;
90 portConfig->format = config.base.format;
91}
92
David Li9cf5e622023-03-21 00:51:10 +080093template<typename OutEnum, typename OutEnumRange, typename InEnum>
94ConversionResult<OutEnum> convertEnum(const OutEnumRange& range, InEnum e) {
95 using InIntType = std::underlying_type_t<InEnum>;
96 static_assert(std::is_same_v<InIntType, std::underlying_type_t<OutEnum>>);
97
98 InIntType inEnumIndex = static_cast<InIntType>(e);
99 OutEnum outEnum = static_cast<OutEnum>(inEnumIndex);
100 if (std::find(range.begin(), range.end(), outEnum) == range.end()) {
101 return ::android::base::unexpected(BAD_VALUE);
102 }
103 return outEnum;
104}
105
106template<typename NdkEnum, typename CppEnum>
107ConversionResult<NdkEnum> cpp2ndk_Enum(CppEnum e) {
108 return convertEnum<NdkEnum>(::ndk::enum_range<NdkEnum>(), e);
109}
110
111template<typename CppEnum, typename NdkEnum>
112ConversionResult<CppEnum> ndk2cpp_Enum(NdkEnum e) {
113 return convertEnum<CppEnum>(::android::enum_range<CppEnum>(), e);
114}
115
116ConversionResult<android::media::audio::common::AudioDeviceAddress>
117ndk2cpp_AudioDeviceAddress(const AudioDeviceAddress& ndk) {
118 using CppTag = android::media::audio::common::AudioDeviceAddress::Tag;
119 using NdkTag = AudioDeviceAddress::Tag;
120
121 CppTag cppTag = VALUE_OR_RETURN(ndk2cpp_Enum<CppTag>(ndk.getTag()));
122
123 switch (cppTag) {
124 case CppTag::id:
125 return android::media::audio::common::AudioDeviceAddress::make<CppTag::id>(
126 ndk.get<NdkTag::id>());
127 case CppTag::mac:
128 return android::media::audio::common::AudioDeviceAddress::make<CppTag::mac>(
129 ndk.get<NdkTag::mac>());
130 case CppTag::ipv4:
131 return android::media::audio::common::AudioDeviceAddress::make<CppTag::ipv4>(
132 ndk.get<NdkTag::ipv4>());
133 case CppTag::ipv6:
134 return android::media::audio::common::AudioDeviceAddress::make<CppTag::ipv6>(
135 ndk.get<NdkTag::ipv6>());
136 case CppTag::alsa:
137 return android::media::audio::common::AudioDeviceAddress::make<CppTag::alsa>(
138 ndk.get<NdkTag::alsa>());
139 }
140
141 return ::android::base::unexpected(BAD_VALUE);
142}
143
144ConversionResult<media::audio::common::AudioDevice> ndk2cpp_AudioDevice(const AudioDevice& ndk) {
145 media::audio::common::AudioDevice cpp;
146 cpp.type.type = VALUE_OR_RETURN(
147 ndk2cpp_Enum<media::audio::common::AudioDeviceType>(ndk.type.type));
148 cpp.type.connection = ndk.type.connection;
149 cpp.address = VALUE_OR_RETURN(ndk2cpp_AudioDeviceAddress(ndk.address));
150 return cpp;
151}
152
153ConversionResult<media::audio::common::AudioMMapPolicyInfo>
154ndk2cpp_AudioMMapPolicyInfo(const AudioMMapPolicyInfo& ndk) {
155 media::audio::common::AudioMMapPolicyInfo cpp;
156 cpp.device = VALUE_OR_RETURN(ndk2cpp_AudioDevice(ndk.device));
157 cpp.mmapPolicy = VALUE_OR_RETURN(
158 ndk2cpp_Enum<media::audio::common::AudioMMapPolicy>(ndk.mmapPolicy));
159 return cpp;
160}
161
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800162} // namespace
163
Mikhail Naganov31d46652023-01-10 18:29:25 +0000164status_t DeviceHalAidl::getSupportedDevices(uint32_t*) {
165 // Obsolete.
166 return INVALID_OPERATION;
Shunkai Yao51202502022-12-12 06:11:46 +0000167}
168
169status_t DeviceHalAidl::initCheck() {
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800170 TIME_CHECK();
Mikhail Naganov31d46652023-01-10 18:29:25 +0000171 if (mModule == nullptr) return NO_INIT;
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800172 std::vector<AudioPort> ports;
173 RETURN_STATUS_IF_ERROR(
174 statusTFromBinderStatus(mModule->getAudioPorts(&ports)));
175 ALOGW_IF(ports.empty(), "%s: module %s returned an empty list of audio ports",
176 __func__, mInstance.c_str());
177 std::transform(ports.begin(), ports.end(), std::inserter(mPorts, mPorts.end()),
178 [](const auto& p) { return std::make_pair(p.id, p); });
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800179 mDefaultInputPortId = mDefaultOutputPortId = -1;
180 const int defaultDeviceFlag = 1 << AudioPortDeviceExt::FLAG_INDEX_DEFAULT_DEVICE;
181 for (const auto& pair : mPorts) {
182 const auto& p = pair.second;
183 if (p.ext.getTag() == AudioPortExt::Tag::device &&
184 (p.ext.get<AudioPortExt::Tag::device>().flags & defaultDeviceFlag) != 0) {
185 if (p.flags.getTag() == AudioIoFlags::Tag::input) {
186 mDefaultInputPortId = p.id;
187 } else if (p.flags.getTag() == AudioIoFlags::Tag::output) {
188 mDefaultOutputPortId = p.id;
189 }
190 }
191 }
192 ALOGI("%s: module %s default port ids: input %d, output %d",
193 __func__, mInstance.c_str(), mDefaultInputPortId, mDefaultOutputPortId);
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800194 std::vector<AudioPortConfig> portConfigs;
195 RETURN_STATUS_IF_ERROR(
196 statusTFromBinderStatus(mModule->getAudioPortConfigs(&portConfigs))); // OK if empty
197 std::transform(portConfigs.begin(), portConfigs.end(),
198 std::inserter(mPortConfigs, mPortConfigs.end()),
199 [](const auto& p) { return std::make_pair(p.id, p); });
200 std::vector<AudioPatch> patches;
201 RETURN_STATUS_IF_ERROR(
202 statusTFromBinderStatus(mModule->getAudioPatches(&patches))); // OK if empty
203 std::transform(patches.begin(), patches.end(),
204 std::inserter(mPatches, mPatches.end()),
205 [](const auto& p) { return std::make_pair(p.id, p); });
Shunkai Yao51202502022-12-12 06:11:46 +0000206 return OK;
207}
208
209status_t DeviceHalAidl::setVoiceVolume(float volume) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000210 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000211 if (!mModule) return NO_INIT;
212 std::shared_ptr<ITelephony> telephony;
213 if (ndk::ScopedAStatus status = mModule->getTelephony(&telephony);
214 status.isOk() && telephony != nullptr) {
215 ITelephony::TelecomConfig inConfig{ .voiceVolume = Float{volume} }, outConfig;
216 RETURN_STATUS_IF_ERROR(
217 statusTFromBinderStatus(telephony->setTelecomConfig(inConfig, &outConfig)));
218 ALOGW_IF(outConfig.voiceVolume.has_value() && volume != outConfig.voiceVolume.value().value,
219 "%s: the resulting voice volume %f is not the same as requested %f",
220 __func__, outConfig.voiceVolume.value().value, volume);
221 }
222 return INVALID_OPERATION;
Shunkai Yao51202502022-12-12 06:11:46 +0000223}
224
225status_t DeviceHalAidl::setMasterVolume(float volume) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000226 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000227 if (!mModule) return NO_INIT;
228 return statusTFromBinderStatus(mModule->setMasterVolume(volume));
Shunkai Yao51202502022-12-12 06:11:46 +0000229}
230
231status_t DeviceHalAidl::getMasterVolume(float *volume) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000232 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000233 if (!mModule) return NO_INIT;
234 return statusTFromBinderStatus(mModule->getMasterVolume(volume));
Shunkai Yao51202502022-12-12 06:11:46 +0000235}
236
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000237status_t DeviceHalAidl::setMode(audio_mode_t mode) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000238 TIME_CHECK();
239 if (!mModule) return NO_INIT;
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000240 AudioMode audioMode = VALUE_OR_FATAL(::aidl::android::legacy2aidl_audio_mode_t_AudioMode(mode));
241 std::shared_ptr<ITelephony> telephony;
242 if (ndk::ScopedAStatus status = mModule->getTelephony(&telephony);
243 status.isOk() && telephony != nullptr) {
244 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(telephony->switchAudioMode(audioMode)));
245 }
246 return statusTFromBinderStatus(mModule->updateAudioMode(audioMode));
Shunkai Yao51202502022-12-12 06:11:46 +0000247}
248
249status_t DeviceHalAidl::setMicMute(bool state) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000250 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000251 if (!mModule) return NO_INIT;
252 return statusTFromBinderStatus(mModule->setMicMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000253}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000254
Shunkai Yao51202502022-12-12 06:11:46 +0000255status_t DeviceHalAidl::getMicMute(bool *state) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000256 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000257 if (!mModule) return NO_INIT;
258 return statusTFromBinderStatus(mModule->getMicMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000259}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000260
Shunkai Yao51202502022-12-12 06:11:46 +0000261status_t DeviceHalAidl::setMasterMute(bool state) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000262 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000263 if (!mModule) return NO_INIT;
264 return statusTFromBinderStatus(mModule->setMasterMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000265}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000266
Shunkai Yao51202502022-12-12 06:11:46 +0000267status_t DeviceHalAidl::getMasterMute(bool *state) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000268 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000269 if (!mModule) return NO_INIT;
270 return statusTFromBinderStatus(mModule->getMasterMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000271}
272
Mikhail Naganov31d46652023-01-10 18:29:25 +0000273status_t DeviceHalAidl::setParameters(const String8& kvPairs __unused) {
274 TIME_CHECK();
275 if (!mModule) return NO_INIT;
276 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000277 return OK;
278}
279
Mikhail Naganov31d46652023-01-10 18:29:25 +0000280status_t DeviceHalAidl::getParameters(const String8& keys __unused, String8 *values) {
281 TIME_CHECK();
282 values->clear();
283 if (!mModule) return NO_INIT;
284 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000285 return OK;
286}
287
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800288namespace {
289
290class Cleanup {
291 public:
292 typedef void (DeviceHalAidl::*Cleaner)(int32_t);
293
294 Cleanup(DeviceHalAidl* device, Cleaner cleaner, int32_t id) :
295 mDevice(device), mCleaner(cleaner), mId(id) {}
296 ~Cleanup() { clean(); }
297 void clean() {
298 if (mDevice != nullptr) (mDevice->*mCleaner)(mId);
299 disarm();
300 }
301 void disarm() { mDevice = nullptr; }
302
303 private:
304 DeviceHalAidl* mDevice;
305 const Cleaner mCleaner;
306 const int32_t mId;
307};
308
309} // namespace
310
311// Since the order of container elements destruction is unspecified,
312// ensure that cleanups are performed from the most recent one and upwards.
313// This is the same as if there were individual Cleanup instances on the stack,
314// however the bonus is that we can disarm all of them with just one statement.
315class DeviceHalAidl::Cleanups : public std::forward_list<Cleanup> {
316 public:
317 ~Cleanups() { for (auto& c : *this) c.clean(); }
318 void disarmAll() { for (auto& c : *this) c.disarm(); }
319};
320
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800321status_t DeviceHalAidl::getInputBufferSize(const struct audio_config* config, size_t* size) {
322 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
323 if (size == nullptr) return BAD_VALUE;
324 TIME_CHECK();
325 if (!mModule) return NO_INIT;
326 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
327 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, true /*isInput*/));
328 AudioDevice aidlDevice;
329 aidlDevice.type.type = AudioDeviceType::IN_DEFAULT;
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800330 AudioSource aidlSource = AudioSource::DEFAULT;
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800331 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::input>(0);
332 AudioPortConfig mixPortConfig;
333 Cleanups cleanups;
334 audio_config writableConfig = *config;
335 int32_t nominalLatency;
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800336 RETURN_STATUS_IF_ERROR(prepareToOpenStream(0 /*handle*/, aidlDevice, aidlFlags, aidlSource,
337 &writableConfig, &cleanups, &aidlConfig, &mixPortConfig, &nominalLatency));
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800338 *size = aidlConfig.frameCount *
339 getFrameSizeInBytes(aidlConfig.base.format, aidlConfig.base.channelMask);
340 // Do not disarm cleanups to release temporary port configs.
341 return OK;
342}
343
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800344status_t DeviceHalAidl::prepareToOpenStream(
345 int32_t aidlHandle, const AudioDevice& aidlDevice, const AudioIoFlags& aidlFlags,
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800346 AudioSource aidlSource, struct audio_config* config,
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800347 Cleanups* cleanups, AudioConfig* aidlConfig, AudioPortConfig* mixPortConfig,
348 int32_t* nominalLatency) {
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800349 const bool isInput = aidlFlags.getTag() == AudioIoFlags::Tag::input;
350 // Find / create AudioPortConfigs for the device port and the mix port,
351 // then find / create a patch between them, and open a stream on the mix port.
352 AudioPortConfig devicePortConfig;
353 bool created = false;
354 RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(aidlDevice, &devicePortConfig, &created));
355 if (created) {
356 cleanups->emplace_front(this, &DeviceHalAidl::resetPortConfig, devicePortConfig.id);
357 }
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800358 RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(*aidlConfig, aidlFlags, aidlHandle, aidlSource,
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800359 mixPortConfig, &created));
360 if (created) {
361 cleanups->emplace_front(this, &DeviceHalAidl::resetPortConfig, mixPortConfig->id);
362 }
363 setConfigFromPortConfig(aidlConfig, *mixPortConfig);
364 AudioPatch patch;
365 if (isInput) {
366 RETURN_STATUS_IF_ERROR(findOrCreatePatch(
367 {devicePortConfig.id}, {mixPortConfig->id}, &patch, &created));
368 } else {
369 RETURN_STATUS_IF_ERROR(findOrCreatePatch(
370 {mixPortConfig->id}, {devicePortConfig.id}, &patch, &created));
371 }
372 if (created) {
373 cleanups->emplace_front(this, &DeviceHalAidl::resetPatch, patch.id);
374 }
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800375 *nominalLatency = patch.latenciesMs[0];
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800376 if (aidlConfig->frameCount <= 0) {
377 aidlConfig->frameCount = patch.minimumStreamBufferSizeFrames;
378 }
379 *config = VALUE_OR_RETURN_STATUS(
380 ::aidl::android::aidl2legacy_AudioConfig_audio_config_t(*aidlConfig, isInput));
381 return OK;
382}
383
Mikhail Naganovb0c55252023-02-08 16:59:41 -0800384namespace {
385
386class StreamCallbackBase {
387 protected:
388 explicit StreamCallbackBase(const sp<CallbackBroker>& broker) : mBroker(broker) {}
389 public:
390 void* getCookie() const { return mCookie; }
391 void setCookie(void* cookie) { mCookie = cookie; }
392 sp<CallbackBroker> getBroker() const {
393 if (void* cookie = mCookie; cookie != nullptr) return mBroker.promote();
394 return nullptr;
395 }
396 private:
397 const wp<CallbackBroker> mBroker;
398 std::atomic<void*> mCookie;
399};
400
401template<class C>
402class StreamCallbackBaseHelper {
403 protected:
404 explicit StreamCallbackBaseHelper(const StreamCallbackBase& base) : mBase(base) {}
405 sp<C> getCb(const sp<CallbackBroker>& broker, void* cookie);
406 using CbRef = const sp<C>&;
407 ndk::ScopedAStatus runCb(const std::function<void(CbRef cb)>& f) {
408 if (auto cb = getCb(mBase.getBroker(), mBase.getCookie()); cb != nullptr) f(cb);
409 return ndk::ScopedAStatus::ok();
410 }
411 private:
412 const StreamCallbackBase& mBase;
413};
414
415template<>
416sp<StreamOutHalInterfaceCallback> StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>::getCb(
417 const sp<CallbackBroker>& broker, void* cookie) {
418 if (broker != nullptr) return broker->getStreamOutCallback(cookie);
419 return nullptr;
420}
421
422template<>
423sp<StreamOutHalInterfaceEventCallback>
424StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>::getCb(
425 const sp<CallbackBroker>& broker, void* cookie) {
426 if (broker != nullptr) return broker->getStreamOutEventCallback(cookie);
427 return nullptr;
428}
429
430template<>
431sp<StreamOutHalInterfaceLatencyModeCallback>
432StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>::getCb(
433 const sp<CallbackBroker>& broker, void* cookie) {
434 if (broker != nullptr) return broker->getStreamOutLatencyModeCallback(cookie);
435 return nullptr;
436}
437
438/*
439Note on the callback ownership.
440
441In the Binder ownership model, the server implementation is kept alive
442as long as there is any client (proxy object) alive. This is done by
443incrementing the refcount of the server-side object by the Binder framework.
444When it detects that the last client is gone, it decrements the refcount back.
445
446Thus, it is not needed to keep any references to StreamCallback on our
447side (after we have sent an instance to the client), because we are
448the server-side. The callback object will be kept alive as long as the HAL server
449holds a strong ref to IStreamCallback proxy.
450*/
451
452class OutputStreamCallbackAidl : public StreamCallbackBase,
453 public StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>,
454 public ::aidl::android::hardware::audio::core::BnStreamCallback {
455 public:
456 explicit OutputStreamCallbackAidl(const sp<CallbackBroker>& broker)
457 : StreamCallbackBase(broker),
458 StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>(
459 *static_cast<StreamCallbackBase*>(this)) {}
460 ndk::ScopedAStatus onTransferReady() override {
461 return runCb([](CbRef cb) { cb->onWriteReady(); });
462 }
463 ndk::ScopedAStatus onError() override {
464 return runCb([](CbRef cb) { cb->onError(); });
465 }
466 ndk::ScopedAStatus onDrainReady() override {
467 return runCb([](CbRef cb) { cb->onDrainReady(); });
468 }
469};
470
471class OutputStreamEventCallbackAidl :
472 public StreamCallbackBase,
473 public StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>,
474 public StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>,
475 public ::aidl::android::hardware::audio::core::BnStreamOutEventCallback {
476 public:
477 explicit OutputStreamEventCallbackAidl(const sp<CallbackBroker>& broker)
478 : StreamCallbackBase(broker),
479 StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>(
480 *static_cast<StreamCallbackBase*>(this)),
481 StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>(
482 *static_cast<StreamCallbackBase*>(this)) {}
483 ndk::ScopedAStatus onCodecFormatChanged(const std::vector<uint8_t>& in_audioMetadata) override {
484 std::basic_string<uint8_t> halMetadata(in_audioMetadata.begin(), in_audioMetadata.end());
485 return StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>::runCb(
486 [&halMetadata](auto cb) { cb->onCodecFormatChanged(halMetadata); });
487 }
488 ndk::ScopedAStatus onRecommendedLatencyModeChanged(
489 const std::vector<AudioLatencyMode>& in_modes) override {
490 auto halModes = VALUE_OR_FATAL(
491 ::aidl::android::convertContainer<std::vector<audio_latency_mode_t>>(
492 in_modes,
493 ::aidl::android::aidl2legacy_AudioLatencyMode_audio_latency_mode_t));
494 return StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>::runCb(
495 [&halModes](auto cb) { cb->onRecommendedLatencyModeChanged(halModes); });
496 }
497};
498
499} // namespace
500
Mikhail Naganov31d46652023-01-10 18:29:25 +0000501status_t DeviceHalAidl::openOutputStream(
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800502 audio_io_handle_t handle, audio_devices_t devices,
503 audio_output_flags_t flags, struct audio_config* config,
504 const char* address,
Mikhail Naganov31d46652023-01-10 18:29:25 +0000505 sp<StreamOutHalInterface>* outStream) {
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800506 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000507 if (!outStream || !config) {
508 return BAD_VALUE;
509 }
510 TIME_CHECK();
511 if (!mModule) return NO_INIT;
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800512 int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
513 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(handle));
514 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
515 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, false /*isInput*/));
516 AudioDevice aidlDevice = VALUE_OR_RETURN_STATUS(
517 ::aidl::android::legacy2aidl_audio_device_AudioDevice(devices, address));
518 int32_t aidlOutputFlags = VALUE_OR_RETURN_STATUS(
519 ::aidl::android::legacy2aidl_audio_output_flags_t_int32_t_mask(flags));
520 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::output>(aidlOutputFlags);
521 AudioPortConfig mixPortConfig;
522 Cleanups cleanups;
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800523 int32_t nominalLatency;
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800524 RETURN_STATUS_IF_ERROR(prepareToOpenStream(aidlHandle, aidlDevice, aidlFlags,
525 AudioSource::SYS_RESERVED_INVALID /*only needed for input*/,
526 config, &cleanups, &aidlConfig, &mixPortConfig, &nominalLatency));
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800527 ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamArguments args;
528 args.portConfigId = mixPortConfig.id;
Mikhail Naganovb0c55252023-02-08 16:59:41 -0800529 const bool isOffload = isBitPositionFlagSet(
530 aidlOutputFlags, AudioOutputFlags::COMPRESS_OFFLOAD);
531 std::shared_ptr<OutputStreamCallbackAidl> streamCb;
532 if (isOffload) {
533 streamCb = ndk::SharedRefBase::make<OutputStreamCallbackAidl>(this);
534 }
535 auto eventCb = ndk::SharedRefBase::make<OutputStreamEventCallbackAidl>(this);
536 if (isOffload) {
537 args.offloadInfo = aidlConfig.offloadInfo;
538 args.callback = streamCb;
539 }
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800540 args.bufferSizeFrames = aidlConfig.frameCount;
Mikhail Naganovb0c55252023-02-08 16:59:41 -0800541 args.eventCallback = eventCb;
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800542 ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamReturn ret;
543 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openOutputStream(args, &ret)));
Mikhail Naganov712d71b2023-02-23 17:57:16 -0800544 StreamContextAidl context(ret.desc, isOffload);
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800545 if (!context.isValid()) {
546 ALOGE("%s: Failed to created a valid stream context from the descriptor: %s",
547 __func__, ret.desc.toString().c_str());
548 return NO_INIT;
549 }
550 *outStream = sp<StreamOutHalAidl>::make(*config, std::move(context), nominalLatency,
Mikhail Naganovb0c55252023-02-08 16:59:41 -0800551 std::move(ret.stream), this /*callbackBroker*/);
552 void* cbCookie = (*outStream).get();
553 {
554 std::lock_guard l(mLock);
555 mCallbacks.emplace(cbCookie, Callbacks{});
556 }
557 if (streamCb) streamCb->setCookie(cbCookie);
558 eventCb->setCookie(cbCookie);
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800559 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000560 return OK;
561}
562
Mikhail Naganov31d46652023-01-10 18:29:25 +0000563status_t DeviceHalAidl::openInputStream(
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800564 audio_io_handle_t handle, audio_devices_t devices,
565 struct audio_config* config, audio_input_flags_t flags,
566 const char* address, audio_source_t source,
567 audio_devices_t outputDevice, const char* outputDeviceAddress,
Mikhail Naganov31d46652023-01-10 18:29:25 +0000568 sp<StreamInHalInterface>* inStream) {
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800569 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000570 if (!inStream || !config) {
571 return BAD_VALUE;
572 }
573 TIME_CHECK();
574 if (!mModule) return NO_INIT;
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800575 int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
576 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(handle));
577 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
578 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, true /*isInput*/));
579 AudioDevice aidlDevice = VALUE_OR_RETURN_STATUS(
580 ::aidl::android::legacy2aidl_audio_device_AudioDevice(devices, address));
581 int32_t aidlInputFlags = VALUE_OR_RETURN_STATUS(
582 ::aidl::android::legacy2aidl_audio_input_flags_t_int32_t_mask(flags));
583 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::input>(aidlInputFlags);
584 AudioSource aidlSource = VALUE_OR_RETURN_STATUS(
585 ::aidl::android::legacy2aidl_audio_source_t_AudioSource(source));
586 AudioPortConfig mixPortConfig;
587 Cleanups cleanups;
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800588 int32_t nominalLatency;
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800589 RETURN_STATUS_IF_ERROR(prepareToOpenStream(aidlHandle, aidlDevice, aidlFlags, aidlSource,
590 config, &cleanups, &aidlConfig, &mixPortConfig, &nominalLatency));
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800591 ::aidl::android::hardware::audio::core::IModule::OpenInputStreamArguments args;
592 args.portConfigId = mixPortConfig.id;
593 RecordTrackMetadata aidlTrackMetadata{
594 .source = aidlSource, .gain = 1, .channelMask = aidlConfig.base.channelMask };
595 if (outputDevice != AUDIO_DEVICE_NONE) {
596 aidlTrackMetadata.destinationDevice = VALUE_OR_RETURN_STATUS(
597 ::aidl::android::legacy2aidl_audio_device_AudioDevice(
598 outputDevice, outputDeviceAddress));
599 }
600 args.sinkMetadata.tracks.push_back(std::move(aidlTrackMetadata));
601 args.bufferSizeFrames = aidlConfig.frameCount;
602 ::aidl::android::hardware::audio::core::IModule::OpenInputStreamReturn ret;
603 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openInputStream(args, &ret)));
Mikhail Naganov712d71b2023-02-23 17:57:16 -0800604 StreamContextAidl context(ret.desc, false /*isAsynchronous*/);
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800605 if (!context.isValid()) {
606 ALOGE("%s: Failed to created a valid stream context from the descriptor: %s",
607 __func__, ret.desc.toString().c_str());
608 return NO_INIT;
609 }
610 *inStream = sp<StreamInHalAidl>::make(*config, std::move(context), nominalLatency,
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800611 std::move(ret.stream), this /*micInfoProvider*/);
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800612 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000613 return OK;
614}
615
616status_t DeviceHalAidl::supportsAudioPatches(bool* supportsPatches) {
617 *supportsPatches = true;
618 return OK;
619}
620
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800621status_t DeviceHalAidl::createAudioPatch(unsigned int num_sources,
622 const struct audio_port_config* sources,
623 unsigned int num_sinks,
624 const struct audio_port_config* sinks,
625 audio_patch_handle_t* patch) {
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800626 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000627 TIME_CHECK();
628 if (!mModule) return NO_INIT;
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800629 if (num_sinks > AUDIO_PATCH_PORTS_MAX || num_sources > AUDIO_PATCH_PORTS_MAX ||
630 sources == nullptr || sinks == nullptr || patch == nullptr) {
631 return BAD_VALUE;
632 }
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800633 // When the patch handle (*patch) is AUDIO_PATCH_HANDLE_NONE, it means
634 // the framework wants to create a new patch. The handle has to be generated
635 // by the HAL. Since handles generated this way can only be unique within
636 // a HAL module, the framework generates a globally unique handle, and maps
637 // it on the <HAL module, patch handle> pair.
638 // When the patch handle is set, it meant the framework intends to update
639 // an existing patch.
640 //
641 // This behavior corresponds to HAL module behavior, with the only difference
642 // that the HAL module uses `int32_t` for patch IDs. The following assert ensures
643 // that both the framework and the HAL use the same value for "no ID":
644 static_assert(AUDIO_PATCH_HANDLE_NONE == 0);
645 int32_t halPatchId = static_cast<int32_t>(*patch);
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800646
647 // Upon conversion, mix port configs contain audio configuration, while
648 // device port configs contain device address. This data is used to find
649 // or create HAL configs.
650 std::vector<AudioPortConfig> aidlSources, aidlSinks;
651 for (unsigned int i = 0; i < num_sources; ++i) {
652 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
653 sources[i].role, sources[i].type)) ==
654 ::aidl::android::AudioPortDirection::INPUT;
655 aidlSources.push_back(VALUE_OR_RETURN_STATUS(
656 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
657 sources[i], isInput, 0)));
658 }
659 for (unsigned int i = 0; i < num_sinks; ++i) {
660 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
661 sinks[i].role, sinks[i].type)) ==
662 ::aidl::android::AudioPortDirection::INPUT;
663 aidlSinks.push_back(VALUE_OR_RETURN_STATUS(
664 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
665 sinks[i], isInput, 0)));
666 }
667 Cleanups cleanups;
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800668 auto existingPatchIt = halPatchId != 0 ? mPatches.find(halPatchId): mPatches.end();
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800669 AudioPatch aidlPatch;
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800670 if (existingPatchIt != mPatches.end()) {
671 aidlPatch = existingPatchIt->second;
672 aidlPatch.sourcePortConfigIds.clear();
673 aidlPatch.sinkPortConfigIds.clear();
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800674 }
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800675 ALOGD("%s: sources: %s, sinks: %s",
676 __func__, ::android::internal::ToString(aidlSources).c_str(),
677 ::android::internal::ToString(aidlSinks).c_str());
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800678 auto fillPortConfigs = [&](
679 const std::vector<AudioPortConfig>& configs, std::vector<int32_t>* ids) -> status_t {
680 for (const auto& s : configs) {
681 AudioPortConfig portConfig;
682 bool created = false;
683 RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(s, &portConfig, &created));
684 if (created) {
685 cleanups.emplace_front(this, &DeviceHalAidl::resetPortConfig, portConfig.id);
686 }
687 ids->push_back(portConfig.id);
688 }
689 return OK;
690 };
691 RETURN_STATUS_IF_ERROR(fillPortConfigs(aidlSources, &aidlPatch.sourcePortConfigIds));
692 RETURN_STATUS_IF_ERROR(fillPortConfigs(aidlSinks, &aidlPatch.sinkPortConfigIds));
693 if (existingPatchIt != mPatches.end()) {
694 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
695 mModule->setAudioPatch(aidlPatch, &aidlPatch)));
696 existingPatchIt->second = aidlPatch;
697 } else {
698 bool created = false;
699 RETURN_STATUS_IF_ERROR(findOrCreatePatch(aidlPatch, &aidlPatch, &created));
700 // Since no cleanup of the patch is needed, 'created' is ignored.
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800701 halPatchId = aidlPatch.id;
702 *patch = static_cast<audio_patch_handle_t>(halPatchId);
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800703 }
704 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000705 return OK;
706}
707
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800708status_t DeviceHalAidl::releaseAudioPatch(audio_patch_handle_t patch) {
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800709 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000710 TIME_CHECK();
711 if (!mModule) return NO_INIT;
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800712 static_assert(AUDIO_PATCH_HANDLE_NONE == 0);
713 if (patch == AUDIO_PATCH_HANDLE_NONE) {
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800714 return BAD_VALUE;
715 }
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800716 int32_t halPatchId = static_cast<int32_t>(patch);
717 auto patchIt = mPatches.find(halPatchId);
718 if (patchIt == mPatches.end()) {
719 ALOGE("%s: patch with id %d not found", __func__, halPatchId);
720 return BAD_VALUE;
721 }
722 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->resetAudioPatch(halPatchId)));
723 mPatches.erase(patchIt);
Shunkai Yao51202502022-12-12 06:11:46 +0000724 return OK;
725}
726
Mikhail Naganov31d46652023-01-10 18:29:25 +0000727status_t DeviceHalAidl::getAudioPort(struct audio_port* port __unused) {
728 TIME_CHECK();
729 ALOGE("%s not implemented yet", __func__);
730 return INVALID_OPERATION;
731}
732
733status_t DeviceHalAidl::getAudioPort(struct audio_port_v7 *port __unused) {
734 TIME_CHECK();
735 ALOGE("%s not implemented yet", __func__);
736 return INVALID_OPERATION;
737}
738
739status_t DeviceHalAidl::setAudioPortConfig(const struct audio_port_config* config __unused) {
740 TIME_CHECK();
741 if (!mModule) return NO_INIT;
742 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000743 return OK;
744}
745
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800746MicrophoneInfoProvider::Info const* DeviceHalAidl::getMicrophoneInfo() {
747 if (mMicrophones.status == Microphones::Status::UNKNOWN) {
748 TIME_CHECK();
749 std::vector<MicrophoneInfo> aidlInfo;
750 status_t status = statusTFromBinderStatus(mModule->getMicrophones(&aidlInfo));
751 if (status == OK) {
752 mMicrophones.status = Microphones::Status::QUERIED;
753 mMicrophones.info = std::move(aidlInfo);
754 } else if (status == INVALID_OPERATION) {
755 mMicrophones.status = Microphones::Status::NOT_SUPPORTED;
756 } else {
757 ALOGE("%s: Unexpected status from 'IModule.getMicrophones': %d", __func__, status);
758 return {};
759 }
760 }
761 if (mMicrophones.status == Microphones::Status::QUERIED) {
762 return &mMicrophones.info;
763 }
764 return {}; // NOT_SUPPORTED
765}
766
Shunkai Yao51202502022-12-12 06:11:46 +0000767status_t DeviceHalAidl::getMicrophones(
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800768 std::vector<audio_microphone_characteristic_t>* microphones) {
769 if (!microphones) {
770 return BAD_VALUE;
771 }
Mikhail Naganov31d46652023-01-10 18:29:25 +0000772 TIME_CHECK();
773 if (!mModule) return NO_INIT;
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800774 auto staticInfo = getMicrophoneInfo();
775 if (!staticInfo) return INVALID_OPERATION;
776 std::vector<MicrophoneDynamicInfo> emptyDynamicInfo;
777 emptyDynamicInfo.reserve(staticInfo->size());
778 std::transform(staticInfo->begin(), staticInfo->end(), std::back_inserter(emptyDynamicInfo),
779 [](const auto& info) { return MicrophoneDynamicInfo{ .id = info.id }; });
780 *microphones = VALUE_OR_RETURN_STATUS(
781 ::aidl::android::convertContainers<std::vector<audio_microphone_characteristic_t>>(
782 *staticInfo, emptyDynamicInfo,
783 ::aidl::android::aidl2legacy_MicrophoneInfos_audio_microphone_characteristic_t)
784 );
Shunkai Yao51202502022-12-12 06:11:46 +0000785 return OK;
786}
787
Mikhail Naganov31d46652023-01-10 18:29:25 +0000788status_t DeviceHalAidl::addDeviceEffect(audio_port_handle_t device __unused,
789 sp<EffectHalInterface> effect) {
Shunkai Yao51202502022-12-12 06:11:46 +0000790 if (!effect) {
791 return BAD_VALUE;
792 }
Mikhail Naganov31d46652023-01-10 18:29:25 +0000793 TIME_CHECK();
794 if (!mModule) return NO_INIT;
795 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000796 return OK;
797}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000798status_t DeviceHalAidl::removeDeviceEffect(audio_port_handle_t device __unused,
Shunkai Yao51202502022-12-12 06:11:46 +0000799 sp<EffectHalInterface> effect) {
800 if (!effect) {
801 return BAD_VALUE;
802 }
Mikhail Naganov31d46652023-01-10 18:29:25 +0000803 TIME_CHECK();
804 if (!mModule) return NO_INIT;
805 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000806 return OK;
807}
808
809status_t DeviceHalAidl::getMmapPolicyInfos(
David Li9cf5e622023-03-21 00:51:10 +0800810 media::audio::common::AudioMMapPolicyType policyType,
811 std::vector<media::audio::common::AudioMMapPolicyInfo>* policyInfos) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000812 TIME_CHECK();
David Li9cf5e622023-03-21 00:51:10 +0800813 AudioMMapPolicyType mmapPolicyType =
814 VALUE_OR_RETURN_STATUS(cpp2ndk_Enum<AudioMMapPolicyType>(policyType));
815
816 std::vector<AudioMMapPolicyInfo> mmapPolicyInfos;
817
818 if (status_t status = statusTFromBinderStatus(
819 mModule->getMmapPolicyInfos(mmapPolicyType, &mmapPolicyInfos)); status != OK) {
820 return status;
821 }
822
823 *policyInfos = VALUE_OR_RETURN_STATUS(
824 convertContainer<std::vector<media::audio::common::AudioMMapPolicyInfo>>(
825 mmapPolicyInfos, ndk2cpp_AudioMMapPolicyInfo));
Shunkai Yao51202502022-12-12 06:11:46 +0000826 return OK;
827}
828
829int32_t DeviceHalAidl::getAAudioMixerBurstCount() {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000830 TIME_CHECK();
David Li9cf5e622023-03-21 00:51:10 +0800831 int32_t mixerBurstCount = 0;
832 if (mModule->getAAudioMixerBurstCount(&mixerBurstCount).isOk()) {
833 return mixerBurstCount;
834 }
835 return 0;
Shunkai Yao51202502022-12-12 06:11:46 +0000836}
837
838int32_t DeviceHalAidl::getAAudioHardwareBurstMinUsec() {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000839 TIME_CHECK();
David Li9cf5e622023-03-21 00:51:10 +0800840 int32_t hardwareBurstMinUsec = 0;
841 if (mModule->getAAudioHardwareBurstMinUsec(&hardwareBurstMinUsec).isOk()) {
842 return hardwareBurstMinUsec;
843 }
844 return 0;
Shunkai Yao51202502022-12-12 06:11:46 +0000845}
846
847error::Result<audio_hw_sync_t> DeviceHalAidl::getHwAvSync() {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000848 TIME_CHECK();
Mikhail Naganov08a62ab2023-03-14 17:11:51 -0700849 if (!mModule) return NO_INIT;
850 int32_t aidlHwAvSync;
851 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->generateHwAvSyncId(&aidlHwAvSync)));
852 return VALUE_OR_RETURN_STATUS(
853 ::aidl::android::aidl2legacy_int32_t_audio_hw_sync_t(aidlHwAvSync));
Shunkai Yao51202502022-12-12 06:11:46 +0000854}
855
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000856status_t DeviceHalAidl::dump(int fd, const Vector<String16>& args) {
857 TIME_CHECK();
858 if (!mModule) return NO_INIT;
859 return mModule->dump(fd, Args(args).args(), args.size());
David Li9cf5e622023-03-21 00:51:10 +0800860}
Shunkai Yao51202502022-12-12 06:11:46 +0000861
Mikhail Naganov31d46652023-01-10 18:29:25 +0000862int32_t DeviceHalAidl::supportsBluetoothVariableLatency(bool* supports __unused) {
863 TIME_CHECK();
Shunkai Yao51202502022-12-12 06:11:46 +0000864 ALOGE("%s not implemented yet", __func__);
865 return INVALID_OPERATION;
866}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000867
Vlad Popa03bd5bc2023-01-17 16:16:51 +0100868status_t DeviceHalAidl::getSoundDoseInterface(const std::string& module,
869 ::ndk::SpAIBinder* soundDoseBinder) {
870 TIME_CHECK();
871 if (!mModule) return NO_INIT;
872 if (mSoundDose == nullptr) {
873 ndk::ScopedAStatus status = mModule->getSoundDose(&mSoundDose);
874 if (!status.isOk()) {
875 ALOGE("%s failed to return the sound dose interface for module %s: %s",
876 __func__,
877 module.c_str(),
878 status.getDescription().c_str());
879 return BAD_VALUE;
880 }
881 }
882 *soundDoseBinder = mSoundDose->asBinder();
883 ALOGI("%s using audio AIDL HAL sound dose interface", __func__);
884
885 return OK;
886}
887
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800888bool DeviceHalAidl::audioDeviceMatches(const AudioDevice& device, const AudioPort& p) {
889 if (p.ext.getTag() != AudioPortExt::Tag::device) return false;
890 return p.ext.get<AudioPortExt::Tag::device>().device == device;
891}
892
893bool DeviceHalAidl::audioDeviceMatches(const AudioDevice& device, const AudioPortConfig& p) {
894 if (p.ext.getTag() != AudioPortExt::Tag::device) return false;
895 if (device.type.type == AudioDeviceType::IN_DEFAULT) {
896 return p.portId == mDefaultInputPortId;
897 } else if (device.type.type == AudioDeviceType::OUT_DEFAULT) {
898 return p.portId == mDefaultOutputPortId;
899 }
900 return p.ext.get<AudioPortExt::Tag::device>().device == device;
901}
902
Mikhail Naganov1a44bc62023-02-16 17:35:06 -0800903status_t DeviceHalAidl::createPortConfig(
904 const AudioPortConfig& requestedPortConfig, PortConfigs::iterator* result) {
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800905 TIME_CHECK();
Mikhail Naganov1a44bc62023-02-16 17:35:06 -0800906 AudioPortConfig appliedPortConfig;
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800907 bool applied = false;
908 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPortConfig(
Mikhail Naganov1a44bc62023-02-16 17:35:06 -0800909 requestedPortConfig, &appliedPortConfig, &applied)));
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800910 if (!applied) {
911 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPortConfig(
Mikhail Naganov1a44bc62023-02-16 17:35:06 -0800912 appliedPortConfig, &appliedPortConfig, &applied)));
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800913 if (!applied) {
914 ALOGE("%s: module %s did not apply suggested config %s",
Mikhail Naganov1a44bc62023-02-16 17:35:06 -0800915 __func__, mInstance.c_str(), appliedPortConfig.toString().c_str());
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800916 return NO_INIT;
917 }
918 }
Mikhail Naganov1a44bc62023-02-16 17:35:06 -0800919 auto id = appliedPortConfig.id;
920 auto [it, inserted] = mPortConfigs.emplace(std::move(id), std::move(appliedPortConfig));
921 LOG_ALWAYS_FATAL_IF(!inserted, "%s: port config with id %d already exists",
922 __func__, it->first);
923 *result = it;
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800924 return OK;
925}
926
927status_t DeviceHalAidl::findOrCreatePatch(
928 const AudioPatch& requestedPatch, AudioPatch* patch, bool* created) {
929 std::set<int32_t> sourcePortConfigIds(requestedPatch.sourcePortConfigIds.begin(),
930 requestedPatch.sourcePortConfigIds.end());
931 std::set<int32_t> sinkPortConfigIds(requestedPatch.sinkPortConfigIds.begin(),
932 requestedPatch.sinkPortConfigIds.end());
933 return findOrCreatePatch(sourcePortConfigIds, sinkPortConfigIds, patch, created);
934}
935
936status_t DeviceHalAidl::findOrCreatePatch(
937 const std::set<int32_t>& sourcePortConfigIds, const std::set<int32_t>& sinkPortConfigIds,
938 AudioPatch* patch, bool* created) {
939 auto patchIt = findPatch(sourcePortConfigIds, sinkPortConfigIds);
940 if (patchIt == mPatches.end()) {
941 TIME_CHECK();
942 AudioPatch requestedPatch, appliedPatch;
943 requestedPatch.sourcePortConfigIds.insert(requestedPatch.sourcePortConfigIds.end(),
944 sourcePortConfigIds.begin(), sourcePortConfigIds.end());
945 requestedPatch.sinkPortConfigIds.insert(requestedPatch.sinkPortConfigIds.end(),
946 sinkPortConfigIds.begin(), sinkPortConfigIds.end());
947 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPatch(
948 requestedPatch, &appliedPatch)));
949 patchIt = mPatches.insert(mPatches.end(), std::make_pair(appliedPatch.id, appliedPatch));
950 *created = true;
951 } else {
952 *created = false;
953 }
954 *patch = patchIt->second;
955 return OK;
956}
957
958status_t DeviceHalAidl::findOrCreatePortConfig(const AudioDevice& device,
959 AudioPortConfig* portConfig, bool* created) {
960 auto portConfigIt = findPortConfig(device);
961 if (portConfigIt == mPortConfigs.end()) {
962 auto portsIt = findPort(device);
963 if (portsIt == mPorts.end()) {
964 ALOGE("%s: device port for device %s is not found in the module %s",
965 __func__, device.toString().c_str(), mInstance.c_str());
966 return BAD_VALUE;
967 }
968 AudioPortConfig requestedPortConfig;
969 requestedPortConfig.portId = portsIt->first;
Mikhail Naganov1a44bc62023-02-16 17:35:06 -0800970 RETURN_STATUS_IF_ERROR(createPortConfig(requestedPortConfig, &portConfigIt));
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800971 *created = true;
972 } else {
973 *created = false;
974 }
975 *portConfig = portConfigIt->second;
976 return OK;
977}
978
979status_t DeviceHalAidl::findOrCreatePortConfig(
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800980 const AudioConfig& config, const std::optional<AudioIoFlags>& flags, int32_t ioHandle,
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800981 AudioSource source, AudioPortConfig* portConfig, bool* created) {
Mikhail Naganov1a44bc62023-02-16 17:35:06 -0800982 // These flags get removed one by one in this order when retrying port finding.
983 static const std::vector<AudioInputFlags> kOptionalInputFlags{
984 AudioInputFlags::FAST, AudioInputFlags::RAW };
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800985 auto portConfigIt = findPortConfig(config, flags, ioHandle);
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800986 if (portConfigIt == mPortConfigs.end() && flags.has_value()) {
Mikhail Naganov1a44bc62023-02-16 17:35:06 -0800987 auto optionalInputFlagsIt = kOptionalInputFlags.begin();
988 AudioIoFlags matchFlags = flags.value();
989 auto portsIt = findPort(config, matchFlags);
990 while (portsIt == mPorts.end() && matchFlags.getTag() == AudioIoFlags::Tag::input
991 && optionalInputFlagsIt != kOptionalInputFlags.end()) {
992 if (!isBitPositionFlagSet(
993 matchFlags.get<AudioIoFlags::Tag::input>(), *optionalInputFlagsIt)) {
994 ++optionalInputFlagsIt;
995 continue;
996 }
997 matchFlags.set<AudioIoFlags::Tag::input>(matchFlags.get<AudioIoFlags::Tag::input>() &
998 ~makeBitPositionFlagMask(*optionalInputFlagsIt++));
999 portsIt = findPort(config, matchFlags);
1000 ALOGI("%s: mix port for config %s, flags %s was not found in the module %s, "
1001 "retried with flags %s", __func__, config.toString().c_str(),
1002 flags.value().toString().c_str(), mInstance.c_str(),
1003 matchFlags.toString().c_str());
1004 }
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001005 if (portsIt == mPorts.end()) {
1006 ALOGE("%s: mix port for config %s, flags %s is not found in the module %s",
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001007 __func__, config.toString().c_str(), matchFlags.toString().c_str(),
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001008 mInstance.c_str());
1009 return BAD_VALUE;
1010 }
1011 AudioPortConfig requestedPortConfig;
1012 requestedPortConfig.portId = portsIt->first;
1013 setPortConfigFromConfig(&requestedPortConfig, config);
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001014 requestedPortConfig.ext = AudioPortMixExt{ .handle = ioHandle };
Mikhail Naganovd8d01f72023-03-09 16:24:40 -08001015 if (matchFlags.getTag() == AudioIoFlags::Tag::input
1016 && source != AudioSource::SYS_RESERVED_INVALID) {
1017 requestedPortConfig.ext.get<AudioPortExt::Tag::mix>().usecase =
1018 AudioPortMixExtUseCase::make<AudioPortMixExtUseCase::Tag::source>(source);
1019 }
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001020 RETURN_STATUS_IF_ERROR(createPortConfig(requestedPortConfig, &portConfigIt));
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001021 *created = true;
Mikhail Naganov8bd806e2023-01-30 12:33:18 -08001022 } else if (!flags.has_value()) {
1023 ALOGW("%s: mix port config for %s, handle %d not found in the module %s, "
1024 "and was not created as flags are not specified",
1025 __func__, config.toString().c_str(), ioHandle, mInstance.c_str());
1026 return BAD_VALUE;
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001027 } else {
1028 *created = false;
1029 }
1030 *portConfig = portConfigIt->second;
1031 return OK;
1032}
1033
1034status_t DeviceHalAidl::findOrCreatePortConfig(
1035 const AudioPortConfig& requestedPortConfig, AudioPortConfig* portConfig, bool* created) {
1036 using Tag = AudioPortExt::Tag;
1037 if (requestedPortConfig.ext.getTag() == Tag::mix) {
1038 if (const auto& p = requestedPortConfig;
1039 !p.sampleRate.has_value() || !p.channelMask.has_value() ||
Mikhail Naganov8bd806e2023-01-30 12:33:18 -08001040 !p.format.has_value()) {
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001041 ALOGW("%s: provided mix port config is not fully specified: %s",
1042 __func__, p.toString().c_str());
1043 return BAD_VALUE;
1044 }
1045 AudioConfig config;
1046 setConfigFromPortConfig(&config, requestedPortConfig);
Mikhail Naganovd8d01f72023-03-09 16:24:40 -08001047 AudioSource source = requestedPortConfig.ext.get<Tag::mix>().usecase.getTag() ==
1048 AudioPortMixExtUseCase::Tag::source ?
1049 requestedPortConfig.ext.get<Tag::mix>().usecase.
1050 get<AudioPortMixExtUseCase::Tag::source>() : AudioSource::SYS_RESERVED_INVALID;
Mikhail Naganov8bd806e2023-01-30 12:33:18 -08001051 return findOrCreatePortConfig(config, requestedPortConfig.flags,
Mikhail Naganovd8d01f72023-03-09 16:24:40 -08001052 requestedPortConfig.ext.get<Tag::mix>().handle, source, portConfig, created);
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001053 } else if (requestedPortConfig.ext.getTag() == Tag::device) {
1054 return findOrCreatePortConfig(
1055 requestedPortConfig.ext.get<Tag::device>().device, portConfig, created);
1056 }
1057 ALOGW("%s: unsupported audio port config: %s",
1058 __func__, requestedPortConfig.toString().c_str());
1059 return BAD_VALUE;
1060}
1061
1062DeviceHalAidl::Patches::iterator DeviceHalAidl::findPatch(
1063 const std::set<int32_t>& sourcePortConfigIds, const std::set<int32_t>& sinkPortConfigIds) {
1064 return std::find_if(mPatches.begin(), mPatches.end(),
1065 [&](const auto& pair) {
1066 const auto& p = pair.second;
1067 std::set<int32_t> patchSrcs(
1068 p.sourcePortConfigIds.begin(), p.sourcePortConfigIds.end());
1069 std::set<int32_t> patchSinks(
1070 p.sinkPortConfigIds.begin(), p.sinkPortConfigIds.end());
1071 return sourcePortConfigIds == patchSrcs && sinkPortConfigIds == patchSinks; });
1072}
1073
1074DeviceHalAidl::Ports::iterator DeviceHalAidl::findPort(const AudioDevice& device) {
Mikhail Naganov8bd806e2023-01-30 12:33:18 -08001075 if (device.type.type == AudioDeviceType::IN_DEFAULT) {
1076 return mPorts.find(mDefaultInputPortId);
1077 } else if (device.type.type == AudioDeviceType::OUT_DEFAULT) {
1078 return mPorts.find(mDefaultOutputPortId);
1079 }
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001080 return std::find_if(mPorts.begin(), mPorts.end(),
Mikhail Naganov8bd806e2023-01-30 12:33:18 -08001081 [&](const auto& pair) { return audioDeviceMatches(device, pair.second); });
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001082}
1083
1084DeviceHalAidl::Ports::iterator DeviceHalAidl::findPort(
1085 const AudioConfig& config, const AudioIoFlags& flags) {
Mikhail Naganov8bd806e2023-01-30 12:33:18 -08001086 auto matcher = [&](const auto& pair) {
1087 const auto& p = pair.second;
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001088 return p.ext.getTag() == AudioPortExt::Tag::mix &&
1089 p.flags == flags &&
Mikhail Naganov8bd806e2023-01-30 12:33:18 -08001090 std::find_if(p.profiles.begin(), p.profiles.end(),
1091 [&](const auto& prof) {
1092 return prof.format == config.base.format &&
1093 std::find(prof.channelMasks.begin(), prof.channelMasks.end(),
1094 config.base.channelMask) != prof.channelMasks.end() &&
1095 std::find(prof.sampleRates.begin(), prof.sampleRates.end(),
1096 config.base.sampleRate) != prof.sampleRates.end();
1097 }) != p.profiles.end(); };
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001098 return std::find_if(mPorts.begin(), mPorts.end(), matcher);
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001099}
1100
1101DeviceHalAidl::PortConfigs::iterator DeviceHalAidl::findPortConfig(const AudioDevice& device) {
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001102 return std::find_if(mPortConfigs.begin(), mPortConfigs.end(),
Mikhail Naganov8bd806e2023-01-30 12:33:18 -08001103 [&](const auto& pair) { return audioDeviceMatches(device, pair.second); });
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001104}
1105
1106DeviceHalAidl::PortConfigs::iterator DeviceHalAidl::findPortConfig(
Mikhail Naganov8bd806e2023-01-30 12:33:18 -08001107 const AudioConfig& config, const std::optional<AudioIoFlags>& flags, int32_t ioHandle) {
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001108 using Tag = AudioPortExt::Tag;
1109 return std::find_if(mPortConfigs.begin(), mPortConfigs.end(),
1110 [&](const auto& pair) {
1111 const auto& p = pair.second;
1112 LOG_ALWAYS_FATAL_IF(p.ext.getTag() == Tag::mix &&
1113 !p.sampleRate.has_value() || !p.channelMask.has_value() ||
1114 !p.format.has_value() || !p.flags.has_value(),
1115 "%s: stored mix port config is not fully specified: %s",
1116 __func__, p.toString().c_str());
1117 return p.ext.getTag() == Tag::mix &&
1118 isConfigEqualToPortConfig(config, p) &&
Mikhail Naganov8bd806e2023-01-30 12:33:18 -08001119 (!flags.has_value() || p.flags.value() == flags.value()) &&
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001120 p.ext.template get<Tag::mix>().handle == ioHandle; });
1121}
1122/*
1123DeviceHalAidl::PortConfigs::iterator DeviceHalAidl::findPortConfig(
1124 const AudioPortConfig& portConfig) {
1125 using Tag = AudioPortExt::Tag;
1126 if (portConfig.ext.getTag() == Tag::mix) {
1127 return std::find_if(mPortConfigs.begin(), mPortConfigs.end(),
1128 [&](const auto& pair) {
1129 const auto& p = pair.second;
1130 LOG_ALWAYS_FATAL_IF(p.ext.getTag() == Tag::mix &&
1131 !p.sampleRate.has_value() || !p.channelMask.has_value() ||
1132 !p.format.has_value() || !p.flags.has_value(),
1133 "%s: stored mix port config is not fully specified: %s",
1134 __func__, p.toString().c_str());
1135 return p.ext.getTag() == Tag::mix &&
1136 (!portConfig.sampleRate.has_value() ||
1137 p.sampleRate == portConfig.sampleRate) &&
1138 (!portConfig.channelMask.has_value() ||
1139 p.channelMask == portConfig.channelMask) &&
1140 (!portConfig.format.has_value() || p.format == portConfig.format) &&
1141 (!portConfig.flags.has_value() || p.flags == portConfig.flags) &&
1142 p.ext.template get<Tag::mix>().handle ==
1143 portConfig.ext.template get<Tag::mix>().handle; });
1144 } else if (portConfig.ext.getTag() == Tag::device) {
1145 return findPortConfig(portConfig.ext.get<Tag::device>().device);
1146 }
1147 return mPortConfigs.end();
1148}
1149*/
1150void DeviceHalAidl::resetPatch(int32_t patchId) {
1151 if (auto it = mPatches.find(patchId); it != mPatches.end()) {
1152 mPatches.erase(it);
1153 TIME_CHECK();
1154 if (ndk::ScopedAStatus status = mModule->resetAudioPatch(patchId); !status.isOk()) {
1155 ALOGE("%s: error while resetting patch %d: %s",
1156 __func__, patchId, status.getDescription().c_str());
1157 }
1158 return;
1159 }
1160 ALOGE("%s: patch id %d not found", __func__, patchId);
1161}
1162
1163void DeviceHalAidl::resetPortConfig(int32_t portConfigId) {
1164 if (auto it = mPortConfigs.find(portConfigId); it != mPortConfigs.end()) {
1165 mPortConfigs.erase(it);
1166 TIME_CHECK();
1167 if (ndk::ScopedAStatus status = mModule->resetAudioPortConfig(portConfigId);
1168 !status.isOk()) {
1169 ALOGE("%s: error while resetting port config %d: %s",
1170 __func__, portConfigId, status.getDescription().c_str());
1171 }
1172 return;
1173 }
1174 ALOGE("%s: port config id %d not found", __func__, portConfigId);
1175}
1176
Mikhail Naganovb0c55252023-02-08 16:59:41 -08001177void DeviceHalAidl::clearCallbacks(void* cookie) {
1178 std::lock_guard l(mLock);
1179 mCallbacks.erase(cookie);
1180}
1181
1182sp<StreamOutHalInterfaceCallback> DeviceHalAidl::getStreamOutCallback(void* cookie) {
1183 return getCallbackImpl(cookie, &Callbacks::out);
1184}
1185
1186void DeviceHalAidl::setStreamOutCallback(
1187 void* cookie, const sp<StreamOutHalInterfaceCallback>& cb) {
1188 setCallbackImpl(cookie, &Callbacks::out, cb);
1189}
1190
1191sp<StreamOutHalInterfaceEventCallback> DeviceHalAidl::getStreamOutEventCallback(
1192 void* cookie) {
1193 return getCallbackImpl(cookie, &Callbacks::event);
1194}
1195
1196void DeviceHalAidl::setStreamOutEventCallback(
1197 void* cookie, const sp<StreamOutHalInterfaceEventCallback>& cb) {
1198 setCallbackImpl(cookie, &Callbacks::event, cb);
1199}
1200
1201sp<StreamOutHalInterfaceLatencyModeCallback> DeviceHalAidl::getStreamOutLatencyModeCallback(
1202 void* cookie) {
1203 return getCallbackImpl(cookie, &Callbacks::latency);
1204}
1205
1206void DeviceHalAidl::setStreamOutLatencyModeCallback(
1207 void* cookie, const sp<StreamOutHalInterfaceLatencyModeCallback>& cb) {
1208 setCallbackImpl(cookie, &Callbacks::latency, cb);
1209}
1210
1211template<class C>
1212sp<C> DeviceHalAidl::getCallbackImpl(void* cookie, wp<C> DeviceHalAidl::Callbacks::* field) {
1213 std::lock_guard l(mLock);
1214 if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
1215 return ((it->second).*field).promote();
1216 }
1217 return nullptr;
1218}
1219template<class C>
1220void DeviceHalAidl::setCallbackImpl(
1221 void* cookie, wp<C> DeviceHalAidl::Callbacks::* field, const sp<C>& cb) {
1222 std::lock_guard l(mLock);
1223 if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
1224 (it->second).*field = cb;
1225 }
1226}
1227
Mikhail Naganov31d46652023-01-10 18:29:25 +00001228} // namespace android