blob: 62b9ec79845fa6e7f8a006fe0eb646d366f27ff1 [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 Naganovfab697c2023-01-11 19:33:13 +000023#include <aidl/android/hardware/audio/core/StreamDescriptor.h>
24#include <error/expected_utils.h>
25#include <media/AidlConversionCppNdk.h>
26#include <media/AidlConversionUtil.h>
Mikhail Naganov31d46652023-01-10 18:29:25 +000027#include <mediautils/TimeCheck.h>
Mikhail Naganov8bd806e2023-01-30 12:33:18 -080028#include <Utils.h>
Mikhail Naganov31d46652023-01-10 18:29:25 +000029#include <utils/Log.h>
Shunkai Yao51202502022-12-12 06:11:46 +000030
Mikhail Naganov31d46652023-01-10 18:29:25 +000031#include "DeviceHalAidl.h"
32#include "StreamHalAidl.h"
33
Mikhail Naganovfab697c2023-01-11 19:33:13 +000034using aidl::android::aidl_utils::statusTFromBinderStatus;
Mikhail Naganovf56ce782023-01-25 11:29:11 -080035using aidl::android::media::audio::common::AudioConfig;
36using aidl::android::media::audio::common::AudioDevice;
Mikhail Naganov8bd806e2023-01-30 12:33:18 -080037using aidl::android::media::audio::common::AudioDeviceType;
38using aidl::android::media::audio::common::AudioInputFlags;
Mikhail Naganovf56ce782023-01-25 11:29:11 -080039using aidl::android::media::audio::common::AudioIoFlags;
Mikhail Naganovfab697c2023-01-11 19:33:13 +000040using aidl::android::media::audio::common::AudioMode;
Mikhail Naganovf56ce782023-01-25 11:29:11 -080041using aidl::android::media::audio::common::AudioOutputFlags;
42using aidl::android::media::audio::common::AudioPort;
43using aidl::android::media::audio::common::AudioPortConfig;
Mikhail Naganov8bd806e2023-01-30 12:33:18 -080044using aidl::android::media::audio::common::AudioPortDeviceExt;
Mikhail Naganovf56ce782023-01-25 11:29:11 -080045using aidl::android::media::audio::common::AudioPortExt;
46using aidl::android::media::audio::common::AudioSource;
47using aidl::android::media::audio::common::Int;
Mikhail Naganovfab697c2023-01-11 19:33:13 +000048using aidl::android::media::audio::common::Float;
Mikhail Naganovf56ce782023-01-25 11:29:11 -080049using aidl::android::hardware::audio::common::RecordTrackMetadata;
50using aidl::android::hardware::audio::core::AudioPatch;
Mikhail Naganovfab697c2023-01-11 19:33:13 +000051using aidl::android::hardware::audio::core::IModule;
52using aidl::android::hardware::audio::core::ITelephony;
53using aidl::android::hardware::audio::core::StreamDescriptor;
Vlad Popa03bd5bc2023-01-17 16:16:51 +010054using aidl::android::hardware::audio::core::sounddose::ISoundDose;
Mikhail Naganov8bd806e2023-01-30 12:33:18 -080055using android::hardware::audio::common::getFrameSizeInBytes;
56using android::hardware::audio::common::isBitPositionFlagSet;
57using android::hardware::audio::common::makeBitPositionFlagMask;
Mikhail Naganov31d46652023-01-10 18:29:25 +000058
59namespace android {
60
Mikhail Naganovf56ce782023-01-25 11:29:11 -080061namespace {
62
63bool isConfigEqualToPortConfig(const AudioConfig& config, const AudioPortConfig& portConfig) {
64 return portConfig.sampleRate.value().value == config.base.sampleRate &&
65 portConfig.channelMask.value() == config.base.channelMask &&
66 portConfig.format.value() == config.base.format;
67}
68
69void setConfigFromPortConfig(AudioConfig* config, const AudioPortConfig& portConfig) {
70 config->base.sampleRate = portConfig.sampleRate.value().value;
71 config->base.channelMask = portConfig.channelMask.value();
72 config->base.format = portConfig.format.value();
73}
74
75void setPortConfigFromConfig(AudioPortConfig* portConfig, const AudioConfig& config) {
76 portConfig->sampleRate = Int{ .value = config.base.sampleRate };
77 portConfig->channelMask = config.base.channelMask;
78 portConfig->format = config.base.format;
79}
80
81} // namespace
82
Mikhail Naganov31d46652023-01-10 18:29:25 +000083status_t DeviceHalAidl::getSupportedDevices(uint32_t*) {
84 // Obsolete.
85 return INVALID_OPERATION;
Shunkai Yao51202502022-12-12 06:11:46 +000086}
87
88status_t DeviceHalAidl::initCheck() {
Mikhail Naganovf56ce782023-01-25 11:29:11 -080089 TIME_CHECK();
Mikhail Naganov31d46652023-01-10 18:29:25 +000090 if (mModule == nullptr) return NO_INIT;
Mikhail Naganovf56ce782023-01-25 11:29:11 -080091 std::vector<AudioPort> ports;
92 RETURN_STATUS_IF_ERROR(
93 statusTFromBinderStatus(mModule->getAudioPorts(&ports)));
94 ALOGW_IF(ports.empty(), "%s: module %s returned an empty list of audio ports",
95 __func__, mInstance.c_str());
96 std::transform(ports.begin(), ports.end(), std::inserter(mPorts, mPorts.end()),
97 [](const auto& p) { return std::make_pair(p.id, p); });
Mikhail Naganov8bd806e2023-01-30 12:33:18 -080098 mDefaultInputPortId = mDefaultOutputPortId = -1;
99 const int defaultDeviceFlag = 1 << AudioPortDeviceExt::FLAG_INDEX_DEFAULT_DEVICE;
100 for (const auto& pair : mPorts) {
101 const auto& p = pair.second;
102 if (p.ext.getTag() == AudioPortExt::Tag::device &&
103 (p.ext.get<AudioPortExt::Tag::device>().flags & defaultDeviceFlag) != 0) {
104 if (p.flags.getTag() == AudioIoFlags::Tag::input) {
105 mDefaultInputPortId = p.id;
106 } else if (p.flags.getTag() == AudioIoFlags::Tag::output) {
107 mDefaultOutputPortId = p.id;
108 }
109 }
110 }
111 ALOGI("%s: module %s default port ids: input %d, output %d",
112 __func__, mInstance.c_str(), mDefaultInputPortId, mDefaultOutputPortId);
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800113 std::vector<AudioPortConfig> portConfigs;
114 RETURN_STATUS_IF_ERROR(
115 statusTFromBinderStatus(mModule->getAudioPortConfigs(&portConfigs))); // OK if empty
116 std::transform(portConfigs.begin(), portConfigs.end(),
117 std::inserter(mPortConfigs, mPortConfigs.end()),
118 [](const auto& p) { return std::make_pair(p.id, p); });
119 std::vector<AudioPatch> patches;
120 RETURN_STATUS_IF_ERROR(
121 statusTFromBinderStatus(mModule->getAudioPatches(&patches))); // OK if empty
122 std::transform(patches.begin(), patches.end(),
123 std::inserter(mPatches, mPatches.end()),
124 [](const auto& p) { return std::make_pair(p.id, p); });
Shunkai Yao51202502022-12-12 06:11:46 +0000125 return OK;
126}
127
128status_t DeviceHalAidl::setVoiceVolume(float volume) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000129 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000130 if (!mModule) return NO_INIT;
131 std::shared_ptr<ITelephony> telephony;
132 if (ndk::ScopedAStatus status = mModule->getTelephony(&telephony);
133 status.isOk() && telephony != nullptr) {
134 ITelephony::TelecomConfig inConfig{ .voiceVolume = Float{volume} }, outConfig;
135 RETURN_STATUS_IF_ERROR(
136 statusTFromBinderStatus(telephony->setTelecomConfig(inConfig, &outConfig)));
137 ALOGW_IF(outConfig.voiceVolume.has_value() && volume != outConfig.voiceVolume.value().value,
138 "%s: the resulting voice volume %f is not the same as requested %f",
139 __func__, outConfig.voiceVolume.value().value, volume);
140 }
141 return INVALID_OPERATION;
Shunkai Yao51202502022-12-12 06:11:46 +0000142}
143
144status_t DeviceHalAidl::setMasterVolume(float volume) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000145 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000146 if (!mModule) return NO_INIT;
147 return statusTFromBinderStatus(mModule->setMasterVolume(volume));
Shunkai Yao51202502022-12-12 06:11:46 +0000148}
149
150status_t DeviceHalAidl::getMasterVolume(float *volume) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000151 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000152 if (!mModule) return NO_INIT;
153 return statusTFromBinderStatus(mModule->getMasterVolume(volume));
Shunkai Yao51202502022-12-12 06:11:46 +0000154}
155
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000156status_t DeviceHalAidl::setMode(audio_mode_t mode) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000157 TIME_CHECK();
158 if (!mModule) return NO_INIT;
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000159 AudioMode audioMode = VALUE_OR_FATAL(::aidl::android::legacy2aidl_audio_mode_t_AudioMode(mode));
160 std::shared_ptr<ITelephony> telephony;
161 if (ndk::ScopedAStatus status = mModule->getTelephony(&telephony);
162 status.isOk() && telephony != nullptr) {
163 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(telephony->switchAudioMode(audioMode)));
164 }
165 return statusTFromBinderStatus(mModule->updateAudioMode(audioMode));
Shunkai Yao51202502022-12-12 06:11:46 +0000166}
167
168status_t DeviceHalAidl::setMicMute(bool state) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000169 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000170 if (!mModule) return NO_INIT;
171 return statusTFromBinderStatus(mModule->setMicMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000172}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000173
Shunkai Yao51202502022-12-12 06:11:46 +0000174status_t DeviceHalAidl::getMicMute(bool *state) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000175 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000176 if (!mModule) return NO_INIT;
177 return statusTFromBinderStatus(mModule->getMicMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000178}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000179
Shunkai Yao51202502022-12-12 06:11:46 +0000180status_t DeviceHalAidl::setMasterMute(bool state) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000181 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000182 if (!mModule) return NO_INIT;
183 return statusTFromBinderStatus(mModule->setMasterMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000184}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000185
Shunkai Yao51202502022-12-12 06:11:46 +0000186status_t DeviceHalAidl::getMasterMute(bool *state) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000187 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000188 if (!mModule) return NO_INIT;
189 return statusTFromBinderStatus(mModule->getMasterMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000190}
191
Mikhail Naganov31d46652023-01-10 18:29:25 +0000192status_t DeviceHalAidl::setParameters(const String8& kvPairs __unused) {
193 TIME_CHECK();
194 if (!mModule) return NO_INIT;
195 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000196 return OK;
197}
198
Mikhail Naganov31d46652023-01-10 18:29:25 +0000199status_t DeviceHalAidl::getParameters(const String8& keys __unused, String8 *values) {
200 TIME_CHECK();
201 values->clear();
202 if (!mModule) return NO_INIT;
203 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000204 return OK;
205}
206
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800207namespace {
208
209class Cleanup {
210 public:
211 typedef void (DeviceHalAidl::*Cleaner)(int32_t);
212
213 Cleanup(DeviceHalAidl* device, Cleaner cleaner, int32_t id) :
214 mDevice(device), mCleaner(cleaner), mId(id) {}
215 ~Cleanup() { clean(); }
216 void clean() {
217 if (mDevice != nullptr) (mDevice->*mCleaner)(mId);
218 disarm();
219 }
220 void disarm() { mDevice = nullptr; }
221
222 private:
223 DeviceHalAidl* mDevice;
224 const Cleaner mCleaner;
225 const int32_t mId;
226};
227
228} // namespace
229
230// Since the order of container elements destruction is unspecified,
231// ensure that cleanups are performed from the most recent one and upwards.
232// This is the same as if there were individual Cleanup instances on the stack,
233// however the bonus is that we can disarm all of them with just one statement.
234class DeviceHalAidl::Cleanups : public std::forward_list<Cleanup> {
235 public:
236 ~Cleanups() { for (auto& c : *this) c.clean(); }
237 void disarmAll() { for (auto& c : *this) c.disarm(); }
238};
239
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800240status_t DeviceHalAidl::getInputBufferSize(const struct audio_config* config, size_t* size) {
241 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
242 if (size == nullptr) return BAD_VALUE;
243 TIME_CHECK();
244 if (!mModule) return NO_INIT;
245 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
246 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, true /*isInput*/));
247 AudioDevice aidlDevice;
248 aidlDevice.type.type = AudioDeviceType::IN_DEFAULT;
249 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::input>(0);
250 AudioPortConfig mixPortConfig;
251 Cleanups cleanups;
252 audio_config writableConfig = *config;
253 int32_t nominalLatency;
254 RETURN_STATUS_IF_ERROR(prepareToOpenStream(0 /*handle*/, aidlDevice, aidlFlags, &writableConfig,
255 &cleanups, &aidlConfig, &mixPortConfig, &nominalLatency));
256 *size = aidlConfig.frameCount *
257 getFrameSizeInBytes(aidlConfig.base.format, aidlConfig.base.channelMask);
258 // Do not disarm cleanups to release temporary port configs.
259 return OK;
260}
261
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800262status_t DeviceHalAidl::prepareToOpenStream(
263 int32_t aidlHandle, const AudioDevice& aidlDevice, const AudioIoFlags& aidlFlags,
264 struct audio_config* config,
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800265 Cleanups* cleanups, AudioConfig* aidlConfig, AudioPortConfig* mixPortConfig,
266 int32_t* nominalLatency) {
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800267 const bool isInput = aidlFlags.getTag() == AudioIoFlags::Tag::input;
268 // Find / create AudioPortConfigs for the device port and the mix port,
269 // then find / create a patch between them, and open a stream on the mix port.
270 AudioPortConfig devicePortConfig;
271 bool created = false;
272 RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(aidlDevice, &devicePortConfig, &created));
273 if (created) {
274 cleanups->emplace_front(this, &DeviceHalAidl::resetPortConfig, devicePortConfig.id);
275 }
276 RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(*aidlConfig, aidlFlags, aidlHandle,
277 mixPortConfig, &created));
278 if (created) {
279 cleanups->emplace_front(this, &DeviceHalAidl::resetPortConfig, mixPortConfig->id);
280 }
281 setConfigFromPortConfig(aidlConfig, *mixPortConfig);
282 AudioPatch patch;
283 if (isInput) {
284 RETURN_STATUS_IF_ERROR(findOrCreatePatch(
285 {devicePortConfig.id}, {mixPortConfig->id}, &patch, &created));
286 } else {
287 RETURN_STATUS_IF_ERROR(findOrCreatePatch(
288 {mixPortConfig->id}, {devicePortConfig.id}, &patch, &created));
289 }
290 if (created) {
291 cleanups->emplace_front(this, &DeviceHalAidl::resetPatch, patch.id);
292 }
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800293 *nominalLatency = patch.latenciesMs[0];
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800294 if (aidlConfig->frameCount <= 0) {
295 aidlConfig->frameCount = patch.minimumStreamBufferSizeFrames;
296 }
297 *config = VALUE_OR_RETURN_STATUS(
298 ::aidl::android::aidl2legacy_AudioConfig_audio_config_t(*aidlConfig, isInput));
299 return OK;
300}
301
Mikhail Naganov31d46652023-01-10 18:29:25 +0000302status_t DeviceHalAidl::openOutputStream(
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800303 audio_io_handle_t handle, audio_devices_t devices,
304 audio_output_flags_t flags, struct audio_config* config,
305 const char* address,
Mikhail Naganov31d46652023-01-10 18:29:25 +0000306 sp<StreamOutHalInterface>* outStream) {
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800307 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000308 if (!outStream || !config) {
309 return BAD_VALUE;
310 }
311 TIME_CHECK();
312 if (!mModule) return NO_INIT;
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800313 int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
314 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(handle));
315 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
316 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, false /*isInput*/));
317 AudioDevice aidlDevice = VALUE_OR_RETURN_STATUS(
318 ::aidl::android::legacy2aidl_audio_device_AudioDevice(devices, address));
319 int32_t aidlOutputFlags = VALUE_OR_RETURN_STATUS(
320 ::aidl::android::legacy2aidl_audio_output_flags_t_int32_t_mask(flags));
321 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::output>(aidlOutputFlags);
322 AudioPortConfig mixPortConfig;
323 Cleanups cleanups;
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800324 int32_t nominalLatency;
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800325 RETURN_STATUS_IF_ERROR(prepareToOpenStream(aidlHandle, aidlDevice, aidlFlags, config,
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800326 &cleanups, &aidlConfig, &mixPortConfig, &nominalLatency));
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800327 ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamArguments args;
328 args.portConfigId = mixPortConfig.id;
329 args.offloadInfo = aidlConfig.offloadInfo;
330 args.bufferSizeFrames = aidlConfig.frameCount;
331 ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamReturn ret;
332 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openOutputStream(args, &ret)));
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800333 StreamContextAidl context(ret.desc);
334 if (!context.isValid()) {
335 ALOGE("%s: Failed to created a valid stream context from the descriptor: %s",
336 __func__, ret.desc.toString().c_str());
337 return NO_INIT;
338 }
339 *outStream = sp<StreamOutHalAidl>::make(*config, std::move(context), nominalLatency,
340 std::move(ret.stream));
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800341 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000342 return OK;
343}
344
Mikhail Naganov31d46652023-01-10 18:29:25 +0000345status_t DeviceHalAidl::openInputStream(
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800346 audio_io_handle_t handle, audio_devices_t devices,
347 struct audio_config* config, audio_input_flags_t flags,
348 const char* address, audio_source_t source,
349 audio_devices_t outputDevice, const char* outputDeviceAddress,
Mikhail Naganov31d46652023-01-10 18:29:25 +0000350 sp<StreamInHalInterface>* inStream) {
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800351 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000352 if (!inStream || !config) {
353 return BAD_VALUE;
354 }
355 TIME_CHECK();
356 if (!mModule) return NO_INIT;
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800357 int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
358 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(handle));
359 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
360 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, true /*isInput*/));
361 AudioDevice aidlDevice = VALUE_OR_RETURN_STATUS(
362 ::aidl::android::legacy2aidl_audio_device_AudioDevice(devices, address));
363 int32_t aidlInputFlags = VALUE_OR_RETURN_STATUS(
364 ::aidl::android::legacy2aidl_audio_input_flags_t_int32_t_mask(flags));
365 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::input>(aidlInputFlags);
366 AudioSource aidlSource = VALUE_OR_RETURN_STATUS(
367 ::aidl::android::legacy2aidl_audio_source_t_AudioSource(source));
368 AudioPortConfig mixPortConfig;
369 Cleanups cleanups;
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800370 int32_t nominalLatency;
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800371 RETURN_STATUS_IF_ERROR(prepareToOpenStream(aidlHandle, aidlDevice, aidlFlags, config,
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800372 &cleanups, &aidlConfig, &mixPortConfig, &nominalLatency));
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800373 ::aidl::android::hardware::audio::core::IModule::OpenInputStreamArguments args;
374 args.portConfigId = mixPortConfig.id;
375 RecordTrackMetadata aidlTrackMetadata{
376 .source = aidlSource, .gain = 1, .channelMask = aidlConfig.base.channelMask };
377 if (outputDevice != AUDIO_DEVICE_NONE) {
378 aidlTrackMetadata.destinationDevice = VALUE_OR_RETURN_STATUS(
379 ::aidl::android::legacy2aidl_audio_device_AudioDevice(
380 outputDevice, outputDeviceAddress));
381 }
382 args.sinkMetadata.tracks.push_back(std::move(aidlTrackMetadata));
383 args.bufferSizeFrames = aidlConfig.frameCount;
384 ::aidl::android::hardware::audio::core::IModule::OpenInputStreamReturn ret;
385 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openInputStream(args, &ret)));
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800386 StreamContextAidl context(ret.desc);
387 if (!context.isValid()) {
388 ALOGE("%s: Failed to created a valid stream context from the descriptor: %s",
389 __func__, ret.desc.toString().c_str());
390 return NO_INIT;
391 }
392 *inStream = sp<StreamInHalAidl>::make(*config, std::move(context), nominalLatency,
393 std::move(ret.stream));
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800394 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000395 return OK;
396}
397
398status_t DeviceHalAidl::supportsAudioPatches(bool* supportsPatches) {
399 *supportsPatches = true;
400 return OK;
401}
402
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800403status_t DeviceHalAidl::createAudioPatch(unsigned int num_sources,
404 const struct audio_port_config* sources,
405 unsigned int num_sinks,
406 const struct audio_port_config* sinks,
407 audio_patch_handle_t* patch) {
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800408 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000409 TIME_CHECK();
410 if (!mModule) return NO_INIT;
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800411 if (num_sinks > AUDIO_PATCH_PORTS_MAX || num_sources > AUDIO_PATCH_PORTS_MAX ||
412 sources == nullptr || sinks == nullptr || patch == nullptr) {
413 return BAD_VALUE;
414 }
415 // Note that the patch handle (*patch) is provided by the framework.
416 // In tests it's possible that its value is AUDIO_PATCH_HANDLE_NONE.
417
418 // Upon conversion, mix port configs contain audio configuration, while
419 // device port configs contain device address. This data is used to find
420 // or create HAL configs.
421 std::vector<AudioPortConfig> aidlSources, aidlSinks;
422 for (unsigned int i = 0; i < num_sources; ++i) {
423 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
424 sources[i].role, sources[i].type)) ==
425 ::aidl::android::AudioPortDirection::INPUT;
426 aidlSources.push_back(VALUE_OR_RETURN_STATUS(
427 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
428 sources[i], isInput, 0)));
429 }
430 for (unsigned int i = 0; i < num_sinks; ++i) {
431 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
432 sinks[i].role, sinks[i].type)) ==
433 ::aidl::android::AudioPortDirection::INPUT;
434 aidlSinks.push_back(VALUE_OR_RETURN_STATUS(
435 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
436 sinks[i], isInput, 0)));
437 }
438 Cleanups cleanups;
439 auto existingPatchIt = mPatches.end();
440 auto fwkHandlesIt = *patch != AUDIO_PATCH_HANDLE_NONE ?
441 mFwkHandles.find(*patch) : mFwkHandles.end();
442 AudioPatch aidlPatch;
443 if (fwkHandlesIt != mFwkHandles.end()) {
444 existingPatchIt = mPatches.find(fwkHandlesIt->second);
445 if (existingPatchIt != mPatches.end()) {
446 aidlPatch = existingPatchIt->second;
447 aidlPatch.sourcePortConfigIds.clear();
448 aidlPatch.sinkPortConfigIds.clear();
449 }
450 }
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800451 ALOGD("%s: sources: %s, sinks: %s",
452 __func__, ::android::internal::ToString(aidlSources).c_str(),
453 ::android::internal::ToString(aidlSinks).c_str());
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800454 auto fillPortConfigs = [&](
455 const std::vector<AudioPortConfig>& configs, std::vector<int32_t>* ids) -> status_t {
456 for (const auto& s : configs) {
457 AudioPortConfig portConfig;
458 bool created = false;
459 RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(s, &portConfig, &created));
460 if (created) {
461 cleanups.emplace_front(this, &DeviceHalAidl::resetPortConfig, portConfig.id);
462 }
463 ids->push_back(portConfig.id);
464 }
465 return OK;
466 };
467 RETURN_STATUS_IF_ERROR(fillPortConfigs(aidlSources, &aidlPatch.sourcePortConfigIds));
468 RETURN_STATUS_IF_ERROR(fillPortConfigs(aidlSinks, &aidlPatch.sinkPortConfigIds));
469 if (existingPatchIt != mPatches.end()) {
470 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
471 mModule->setAudioPatch(aidlPatch, &aidlPatch)));
472 existingPatchIt->second = aidlPatch;
473 } else {
474 bool created = false;
475 RETURN_STATUS_IF_ERROR(findOrCreatePatch(aidlPatch, &aidlPatch, &created));
476 // Since no cleanup of the patch is needed, 'created' is ignored.
477 if (fwkHandlesIt != mFwkHandles.end()) {
478 fwkHandlesIt->second = aidlPatch.id;
479 // Patch handle (*patch) stays the same.
480 } else {
481 if (*patch == AUDIO_PATCH_HANDLE_NONE) {
482 // This isn't good as the module can't provide a handle which is really unique.
483 // However, this situation should only happen in tests.
484 *patch = aidlPatch.id;
485 LOG_ALWAYS_FATAL_IF(mFwkHandles.count(*patch) > 0,
486 "%s: patch id %d clashes with another framework patch handle",
487 __func__, *patch);
488 }
489 mFwkHandles.emplace(*patch, aidlPatch.id);
490 }
491 }
492 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000493 return OK;
494}
495
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800496status_t DeviceHalAidl::releaseAudioPatch(audio_patch_handle_t patch) {
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800497 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000498 TIME_CHECK();
499 if (!mModule) return NO_INIT;
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800500 auto idMapIt = mFwkHandles.find(patch);
501 if (idMapIt == mFwkHandles.end()) {
502 return BAD_VALUE;
503 }
504 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->resetAudioPatch(idMapIt->second)));
505 mFwkHandles.erase(idMapIt);
Shunkai Yao51202502022-12-12 06:11:46 +0000506 return OK;
507}
508
Mikhail Naganov31d46652023-01-10 18:29:25 +0000509status_t DeviceHalAidl::getAudioPort(struct audio_port* port __unused) {
510 TIME_CHECK();
511 ALOGE("%s not implemented yet", __func__);
512 return INVALID_OPERATION;
513}
514
515status_t DeviceHalAidl::getAudioPort(struct audio_port_v7 *port __unused) {
516 TIME_CHECK();
517 ALOGE("%s not implemented yet", __func__);
518 return INVALID_OPERATION;
519}
520
521status_t DeviceHalAidl::setAudioPortConfig(const struct audio_port_config* config __unused) {
522 TIME_CHECK();
523 if (!mModule) return NO_INIT;
524 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000525 return OK;
526}
527
528status_t DeviceHalAidl::getMicrophones(
Mikhail Naganov31d46652023-01-10 18:29:25 +0000529 std::vector<audio_microphone_characteristic_t>* microphones __unused) {
530 TIME_CHECK();
531 if (!mModule) return NO_INIT;
532 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000533 return OK;
534}
535
Mikhail Naganov31d46652023-01-10 18:29:25 +0000536status_t DeviceHalAidl::addDeviceEffect(audio_port_handle_t device __unused,
537 sp<EffectHalInterface> effect) {
Shunkai Yao51202502022-12-12 06:11:46 +0000538 if (!effect) {
539 return BAD_VALUE;
540 }
Mikhail Naganov31d46652023-01-10 18:29:25 +0000541 TIME_CHECK();
542 if (!mModule) return NO_INIT;
543 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000544 return OK;
545}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000546status_t DeviceHalAidl::removeDeviceEffect(audio_port_handle_t device __unused,
Shunkai Yao51202502022-12-12 06:11:46 +0000547 sp<EffectHalInterface> effect) {
548 if (!effect) {
549 return BAD_VALUE;
550 }
Mikhail Naganov31d46652023-01-10 18:29:25 +0000551 TIME_CHECK();
552 if (!mModule) return NO_INIT;
553 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000554 return OK;
555}
556
557status_t DeviceHalAidl::getMmapPolicyInfos(
558 media::audio::common::AudioMMapPolicyType policyType __unused,
559 std::vector<media::audio::common::AudioMMapPolicyInfo>* policyInfos __unused) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000560 TIME_CHECK();
Shunkai Yao51202502022-12-12 06:11:46 +0000561 ALOGE("%s not implemented yet", __func__);
562 return OK;
563}
564
565int32_t DeviceHalAidl::getAAudioMixerBurstCount() {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000566 TIME_CHECK();
Shunkai Yao51202502022-12-12 06:11:46 +0000567 ALOGE("%s not implemented yet", __func__);
568 return OK;
569}
570
571int32_t DeviceHalAidl::getAAudioHardwareBurstMinUsec() {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000572 TIME_CHECK();
Shunkai Yao51202502022-12-12 06:11:46 +0000573 ALOGE("%s not implemented yet", __func__);
574 return OK;
575}
576
577error::Result<audio_hw_sync_t> DeviceHalAidl::getHwAvSync() {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000578 TIME_CHECK();
Shunkai Yao51202502022-12-12 06:11:46 +0000579 ALOGE("%s not implemented yet", __func__);
580 return base::unexpected(INVALID_OPERATION);
581}
582
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000583status_t DeviceHalAidl::dump(int fd, const Vector<String16>& args) {
584 TIME_CHECK();
585 if (!mModule) return NO_INIT;
586 return mModule->dump(fd, Args(args).args(), args.size());
Shunkai Yao51202502022-12-12 06:11:46 +0000587};
588
Mikhail Naganov31d46652023-01-10 18:29:25 +0000589int32_t DeviceHalAidl::supportsBluetoothVariableLatency(bool* supports __unused) {
590 TIME_CHECK();
Shunkai Yao51202502022-12-12 06:11:46 +0000591 ALOGE("%s not implemented yet", __func__);
592 return INVALID_OPERATION;
593}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000594
Vlad Popa03bd5bc2023-01-17 16:16:51 +0100595status_t DeviceHalAidl::getSoundDoseInterface(const std::string& module,
596 ::ndk::SpAIBinder* soundDoseBinder) {
597 TIME_CHECK();
598 if (!mModule) return NO_INIT;
599 if (mSoundDose == nullptr) {
600 ndk::ScopedAStatus status = mModule->getSoundDose(&mSoundDose);
601 if (!status.isOk()) {
602 ALOGE("%s failed to return the sound dose interface for module %s: %s",
603 __func__,
604 module.c_str(),
605 status.getDescription().c_str());
606 return BAD_VALUE;
607 }
608 }
609 *soundDoseBinder = mSoundDose->asBinder();
610 ALOGI("%s using audio AIDL HAL sound dose interface", __func__);
611
612 return OK;
613}
614
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800615bool DeviceHalAidl::audioDeviceMatches(const AudioDevice& device, const AudioPort& p) {
616 if (p.ext.getTag() != AudioPortExt::Tag::device) return false;
617 return p.ext.get<AudioPortExt::Tag::device>().device == device;
618}
619
620bool DeviceHalAidl::audioDeviceMatches(const AudioDevice& device, const AudioPortConfig& p) {
621 if (p.ext.getTag() != AudioPortExt::Tag::device) return false;
622 if (device.type.type == AudioDeviceType::IN_DEFAULT) {
623 return p.portId == mDefaultInputPortId;
624 } else if (device.type.type == AudioDeviceType::OUT_DEFAULT) {
625 return p.portId == mDefaultOutputPortId;
626 }
627 return p.ext.get<AudioPortExt::Tag::device>().device == device;
628}
629
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800630status_t DeviceHalAidl::createPortConfig(const AudioPortConfig& requestedPortConfig,
631 AudioPortConfig* appliedPortConfig) {
632 TIME_CHECK();
633 bool applied = false;
634 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPortConfig(
635 requestedPortConfig, appliedPortConfig, &applied)));
636 if (!applied) {
637 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPortConfig(
638 *appliedPortConfig, appliedPortConfig, &applied)));
639 if (!applied) {
640 ALOGE("%s: module %s did not apply suggested config %s",
641 __func__, mInstance.c_str(), appliedPortConfig->toString().c_str());
642 return NO_INIT;
643 }
644 }
645 mPortConfigs.emplace(appliedPortConfig->id, *appliedPortConfig);
646 return OK;
647}
648
649status_t DeviceHalAidl::findOrCreatePatch(
650 const AudioPatch& requestedPatch, AudioPatch* patch, bool* created) {
651 std::set<int32_t> sourcePortConfigIds(requestedPatch.sourcePortConfigIds.begin(),
652 requestedPatch.sourcePortConfigIds.end());
653 std::set<int32_t> sinkPortConfigIds(requestedPatch.sinkPortConfigIds.begin(),
654 requestedPatch.sinkPortConfigIds.end());
655 return findOrCreatePatch(sourcePortConfigIds, sinkPortConfigIds, patch, created);
656}
657
658status_t DeviceHalAidl::findOrCreatePatch(
659 const std::set<int32_t>& sourcePortConfigIds, const std::set<int32_t>& sinkPortConfigIds,
660 AudioPatch* patch, bool* created) {
661 auto patchIt = findPatch(sourcePortConfigIds, sinkPortConfigIds);
662 if (patchIt == mPatches.end()) {
663 TIME_CHECK();
664 AudioPatch requestedPatch, appliedPatch;
665 requestedPatch.sourcePortConfigIds.insert(requestedPatch.sourcePortConfigIds.end(),
666 sourcePortConfigIds.begin(), sourcePortConfigIds.end());
667 requestedPatch.sinkPortConfigIds.insert(requestedPatch.sinkPortConfigIds.end(),
668 sinkPortConfigIds.begin(), sinkPortConfigIds.end());
669 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPatch(
670 requestedPatch, &appliedPatch)));
671 patchIt = mPatches.insert(mPatches.end(), std::make_pair(appliedPatch.id, appliedPatch));
672 *created = true;
673 } else {
674 *created = false;
675 }
676 *patch = patchIt->second;
677 return OK;
678}
679
680status_t DeviceHalAidl::findOrCreatePortConfig(const AudioDevice& device,
681 AudioPortConfig* portConfig, bool* created) {
682 auto portConfigIt = findPortConfig(device);
683 if (portConfigIt == mPortConfigs.end()) {
684 auto portsIt = findPort(device);
685 if (portsIt == mPorts.end()) {
686 ALOGE("%s: device port for device %s is not found in the module %s",
687 __func__, device.toString().c_str(), mInstance.c_str());
688 return BAD_VALUE;
689 }
690 AudioPortConfig requestedPortConfig;
691 requestedPortConfig.portId = portsIt->first;
692 AudioPortConfig appliedPortConfig;
693 RETURN_STATUS_IF_ERROR(createPortConfig(requestedPortConfig, &appliedPortConfig));
694 portConfigIt = mPortConfigs.insert(
695 mPortConfigs.end(), std::make_pair(appliedPortConfig.id, appliedPortConfig));
696 *created = true;
697 } else {
698 *created = false;
699 }
700 *portConfig = portConfigIt->second;
701 return OK;
702}
703
704status_t DeviceHalAidl::findOrCreatePortConfig(
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800705 const AudioConfig& config, const std::optional<AudioIoFlags>& flags, int32_t ioHandle,
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800706 AudioPortConfig* portConfig, bool* created) {
707 auto portConfigIt = findPortConfig(config, flags, ioHandle);
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800708 if (portConfigIt == mPortConfigs.end() && flags.has_value()) {
709 auto portsIt = findPort(config, flags.value());
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800710 if (portsIt == mPorts.end()) {
711 ALOGE("%s: mix port for config %s, flags %s is not found in the module %s",
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800712 __func__, config.toString().c_str(), flags.value().toString().c_str(),
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800713 mInstance.c_str());
714 return BAD_VALUE;
715 }
716 AudioPortConfig requestedPortConfig;
717 requestedPortConfig.portId = portsIt->first;
718 setPortConfigFromConfig(&requestedPortConfig, config);
719 AudioPortConfig appliedPortConfig;
720 RETURN_STATUS_IF_ERROR(createPortConfig(requestedPortConfig, &appliedPortConfig));
721 appliedPortConfig.ext.get<AudioPortExt::Tag::mix>().handle = ioHandle;
722 portConfigIt = mPortConfigs.insert(
723 mPortConfigs.end(), std::make_pair(appliedPortConfig.id, appliedPortConfig));
724 *created = true;
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800725 } else if (!flags.has_value()) {
726 ALOGW("%s: mix port config for %s, handle %d not found in the module %s, "
727 "and was not created as flags are not specified",
728 __func__, config.toString().c_str(), ioHandle, mInstance.c_str());
729 return BAD_VALUE;
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800730 } else {
731 *created = false;
732 }
733 *portConfig = portConfigIt->second;
734 return OK;
735}
736
737status_t DeviceHalAidl::findOrCreatePortConfig(
738 const AudioPortConfig& requestedPortConfig, AudioPortConfig* portConfig, bool* created) {
739 using Tag = AudioPortExt::Tag;
740 if (requestedPortConfig.ext.getTag() == Tag::mix) {
741 if (const auto& p = requestedPortConfig;
742 !p.sampleRate.has_value() || !p.channelMask.has_value() ||
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800743 !p.format.has_value()) {
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800744 ALOGW("%s: provided mix port config is not fully specified: %s",
745 __func__, p.toString().c_str());
746 return BAD_VALUE;
747 }
748 AudioConfig config;
749 setConfigFromPortConfig(&config, requestedPortConfig);
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800750 return findOrCreatePortConfig(config, requestedPortConfig.flags,
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800751 requestedPortConfig.ext.get<Tag::mix>().handle, portConfig, created);
752 } else if (requestedPortConfig.ext.getTag() == Tag::device) {
753 return findOrCreatePortConfig(
754 requestedPortConfig.ext.get<Tag::device>().device, portConfig, created);
755 }
756 ALOGW("%s: unsupported audio port config: %s",
757 __func__, requestedPortConfig.toString().c_str());
758 return BAD_VALUE;
759}
760
761DeviceHalAidl::Patches::iterator DeviceHalAidl::findPatch(
762 const std::set<int32_t>& sourcePortConfigIds, const std::set<int32_t>& sinkPortConfigIds) {
763 return std::find_if(mPatches.begin(), mPatches.end(),
764 [&](const auto& pair) {
765 const auto& p = pair.second;
766 std::set<int32_t> patchSrcs(
767 p.sourcePortConfigIds.begin(), p.sourcePortConfigIds.end());
768 std::set<int32_t> patchSinks(
769 p.sinkPortConfigIds.begin(), p.sinkPortConfigIds.end());
770 return sourcePortConfigIds == patchSrcs && sinkPortConfigIds == patchSinks; });
771}
772
773DeviceHalAidl::Ports::iterator DeviceHalAidl::findPort(const AudioDevice& device) {
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800774 if (device.type.type == AudioDeviceType::IN_DEFAULT) {
775 return mPorts.find(mDefaultInputPortId);
776 } else if (device.type.type == AudioDeviceType::OUT_DEFAULT) {
777 return mPorts.find(mDefaultOutputPortId);
778 }
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800779 return std::find_if(mPorts.begin(), mPorts.end(),
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800780 [&](const auto& pair) { return audioDeviceMatches(device, pair.second); });
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800781}
782
783DeviceHalAidl::Ports::iterator DeviceHalAidl::findPort(
784 const AudioConfig& config, const AudioIoFlags& flags) {
785 using Tag = AudioPortExt::Tag;
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800786 AudioIoFlags matchFlags = flags;
787 auto matcher = [&](const auto& pair) {
788 const auto& p = pair.second;
789 return p.ext.getTag() == Tag::mix &&
790 p.flags == matchFlags &&
791 std::find_if(p.profiles.begin(), p.profiles.end(),
792 [&](const auto& prof) {
793 return prof.format == config.base.format &&
794 std::find(prof.channelMasks.begin(), prof.channelMasks.end(),
795 config.base.channelMask) != prof.channelMasks.end() &&
796 std::find(prof.sampleRates.begin(), prof.sampleRates.end(),
797 config.base.sampleRate) != prof.sampleRates.end();
798 }) != p.profiles.end(); };
799 auto it = std::find_if(mPorts.begin(), mPorts.end(), matcher);
800 if (it == mPorts.end() && flags.getTag() == AudioIoFlags::Tag::input &&
801 isBitPositionFlagSet(flags.get<AudioIoFlags::Tag::input>(), AudioInputFlags::FAST)) {
802 // "Fast" input is not a mandatory flag, try without it.
803 matchFlags.set<AudioIoFlags::Tag::input>(flags.get<AudioIoFlags::Tag::input>() &
804 ~makeBitPositionFlagMask(AudioInputFlags::FAST));
805 it = std::find_if(mPorts.begin(), mPorts.end(), matcher);
806 }
807 return it;
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800808}
809
810DeviceHalAidl::PortConfigs::iterator DeviceHalAidl::findPortConfig(const AudioDevice& device) {
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800811 return std::find_if(mPortConfigs.begin(), mPortConfigs.end(),
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800812 [&](const auto& pair) { return audioDeviceMatches(device, pair.second); });
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800813}
814
815DeviceHalAidl::PortConfigs::iterator DeviceHalAidl::findPortConfig(
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800816 const AudioConfig& config, const std::optional<AudioIoFlags>& flags, int32_t ioHandle) {
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800817 using Tag = AudioPortExt::Tag;
818 return std::find_if(mPortConfigs.begin(), mPortConfigs.end(),
819 [&](const auto& pair) {
820 const auto& p = pair.second;
821 LOG_ALWAYS_FATAL_IF(p.ext.getTag() == Tag::mix &&
822 !p.sampleRate.has_value() || !p.channelMask.has_value() ||
823 !p.format.has_value() || !p.flags.has_value(),
824 "%s: stored mix port config is not fully specified: %s",
825 __func__, p.toString().c_str());
826 return p.ext.getTag() == Tag::mix &&
827 isConfigEqualToPortConfig(config, p) &&
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800828 (!flags.has_value() || p.flags.value() == flags.value()) &&
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800829 p.ext.template get<Tag::mix>().handle == ioHandle; });
830}
831/*
832DeviceHalAidl::PortConfigs::iterator DeviceHalAidl::findPortConfig(
833 const AudioPortConfig& portConfig) {
834 using Tag = AudioPortExt::Tag;
835 if (portConfig.ext.getTag() == Tag::mix) {
836 return std::find_if(mPortConfigs.begin(), mPortConfigs.end(),
837 [&](const auto& pair) {
838 const auto& p = pair.second;
839 LOG_ALWAYS_FATAL_IF(p.ext.getTag() == Tag::mix &&
840 !p.sampleRate.has_value() || !p.channelMask.has_value() ||
841 !p.format.has_value() || !p.flags.has_value(),
842 "%s: stored mix port config is not fully specified: %s",
843 __func__, p.toString().c_str());
844 return p.ext.getTag() == Tag::mix &&
845 (!portConfig.sampleRate.has_value() ||
846 p.sampleRate == portConfig.sampleRate) &&
847 (!portConfig.channelMask.has_value() ||
848 p.channelMask == portConfig.channelMask) &&
849 (!portConfig.format.has_value() || p.format == portConfig.format) &&
850 (!portConfig.flags.has_value() || p.flags == portConfig.flags) &&
851 p.ext.template get<Tag::mix>().handle ==
852 portConfig.ext.template get<Tag::mix>().handle; });
853 } else if (portConfig.ext.getTag() == Tag::device) {
854 return findPortConfig(portConfig.ext.get<Tag::device>().device);
855 }
856 return mPortConfigs.end();
857}
858*/
859void DeviceHalAidl::resetPatch(int32_t patchId) {
860 if (auto it = mPatches.find(patchId); it != mPatches.end()) {
861 mPatches.erase(it);
862 TIME_CHECK();
863 if (ndk::ScopedAStatus status = mModule->resetAudioPatch(patchId); !status.isOk()) {
864 ALOGE("%s: error while resetting patch %d: %s",
865 __func__, patchId, status.getDescription().c_str());
866 }
867 return;
868 }
869 ALOGE("%s: patch id %d not found", __func__, patchId);
870}
871
872void DeviceHalAidl::resetPortConfig(int32_t portConfigId) {
873 if (auto it = mPortConfigs.find(portConfigId); it != mPortConfigs.end()) {
874 mPortConfigs.erase(it);
875 TIME_CHECK();
876 if (ndk::ScopedAStatus status = mModule->resetAudioPortConfig(portConfigId);
877 !status.isOk()) {
878 ALOGE("%s: error while resetting port config %d: %s",
879 __func__, portConfigId, status.getDescription().c_str());
880 }
881 return;
882 }
883 ALOGE("%s: port config id %d not found", __func__, portConfigId);
884}
885
Mikhail Naganov31d46652023-01-10 18:29:25 +0000886} // namespace android