blob: fad5ac1d63bf283d28c98a99899e9890ba13f2b1 [file] [log] [blame]
Shunkai Yao51202502022-12-12 06:11:46 +00001/*
2 * Copyright (C) 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "DeviceHalAidl"
Mikhail Naganov89a9f742023-01-30 12:33:18 -080018// #define LOG_NDEBUG 0
Shunkai Yao51202502022-12-12 06:11:46 +000019
Mikhail Naganov5b1eed12023-01-25 11:29:11 -080020#include <algorithm>
21#include <forward_list>
22
Mikhail Naganovdfd594e2023-02-08 16:59:41 -080023#include <aidl/android/hardware/audio/core/BnStreamCallback.h>
24#include <aidl/android/hardware/audio/core/BnStreamOutEventCallback.h>
Mikhail Naganovfab697c2023-01-11 19:33:13 +000025#include <aidl/android/hardware/audio/core/StreamDescriptor.h>
David Li9cf5e622023-03-21 00:51:10 +080026#include <android/binder_enums.h>
27#include <binder/Enums.h>
Mikhail Naganovfab697c2023-01-11 19:33:13 +000028#include <error/expected_utils.h>
29#include <media/AidlConversionCppNdk.h>
30#include <media/AidlConversionUtil.h>
Mikhail Naganov31d46652023-01-10 18:29:25 +000031#include <mediautils/TimeCheck.h>
Mikhail Naganov89a9f742023-01-30 12:33:18 -080032#include <Utils.h>
Mikhail Naganov31d46652023-01-10 18:29:25 +000033#include <utils/Log.h>
Shunkai Yao51202502022-12-12 06:11:46 +000034
Mikhail Naganov31d46652023-01-10 18:29:25 +000035#include "DeviceHalAidl.h"
36#include "StreamHalAidl.h"
37
Mikhail Naganovfab697c2023-01-11 19:33:13 +000038using aidl::android::aidl_utils::statusTFromBinderStatus;
Mikhail Naganov5b1eed12023-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 Naganov89a9f742023-01-30 12:33:18 -080042using aidl::android::media::audio::common::AudioDeviceType;
43using aidl::android::media::audio::common::AudioInputFlags;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -080044using aidl::android::media::audio::common::AudioIoFlags;
Mikhail Naganovdfd594e2023-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 Naganov5b1eed12023-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 Naganov89a9f742023-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 Naganov5b1eed12023-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 Naganov5b1eed12023-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 Naganov5b1eed12023-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 Naganov5b1eed12023-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 Naganov5b1eed12023-01-25 11:29:11 -0800170 TIME_CHECK();
Mikhail Naganov31d46652023-01-10 18:29:25 +0000171 if (mModule == nullptr) return NO_INIT;
Mikhail Naganov5b1eed12023-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 Naganov89a9f742023-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 Naganov5b1eed12023-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 Naganov5b1eed12023-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 Naganov89a9f742023-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 Naganov89a9f742023-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 Naganov89a9f742023-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 Naganov5b1eed12023-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 Naganov89a9f742023-01-30 12:33:18 -0800347 Cleanups* cleanups, AudioConfig* aidlConfig, AudioPortConfig* mixPortConfig,
348 int32_t* nominalLatency) {
Mikhail Naganov5b1eed12023-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 Naganov5b1eed12023-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 Naganov89a9f742023-01-30 12:33:18 -0800375 *nominalLatency = patch.latenciesMs[0];
Mikhail Naganov5b1eed12023-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 Naganovdfd594e2023-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 Naganov5b1eed12023-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 Naganov89a9f742023-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 Naganov5b1eed12023-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 Naganov89a9f742023-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 Naganov5b1eed12023-01-25 11:29:11 -0800527 ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamArguments args;
528 args.portConfigId = mixPortConfig.id;
Mikhail Naganovdfd594e2023-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 Naganov5b1eed12023-01-25 11:29:11 -0800540 args.bufferSizeFrames = aidlConfig.frameCount;
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800541 args.eventCallback = eventCb;
Mikhail Naganov5b1eed12023-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 Naganov89a9f742023-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 Naganovdfd594e2023-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 Naganov5b1eed12023-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 Naganov5b1eed12023-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 Naganov89a9f742023-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 Naganov5b1eed12023-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 Naganov89a9f742023-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 Naganov5b1eed12023-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 Naganov89a9f742023-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 Naganov5b1eed12023-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 Naganov5b1eed12023-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 Naganov89a9f742023-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 Naganov5b1eed12023-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 Naganov5b1eed12023-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 Naganov5b1eed12023-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 Naganov5b1eed12023-01-25 11:29:11 -0800674 }
Mikhail Naganov89a9f742023-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 Naganov5b1eed12023-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 Naganov5b1eed12023-01-25 11:29:11 -0800703 }
704 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000705 return OK;
706}
707
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800708status_t DeviceHalAidl::releaseAudioPatch(audio_patch_handle_t patch) {
Mikhail Naganov89a9f742023-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 Naganov5b1eed12023-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
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800868bool DeviceHalAidl::audioDeviceMatches(const AudioDevice& device, const AudioPort& p) {
869 if (p.ext.getTag() != AudioPortExt::Tag::device) return false;
870 return p.ext.get<AudioPortExt::Tag::device>().device == device;
871}
872
873bool DeviceHalAidl::audioDeviceMatches(const AudioDevice& device, const AudioPortConfig& p) {
874 if (p.ext.getTag() != AudioPortExt::Tag::device) return false;
875 if (device.type.type == AudioDeviceType::IN_DEFAULT) {
876 return p.portId == mDefaultInputPortId;
877 } else if (device.type.type == AudioDeviceType::OUT_DEFAULT) {
878 return p.portId == mDefaultOutputPortId;
879 }
880 return p.ext.get<AudioPortExt::Tag::device>().device == device;
881}
882
Mikhail Naganov1a44bc62023-02-16 17:35:06 -0800883status_t DeviceHalAidl::createPortConfig(
884 const AudioPortConfig& requestedPortConfig, PortConfigs::iterator* result) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800885 TIME_CHECK();
Mikhail Naganov1a44bc62023-02-16 17:35:06 -0800886 AudioPortConfig appliedPortConfig;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800887 bool applied = false;
888 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPortConfig(
Mikhail Naganov1a44bc62023-02-16 17:35:06 -0800889 requestedPortConfig, &appliedPortConfig, &applied)));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800890 if (!applied) {
891 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPortConfig(
Mikhail Naganov1a44bc62023-02-16 17:35:06 -0800892 appliedPortConfig, &appliedPortConfig, &applied)));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800893 if (!applied) {
894 ALOGE("%s: module %s did not apply suggested config %s",
Mikhail Naganov1a44bc62023-02-16 17:35:06 -0800895 __func__, mInstance.c_str(), appliedPortConfig.toString().c_str());
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800896 return NO_INIT;
897 }
898 }
Mikhail Naganov1a44bc62023-02-16 17:35:06 -0800899 auto id = appliedPortConfig.id;
900 auto [it, inserted] = mPortConfigs.emplace(std::move(id), std::move(appliedPortConfig));
901 LOG_ALWAYS_FATAL_IF(!inserted, "%s: port config with id %d already exists",
902 __func__, it->first);
903 *result = it;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800904 return OK;
905}
906
907status_t DeviceHalAidl::findOrCreatePatch(
908 const AudioPatch& requestedPatch, AudioPatch* patch, bool* created) {
909 std::set<int32_t> sourcePortConfigIds(requestedPatch.sourcePortConfigIds.begin(),
910 requestedPatch.sourcePortConfigIds.end());
911 std::set<int32_t> sinkPortConfigIds(requestedPatch.sinkPortConfigIds.begin(),
912 requestedPatch.sinkPortConfigIds.end());
913 return findOrCreatePatch(sourcePortConfigIds, sinkPortConfigIds, patch, created);
914}
915
916status_t DeviceHalAidl::findOrCreatePatch(
917 const std::set<int32_t>& sourcePortConfigIds, const std::set<int32_t>& sinkPortConfigIds,
918 AudioPatch* patch, bool* created) {
919 auto patchIt = findPatch(sourcePortConfigIds, sinkPortConfigIds);
920 if (patchIt == mPatches.end()) {
921 TIME_CHECK();
922 AudioPatch requestedPatch, appliedPatch;
923 requestedPatch.sourcePortConfigIds.insert(requestedPatch.sourcePortConfigIds.end(),
924 sourcePortConfigIds.begin(), sourcePortConfigIds.end());
925 requestedPatch.sinkPortConfigIds.insert(requestedPatch.sinkPortConfigIds.end(),
926 sinkPortConfigIds.begin(), sinkPortConfigIds.end());
927 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPatch(
928 requestedPatch, &appliedPatch)));
929 patchIt = mPatches.insert(mPatches.end(), std::make_pair(appliedPatch.id, appliedPatch));
930 *created = true;
931 } else {
932 *created = false;
933 }
934 *patch = patchIt->second;
935 return OK;
936}
937
938status_t DeviceHalAidl::findOrCreatePortConfig(const AudioDevice& device,
939 AudioPortConfig* portConfig, bool* created) {
940 auto portConfigIt = findPortConfig(device);
941 if (portConfigIt == mPortConfigs.end()) {
942 auto portsIt = findPort(device);
943 if (portsIt == mPorts.end()) {
944 ALOGE("%s: device port for device %s is not found in the module %s",
945 __func__, device.toString().c_str(), mInstance.c_str());
946 return BAD_VALUE;
947 }
948 AudioPortConfig requestedPortConfig;
949 requestedPortConfig.portId = portsIt->first;
Mikhail Naganov1a44bc62023-02-16 17:35:06 -0800950 RETURN_STATUS_IF_ERROR(createPortConfig(requestedPortConfig, &portConfigIt));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800951 *created = true;
952 } else {
953 *created = false;
954 }
955 *portConfig = portConfigIt->second;
956 return OK;
957}
958
959status_t DeviceHalAidl::findOrCreatePortConfig(
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800960 const AudioConfig& config, const std::optional<AudioIoFlags>& flags, int32_t ioHandle,
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800961 AudioSource source, AudioPortConfig* portConfig, bool* created) {
Mikhail Naganov1a44bc62023-02-16 17:35:06 -0800962 // These flags get removed one by one in this order when retrying port finding.
963 static const std::vector<AudioInputFlags> kOptionalInputFlags{
964 AudioInputFlags::FAST, AudioInputFlags::RAW };
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800965 auto portConfigIt = findPortConfig(config, flags, ioHandle);
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800966 if (portConfigIt == mPortConfigs.end() && flags.has_value()) {
Mikhail Naganov1a44bc62023-02-16 17:35:06 -0800967 auto optionalInputFlagsIt = kOptionalInputFlags.begin();
968 AudioIoFlags matchFlags = flags.value();
969 auto portsIt = findPort(config, matchFlags);
970 while (portsIt == mPorts.end() && matchFlags.getTag() == AudioIoFlags::Tag::input
971 && optionalInputFlagsIt != kOptionalInputFlags.end()) {
972 if (!isBitPositionFlagSet(
973 matchFlags.get<AudioIoFlags::Tag::input>(), *optionalInputFlagsIt)) {
974 ++optionalInputFlagsIt;
975 continue;
976 }
977 matchFlags.set<AudioIoFlags::Tag::input>(matchFlags.get<AudioIoFlags::Tag::input>() &
978 ~makeBitPositionFlagMask(*optionalInputFlagsIt++));
979 portsIt = findPort(config, matchFlags);
980 ALOGI("%s: mix port for config %s, flags %s was not found in the module %s, "
981 "retried with flags %s", __func__, config.toString().c_str(),
982 flags.value().toString().c_str(), mInstance.c_str(),
983 matchFlags.toString().c_str());
984 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800985 if (portsIt == mPorts.end()) {
986 ALOGE("%s: mix port for config %s, flags %s is not found in the module %s",
Mikhail Naganov1a44bc62023-02-16 17:35:06 -0800987 __func__, config.toString().c_str(), matchFlags.toString().c_str(),
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800988 mInstance.c_str());
989 return BAD_VALUE;
990 }
991 AudioPortConfig requestedPortConfig;
992 requestedPortConfig.portId = portsIt->first;
993 setPortConfigFromConfig(&requestedPortConfig, config);
Mikhail Naganov1a44bc62023-02-16 17:35:06 -0800994 requestedPortConfig.ext = AudioPortMixExt{ .handle = ioHandle };
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800995 if (matchFlags.getTag() == AudioIoFlags::Tag::input
996 && source != AudioSource::SYS_RESERVED_INVALID) {
997 requestedPortConfig.ext.get<AudioPortExt::Tag::mix>().usecase =
998 AudioPortMixExtUseCase::make<AudioPortMixExtUseCase::Tag::source>(source);
999 }
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001000 RETURN_STATUS_IF_ERROR(createPortConfig(requestedPortConfig, &portConfigIt));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001001 *created = true;
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001002 } else if (!flags.has_value()) {
1003 ALOGW("%s: mix port config for %s, handle %d not found in the module %s, "
1004 "and was not created as flags are not specified",
1005 __func__, config.toString().c_str(), ioHandle, mInstance.c_str());
1006 return BAD_VALUE;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001007 } else {
1008 *created = false;
1009 }
1010 *portConfig = portConfigIt->second;
1011 return OK;
1012}
1013
1014status_t DeviceHalAidl::findOrCreatePortConfig(
1015 const AudioPortConfig& requestedPortConfig, AudioPortConfig* portConfig, bool* created) {
1016 using Tag = AudioPortExt::Tag;
1017 if (requestedPortConfig.ext.getTag() == Tag::mix) {
1018 if (const auto& p = requestedPortConfig;
1019 !p.sampleRate.has_value() || !p.channelMask.has_value() ||
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001020 !p.format.has_value()) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001021 ALOGW("%s: provided mix port config is not fully specified: %s",
1022 __func__, p.toString().c_str());
1023 return BAD_VALUE;
1024 }
1025 AudioConfig config;
1026 setConfigFromPortConfig(&config, requestedPortConfig);
Mikhail Naganovd8d01f72023-03-09 16:24:40 -08001027 AudioSource source = requestedPortConfig.ext.get<Tag::mix>().usecase.getTag() ==
1028 AudioPortMixExtUseCase::Tag::source ?
1029 requestedPortConfig.ext.get<Tag::mix>().usecase.
1030 get<AudioPortMixExtUseCase::Tag::source>() : AudioSource::SYS_RESERVED_INVALID;
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001031 return findOrCreatePortConfig(config, requestedPortConfig.flags,
Mikhail Naganovd8d01f72023-03-09 16:24:40 -08001032 requestedPortConfig.ext.get<Tag::mix>().handle, source, portConfig, created);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001033 } else if (requestedPortConfig.ext.getTag() == Tag::device) {
1034 return findOrCreatePortConfig(
1035 requestedPortConfig.ext.get<Tag::device>().device, portConfig, created);
1036 }
1037 ALOGW("%s: unsupported audio port config: %s",
1038 __func__, requestedPortConfig.toString().c_str());
1039 return BAD_VALUE;
1040}
1041
1042DeviceHalAidl::Patches::iterator DeviceHalAidl::findPatch(
1043 const std::set<int32_t>& sourcePortConfigIds, const std::set<int32_t>& sinkPortConfigIds) {
1044 return std::find_if(mPatches.begin(), mPatches.end(),
1045 [&](const auto& pair) {
1046 const auto& p = pair.second;
1047 std::set<int32_t> patchSrcs(
1048 p.sourcePortConfigIds.begin(), p.sourcePortConfigIds.end());
1049 std::set<int32_t> patchSinks(
1050 p.sinkPortConfigIds.begin(), p.sinkPortConfigIds.end());
1051 return sourcePortConfigIds == patchSrcs && sinkPortConfigIds == patchSinks; });
1052}
1053
1054DeviceHalAidl::Ports::iterator DeviceHalAidl::findPort(const AudioDevice& device) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001055 if (device.type.type == AudioDeviceType::IN_DEFAULT) {
1056 return mPorts.find(mDefaultInputPortId);
1057 } else if (device.type.type == AudioDeviceType::OUT_DEFAULT) {
1058 return mPorts.find(mDefaultOutputPortId);
1059 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001060 return std::find_if(mPorts.begin(), mPorts.end(),
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001061 [&](const auto& pair) { return audioDeviceMatches(device, pair.second); });
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001062}
1063
1064DeviceHalAidl::Ports::iterator DeviceHalAidl::findPort(
1065 const AudioConfig& config, const AudioIoFlags& flags) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001066 auto matcher = [&](const auto& pair) {
1067 const auto& p = pair.second;
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001068 return p.ext.getTag() == AudioPortExt::Tag::mix &&
1069 p.flags == flags &&
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001070 std::find_if(p.profiles.begin(), p.profiles.end(),
1071 [&](const auto& prof) {
1072 return prof.format == config.base.format &&
1073 std::find(prof.channelMasks.begin(), prof.channelMasks.end(),
1074 config.base.channelMask) != prof.channelMasks.end() &&
1075 std::find(prof.sampleRates.begin(), prof.sampleRates.end(),
1076 config.base.sampleRate) != prof.sampleRates.end();
1077 }) != p.profiles.end(); };
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001078 return std::find_if(mPorts.begin(), mPorts.end(), matcher);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001079}
1080
1081DeviceHalAidl::PortConfigs::iterator DeviceHalAidl::findPortConfig(const AudioDevice& device) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001082 return std::find_if(mPortConfigs.begin(), mPortConfigs.end(),
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001083 [&](const auto& pair) { return audioDeviceMatches(device, pair.second); });
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001084}
1085
1086DeviceHalAidl::PortConfigs::iterator DeviceHalAidl::findPortConfig(
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001087 const AudioConfig& config, const std::optional<AudioIoFlags>& flags, int32_t ioHandle) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001088 using Tag = AudioPortExt::Tag;
1089 return std::find_if(mPortConfigs.begin(), mPortConfigs.end(),
1090 [&](const auto& pair) {
1091 const auto& p = pair.second;
1092 LOG_ALWAYS_FATAL_IF(p.ext.getTag() == Tag::mix &&
1093 !p.sampleRate.has_value() || !p.channelMask.has_value() ||
1094 !p.format.has_value() || !p.flags.has_value(),
1095 "%s: stored mix port config is not fully specified: %s",
1096 __func__, p.toString().c_str());
1097 return p.ext.getTag() == Tag::mix &&
1098 isConfigEqualToPortConfig(config, p) &&
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001099 (!flags.has_value() || p.flags.value() == flags.value()) &&
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001100 p.ext.template get<Tag::mix>().handle == ioHandle; });
1101}
1102/*
1103DeviceHalAidl::PortConfigs::iterator DeviceHalAidl::findPortConfig(
1104 const AudioPortConfig& portConfig) {
1105 using Tag = AudioPortExt::Tag;
1106 if (portConfig.ext.getTag() == Tag::mix) {
1107 return std::find_if(mPortConfigs.begin(), mPortConfigs.end(),
1108 [&](const auto& pair) {
1109 const auto& p = pair.second;
1110 LOG_ALWAYS_FATAL_IF(p.ext.getTag() == Tag::mix &&
1111 !p.sampleRate.has_value() || !p.channelMask.has_value() ||
1112 !p.format.has_value() || !p.flags.has_value(),
1113 "%s: stored mix port config is not fully specified: %s",
1114 __func__, p.toString().c_str());
1115 return p.ext.getTag() == Tag::mix &&
1116 (!portConfig.sampleRate.has_value() ||
1117 p.sampleRate == portConfig.sampleRate) &&
1118 (!portConfig.channelMask.has_value() ||
1119 p.channelMask == portConfig.channelMask) &&
1120 (!portConfig.format.has_value() || p.format == portConfig.format) &&
1121 (!portConfig.flags.has_value() || p.flags == portConfig.flags) &&
1122 p.ext.template get<Tag::mix>().handle ==
1123 portConfig.ext.template get<Tag::mix>().handle; });
1124 } else if (portConfig.ext.getTag() == Tag::device) {
1125 return findPortConfig(portConfig.ext.get<Tag::device>().device);
1126 }
1127 return mPortConfigs.end();
1128}
1129*/
1130void DeviceHalAidl::resetPatch(int32_t patchId) {
1131 if (auto it = mPatches.find(patchId); it != mPatches.end()) {
1132 mPatches.erase(it);
1133 TIME_CHECK();
1134 if (ndk::ScopedAStatus status = mModule->resetAudioPatch(patchId); !status.isOk()) {
1135 ALOGE("%s: error while resetting patch %d: %s",
1136 __func__, patchId, status.getDescription().c_str());
1137 }
1138 return;
1139 }
1140 ALOGE("%s: patch id %d not found", __func__, patchId);
1141}
1142
1143void DeviceHalAidl::resetPortConfig(int32_t portConfigId) {
1144 if (auto it = mPortConfigs.find(portConfigId); it != mPortConfigs.end()) {
1145 mPortConfigs.erase(it);
1146 TIME_CHECK();
1147 if (ndk::ScopedAStatus status = mModule->resetAudioPortConfig(portConfigId);
1148 !status.isOk()) {
1149 ALOGE("%s: error while resetting port config %d: %s",
1150 __func__, portConfigId, status.getDescription().c_str());
1151 }
1152 return;
1153 }
1154 ALOGE("%s: port config id %d not found", __func__, portConfigId);
1155}
1156
Mikhail Naganovdfd594e2023-02-08 16:59:41 -08001157void DeviceHalAidl::clearCallbacks(void* cookie) {
1158 std::lock_guard l(mLock);
1159 mCallbacks.erase(cookie);
1160}
1161
1162sp<StreamOutHalInterfaceCallback> DeviceHalAidl::getStreamOutCallback(void* cookie) {
1163 return getCallbackImpl(cookie, &Callbacks::out);
1164}
1165
1166void DeviceHalAidl::setStreamOutCallback(
1167 void* cookie, const sp<StreamOutHalInterfaceCallback>& cb) {
1168 setCallbackImpl(cookie, &Callbacks::out, cb);
1169}
1170
1171sp<StreamOutHalInterfaceEventCallback> DeviceHalAidl::getStreamOutEventCallback(
1172 void* cookie) {
1173 return getCallbackImpl(cookie, &Callbacks::event);
1174}
1175
1176void DeviceHalAidl::setStreamOutEventCallback(
1177 void* cookie, const sp<StreamOutHalInterfaceEventCallback>& cb) {
1178 setCallbackImpl(cookie, &Callbacks::event, cb);
1179}
1180
1181sp<StreamOutHalInterfaceLatencyModeCallback> DeviceHalAidl::getStreamOutLatencyModeCallback(
1182 void* cookie) {
1183 return getCallbackImpl(cookie, &Callbacks::latency);
1184}
1185
1186void DeviceHalAidl::setStreamOutLatencyModeCallback(
1187 void* cookie, const sp<StreamOutHalInterfaceLatencyModeCallback>& cb) {
1188 setCallbackImpl(cookie, &Callbacks::latency, cb);
1189}
1190
1191template<class C>
1192sp<C> DeviceHalAidl::getCallbackImpl(void* cookie, wp<C> DeviceHalAidl::Callbacks::* field) {
1193 std::lock_guard l(mLock);
1194 if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
1195 return ((it->second).*field).promote();
1196 }
1197 return nullptr;
1198}
1199template<class C>
1200void DeviceHalAidl::setCallbackImpl(
1201 void* cookie, wp<C> DeviceHalAidl::Callbacks::* field, const sp<C>& cb) {
1202 std::lock_guard l(mLock);
1203 if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
1204 (it->second).*field = cb;
1205 }
1206}
1207
Mikhail Naganov31d46652023-01-10 18:29:25 +00001208} // namespace android