blob: 6c882a6abe2213fb39d9968c4b400cbb281ac8ed [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 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 Naganov89a9f742023-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 Naganov5b1eed12023-01-25 11:29:11 -080035using aidl::android::media::audio::common::AudioConfig;
36using aidl::android::media::audio::common::AudioDevice;
Mikhail Naganov89a9f742023-01-30 12:33:18 -080037using aidl::android::media::audio::common::AudioDeviceType;
38using aidl::android::media::audio::common::AudioInputFlags;
Mikhail Naganov5b1eed12023-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 Naganov5b1eed12023-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 Naganov89a9f742023-01-30 12:33:18 -080044using aidl::android::media::audio::common::AudioPortDeviceExt;
Mikhail Naganov5b1eed12023-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 Naganov5b1eed12023-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;
Mikhail Naganov89a9f742023-01-30 12:33:18 -080054using android::hardware::audio::common::getFrameSizeInBytes;
55using android::hardware::audio::common::isBitPositionFlagSet;
56using android::hardware::audio::common::makeBitPositionFlagMask;
Mikhail Naganov31d46652023-01-10 18:29:25 +000057
58namespace android {
59
Mikhail Naganov5b1eed12023-01-25 11:29:11 -080060namespace {
61
62bool isConfigEqualToPortConfig(const AudioConfig& config, const AudioPortConfig& portConfig) {
63 return portConfig.sampleRate.value().value == config.base.sampleRate &&
64 portConfig.channelMask.value() == config.base.channelMask &&
65 portConfig.format.value() == config.base.format;
66}
67
68void setConfigFromPortConfig(AudioConfig* config, const AudioPortConfig& portConfig) {
69 config->base.sampleRate = portConfig.sampleRate.value().value;
70 config->base.channelMask = portConfig.channelMask.value();
71 config->base.format = portConfig.format.value();
72}
73
74void setPortConfigFromConfig(AudioPortConfig* portConfig, const AudioConfig& config) {
75 portConfig->sampleRate = Int{ .value = config.base.sampleRate };
76 portConfig->channelMask = config.base.channelMask;
77 portConfig->format = config.base.format;
78}
79
80} // namespace
81
Mikhail Naganov31d46652023-01-10 18:29:25 +000082status_t DeviceHalAidl::getSupportedDevices(uint32_t*) {
83 // Obsolete.
84 return INVALID_OPERATION;
Shunkai Yao51202502022-12-12 06:11:46 +000085}
86
87status_t DeviceHalAidl::initCheck() {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -080088 TIME_CHECK();
Mikhail Naganov31d46652023-01-10 18:29:25 +000089 if (mModule == nullptr) return NO_INIT;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -080090 std::vector<AudioPort> ports;
91 RETURN_STATUS_IF_ERROR(
92 statusTFromBinderStatus(mModule->getAudioPorts(&ports)));
93 ALOGW_IF(ports.empty(), "%s: module %s returned an empty list of audio ports",
94 __func__, mInstance.c_str());
95 std::transform(ports.begin(), ports.end(), std::inserter(mPorts, mPorts.end()),
96 [](const auto& p) { return std::make_pair(p.id, p); });
Mikhail Naganov89a9f742023-01-30 12:33:18 -080097 mDefaultInputPortId = mDefaultOutputPortId = -1;
98 const int defaultDeviceFlag = 1 << AudioPortDeviceExt::FLAG_INDEX_DEFAULT_DEVICE;
99 for (const auto& pair : mPorts) {
100 const auto& p = pair.second;
101 if (p.ext.getTag() == AudioPortExt::Tag::device &&
102 (p.ext.get<AudioPortExt::Tag::device>().flags & defaultDeviceFlag) != 0) {
103 if (p.flags.getTag() == AudioIoFlags::Tag::input) {
104 mDefaultInputPortId = p.id;
105 } else if (p.flags.getTag() == AudioIoFlags::Tag::output) {
106 mDefaultOutputPortId = p.id;
107 }
108 }
109 }
110 ALOGI("%s: module %s default port ids: input %d, output %d",
111 __func__, mInstance.c_str(), mDefaultInputPortId, mDefaultOutputPortId);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800112 std::vector<AudioPortConfig> portConfigs;
113 RETURN_STATUS_IF_ERROR(
114 statusTFromBinderStatus(mModule->getAudioPortConfigs(&portConfigs))); // OK if empty
115 std::transform(portConfigs.begin(), portConfigs.end(),
116 std::inserter(mPortConfigs, mPortConfigs.end()),
117 [](const auto& p) { return std::make_pair(p.id, p); });
118 std::vector<AudioPatch> patches;
119 RETURN_STATUS_IF_ERROR(
120 statusTFromBinderStatus(mModule->getAudioPatches(&patches))); // OK if empty
121 std::transform(patches.begin(), patches.end(),
122 std::inserter(mPatches, mPatches.end()),
123 [](const auto& p) { return std::make_pair(p.id, p); });
Shunkai Yao51202502022-12-12 06:11:46 +0000124 return OK;
125}
126
127status_t DeviceHalAidl::setVoiceVolume(float volume) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000128 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000129 if (!mModule) return NO_INIT;
130 std::shared_ptr<ITelephony> telephony;
131 if (ndk::ScopedAStatus status = mModule->getTelephony(&telephony);
132 status.isOk() && telephony != nullptr) {
133 ITelephony::TelecomConfig inConfig{ .voiceVolume = Float{volume} }, outConfig;
134 RETURN_STATUS_IF_ERROR(
135 statusTFromBinderStatus(telephony->setTelecomConfig(inConfig, &outConfig)));
136 ALOGW_IF(outConfig.voiceVolume.has_value() && volume != outConfig.voiceVolume.value().value,
137 "%s: the resulting voice volume %f is not the same as requested %f",
138 __func__, outConfig.voiceVolume.value().value, volume);
139 }
140 return INVALID_OPERATION;
Shunkai Yao51202502022-12-12 06:11:46 +0000141}
142
143status_t DeviceHalAidl::setMasterVolume(float volume) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000144 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000145 if (!mModule) return NO_INIT;
146 return statusTFromBinderStatus(mModule->setMasterVolume(volume));
Shunkai Yao51202502022-12-12 06:11:46 +0000147}
148
149status_t DeviceHalAidl::getMasterVolume(float *volume) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000150 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000151 if (!mModule) return NO_INIT;
152 return statusTFromBinderStatus(mModule->getMasterVolume(volume));
Shunkai Yao51202502022-12-12 06:11:46 +0000153}
154
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000155status_t DeviceHalAidl::setMode(audio_mode_t mode) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000156 TIME_CHECK();
157 if (!mModule) return NO_INIT;
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000158 AudioMode audioMode = VALUE_OR_FATAL(::aidl::android::legacy2aidl_audio_mode_t_AudioMode(mode));
159 std::shared_ptr<ITelephony> telephony;
160 if (ndk::ScopedAStatus status = mModule->getTelephony(&telephony);
161 status.isOk() && telephony != nullptr) {
162 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(telephony->switchAudioMode(audioMode)));
163 }
164 return statusTFromBinderStatus(mModule->updateAudioMode(audioMode));
Shunkai Yao51202502022-12-12 06:11:46 +0000165}
166
167status_t DeviceHalAidl::setMicMute(bool state) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000168 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000169 if (!mModule) return NO_INIT;
170 return statusTFromBinderStatus(mModule->setMicMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000171}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000172
Shunkai Yao51202502022-12-12 06:11:46 +0000173status_t DeviceHalAidl::getMicMute(bool *state) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000174 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000175 if (!mModule) return NO_INIT;
176 return statusTFromBinderStatus(mModule->getMicMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000177}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000178
Shunkai Yao51202502022-12-12 06:11:46 +0000179status_t DeviceHalAidl::setMasterMute(bool state) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000180 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000181 if (!mModule) return NO_INIT;
182 return statusTFromBinderStatus(mModule->setMasterMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000183}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000184
Shunkai Yao51202502022-12-12 06:11:46 +0000185status_t DeviceHalAidl::getMasterMute(bool *state) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000186 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000187 if (!mModule) return NO_INIT;
188 return statusTFromBinderStatus(mModule->getMasterMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000189}
190
Mikhail Naganov31d46652023-01-10 18:29:25 +0000191status_t DeviceHalAidl::setParameters(const String8& kvPairs __unused) {
192 TIME_CHECK();
193 if (!mModule) return NO_INIT;
194 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000195 return OK;
196}
197
Mikhail Naganov31d46652023-01-10 18:29:25 +0000198status_t DeviceHalAidl::getParameters(const String8& keys __unused, String8 *values) {
199 TIME_CHECK();
200 values->clear();
201 if (!mModule) return NO_INIT;
202 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000203 return OK;
204}
205
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800206namespace {
207
208class Cleanup {
209 public:
210 typedef void (DeviceHalAidl::*Cleaner)(int32_t);
211
212 Cleanup(DeviceHalAidl* device, Cleaner cleaner, int32_t id) :
213 mDevice(device), mCleaner(cleaner), mId(id) {}
214 ~Cleanup() { clean(); }
215 void clean() {
216 if (mDevice != nullptr) (mDevice->*mCleaner)(mId);
217 disarm();
218 }
219 void disarm() { mDevice = nullptr; }
220
221 private:
222 DeviceHalAidl* mDevice;
223 const Cleaner mCleaner;
224 const int32_t mId;
225};
226
227} // namespace
228
229// Since the order of container elements destruction is unspecified,
230// ensure that cleanups are performed from the most recent one and upwards.
231// This is the same as if there were individual Cleanup instances on the stack,
232// however the bonus is that we can disarm all of them with just one statement.
233class DeviceHalAidl::Cleanups : public std::forward_list<Cleanup> {
234 public:
235 ~Cleanups() { for (auto& c : *this) c.clean(); }
236 void disarmAll() { for (auto& c : *this) c.disarm(); }
237};
238
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800239status_t DeviceHalAidl::getInputBufferSize(const struct audio_config* config, size_t* size) {
240 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
241 if (size == nullptr) return BAD_VALUE;
242 TIME_CHECK();
243 if (!mModule) return NO_INIT;
244 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
245 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, true /*isInput*/));
246 AudioDevice aidlDevice;
247 aidlDevice.type.type = AudioDeviceType::IN_DEFAULT;
248 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::input>(0);
249 AudioPortConfig mixPortConfig;
250 Cleanups cleanups;
251 audio_config writableConfig = *config;
252 int32_t nominalLatency;
253 RETURN_STATUS_IF_ERROR(prepareToOpenStream(0 /*handle*/, aidlDevice, aidlFlags, &writableConfig,
254 &cleanups, &aidlConfig, &mixPortConfig, &nominalLatency));
255 *size = aidlConfig.frameCount *
256 getFrameSizeInBytes(aidlConfig.base.format, aidlConfig.base.channelMask);
257 // Do not disarm cleanups to release temporary port configs.
258 return OK;
259}
260
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800261status_t DeviceHalAidl::prepareToOpenStream(
262 int32_t aidlHandle, const AudioDevice& aidlDevice, const AudioIoFlags& aidlFlags,
263 struct audio_config* config,
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800264 Cleanups* cleanups, AudioConfig* aidlConfig, AudioPortConfig* mixPortConfig,
265 int32_t* nominalLatency) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800266 const bool isInput = aidlFlags.getTag() == AudioIoFlags::Tag::input;
267 // Find / create AudioPortConfigs for the device port and the mix port,
268 // then find / create a patch between them, and open a stream on the mix port.
269 AudioPortConfig devicePortConfig;
270 bool created = false;
271 RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(aidlDevice, &devicePortConfig, &created));
272 if (created) {
273 cleanups->emplace_front(this, &DeviceHalAidl::resetPortConfig, devicePortConfig.id);
274 }
275 RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(*aidlConfig, aidlFlags, aidlHandle,
276 mixPortConfig, &created));
277 if (created) {
278 cleanups->emplace_front(this, &DeviceHalAidl::resetPortConfig, mixPortConfig->id);
279 }
280 setConfigFromPortConfig(aidlConfig, *mixPortConfig);
281 AudioPatch patch;
282 if (isInput) {
283 RETURN_STATUS_IF_ERROR(findOrCreatePatch(
284 {devicePortConfig.id}, {mixPortConfig->id}, &patch, &created));
285 } else {
286 RETURN_STATUS_IF_ERROR(findOrCreatePatch(
287 {mixPortConfig->id}, {devicePortConfig.id}, &patch, &created));
288 }
289 if (created) {
290 cleanups->emplace_front(this, &DeviceHalAidl::resetPatch, patch.id);
291 }
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800292 *nominalLatency = patch.latenciesMs[0];
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800293 if (aidlConfig->frameCount <= 0) {
294 aidlConfig->frameCount = patch.minimumStreamBufferSizeFrames;
295 }
296 *config = VALUE_OR_RETURN_STATUS(
297 ::aidl::android::aidl2legacy_AudioConfig_audio_config_t(*aidlConfig, isInput));
298 return OK;
299}
300
Mikhail Naganov31d46652023-01-10 18:29:25 +0000301status_t DeviceHalAidl::openOutputStream(
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800302 audio_io_handle_t handle, audio_devices_t devices,
303 audio_output_flags_t flags, struct audio_config* config,
304 const char* address,
Mikhail Naganov31d46652023-01-10 18:29:25 +0000305 sp<StreamOutHalInterface>* outStream) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800306 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000307 if (!outStream || !config) {
308 return BAD_VALUE;
309 }
310 TIME_CHECK();
311 if (!mModule) return NO_INIT;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800312 int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
313 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(handle));
314 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
315 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, false /*isInput*/));
316 AudioDevice aidlDevice = VALUE_OR_RETURN_STATUS(
317 ::aidl::android::legacy2aidl_audio_device_AudioDevice(devices, address));
318 int32_t aidlOutputFlags = VALUE_OR_RETURN_STATUS(
319 ::aidl::android::legacy2aidl_audio_output_flags_t_int32_t_mask(flags));
320 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::output>(aidlOutputFlags);
321 AudioPortConfig mixPortConfig;
322 Cleanups cleanups;
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800323 int32_t nominalLatency;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800324 RETURN_STATUS_IF_ERROR(prepareToOpenStream(aidlHandle, aidlDevice, aidlFlags, config,
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800325 &cleanups, &aidlConfig, &mixPortConfig, &nominalLatency));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800326 ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamArguments args;
327 args.portConfigId = mixPortConfig.id;
328 args.offloadInfo = aidlConfig.offloadInfo;
329 args.bufferSizeFrames = aidlConfig.frameCount;
330 ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamReturn ret;
331 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openOutputStream(args, &ret)));
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800332 StreamContextAidl context(ret.desc);
333 if (!context.isValid()) {
334 ALOGE("%s: Failed to created a valid stream context from the descriptor: %s",
335 __func__, ret.desc.toString().c_str());
336 return NO_INIT;
337 }
338 *outStream = sp<StreamOutHalAidl>::make(*config, std::move(context), nominalLatency,
339 std::move(ret.stream));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800340 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000341 return OK;
342}
343
Mikhail Naganov31d46652023-01-10 18:29:25 +0000344status_t DeviceHalAidl::openInputStream(
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800345 audio_io_handle_t handle, audio_devices_t devices,
346 struct audio_config* config, audio_input_flags_t flags,
347 const char* address, audio_source_t source,
348 audio_devices_t outputDevice, const char* outputDeviceAddress,
Mikhail Naganov31d46652023-01-10 18:29:25 +0000349 sp<StreamInHalInterface>* inStream) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800350 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000351 if (!inStream || !config) {
352 return BAD_VALUE;
353 }
354 TIME_CHECK();
355 if (!mModule) return NO_INIT;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800356 int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
357 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(handle));
358 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
359 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, true /*isInput*/));
360 AudioDevice aidlDevice = VALUE_OR_RETURN_STATUS(
361 ::aidl::android::legacy2aidl_audio_device_AudioDevice(devices, address));
362 int32_t aidlInputFlags = VALUE_OR_RETURN_STATUS(
363 ::aidl::android::legacy2aidl_audio_input_flags_t_int32_t_mask(flags));
364 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::input>(aidlInputFlags);
365 AudioSource aidlSource = VALUE_OR_RETURN_STATUS(
366 ::aidl::android::legacy2aidl_audio_source_t_AudioSource(source));
367 AudioPortConfig mixPortConfig;
368 Cleanups cleanups;
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800369 int32_t nominalLatency;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800370 RETURN_STATUS_IF_ERROR(prepareToOpenStream(aidlHandle, aidlDevice, aidlFlags, config,
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800371 &cleanups, &aidlConfig, &mixPortConfig, &nominalLatency));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800372 ::aidl::android::hardware::audio::core::IModule::OpenInputStreamArguments args;
373 args.portConfigId = mixPortConfig.id;
374 RecordTrackMetadata aidlTrackMetadata{
375 .source = aidlSource, .gain = 1, .channelMask = aidlConfig.base.channelMask };
376 if (outputDevice != AUDIO_DEVICE_NONE) {
377 aidlTrackMetadata.destinationDevice = VALUE_OR_RETURN_STATUS(
378 ::aidl::android::legacy2aidl_audio_device_AudioDevice(
379 outputDevice, outputDeviceAddress));
380 }
381 args.sinkMetadata.tracks.push_back(std::move(aidlTrackMetadata));
382 args.bufferSizeFrames = aidlConfig.frameCount;
383 ::aidl::android::hardware::audio::core::IModule::OpenInputStreamReturn ret;
384 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openInputStream(args, &ret)));
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800385 StreamContextAidl context(ret.desc);
386 if (!context.isValid()) {
387 ALOGE("%s: Failed to created a valid stream context from the descriptor: %s",
388 __func__, ret.desc.toString().c_str());
389 return NO_INIT;
390 }
391 *inStream = sp<StreamInHalAidl>::make(*config, std::move(context), nominalLatency,
392 std::move(ret.stream));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800393 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000394 return OK;
395}
396
397status_t DeviceHalAidl::supportsAudioPatches(bool* supportsPatches) {
398 *supportsPatches = true;
399 return OK;
400}
401
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800402status_t DeviceHalAidl::createAudioPatch(unsigned int num_sources,
403 const struct audio_port_config* sources,
404 unsigned int num_sinks,
405 const struct audio_port_config* sinks,
406 audio_patch_handle_t* patch) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800407 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000408 TIME_CHECK();
409 if (!mModule) return NO_INIT;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800410 if (num_sinks > AUDIO_PATCH_PORTS_MAX || num_sources > AUDIO_PATCH_PORTS_MAX ||
411 sources == nullptr || sinks == nullptr || patch == nullptr) {
412 return BAD_VALUE;
413 }
414 // Note that the patch handle (*patch) is provided by the framework.
415 // In tests it's possible that its value is AUDIO_PATCH_HANDLE_NONE.
416
417 // Upon conversion, mix port configs contain audio configuration, while
418 // device port configs contain device address. This data is used to find
419 // or create HAL configs.
420 std::vector<AudioPortConfig> aidlSources, aidlSinks;
421 for (unsigned int i = 0; i < num_sources; ++i) {
422 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
423 sources[i].role, sources[i].type)) ==
424 ::aidl::android::AudioPortDirection::INPUT;
425 aidlSources.push_back(VALUE_OR_RETURN_STATUS(
426 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
427 sources[i], isInput, 0)));
428 }
429 for (unsigned int i = 0; i < num_sinks; ++i) {
430 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
431 sinks[i].role, sinks[i].type)) ==
432 ::aidl::android::AudioPortDirection::INPUT;
433 aidlSinks.push_back(VALUE_OR_RETURN_STATUS(
434 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
435 sinks[i], isInput, 0)));
436 }
437 Cleanups cleanups;
438 auto existingPatchIt = mPatches.end();
439 auto fwkHandlesIt = *patch != AUDIO_PATCH_HANDLE_NONE ?
440 mFwkHandles.find(*patch) : mFwkHandles.end();
441 AudioPatch aidlPatch;
442 if (fwkHandlesIt != mFwkHandles.end()) {
443 existingPatchIt = mPatches.find(fwkHandlesIt->second);
444 if (existingPatchIt != mPatches.end()) {
445 aidlPatch = existingPatchIt->second;
446 aidlPatch.sourcePortConfigIds.clear();
447 aidlPatch.sinkPortConfigIds.clear();
448 }
449 }
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800450 ALOGD("%s: sources: %s, sinks: %s",
451 __func__, ::android::internal::ToString(aidlSources).c_str(),
452 ::android::internal::ToString(aidlSinks).c_str());
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800453 auto fillPortConfigs = [&](
454 const std::vector<AudioPortConfig>& configs, std::vector<int32_t>* ids) -> status_t {
455 for (const auto& s : configs) {
456 AudioPortConfig portConfig;
457 bool created = false;
458 RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(s, &portConfig, &created));
459 if (created) {
460 cleanups.emplace_front(this, &DeviceHalAidl::resetPortConfig, portConfig.id);
461 }
462 ids->push_back(portConfig.id);
463 }
464 return OK;
465 };
466 RETURN_STATUS_IF_ERROR(fillPortConfigs(aidlSources, &aidlPatch.sourcePortConfigIds));
467 RETURN_STATUS_IF_ERROR(fillPortConfigs(aidlSinks, &aidlPatch.sinkPortConfigIds));
468 if (existingPatchIt != mPatches.end()) {
469 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
470 mModule->setAudioPatch(aidlPatch, &aidlPatch)));
471 existingPatchIt->second = aidlPatch;
472 } else {
473 bool created = false;
474 RETURN_STATUS_IF_ERROR(findOrCreatePatch(aidlPatch, &aidlPatch, &created));
475 // Since no cleanup of the patch is needed, 'created' is ignored.
476 if (fwkHandlesIt != mFwkHandles.end()) {
477 fwkHandlesIt->second = aidlPatch.id;
478 // Patch handle (*patch) stays the same.
479 } else {
480 if (*patch == AUDIO_PATCH_HANDLE_NONE) {
481 // This isn't good as the module can't provide a handle which is really unique.
482 // However, this situation should only happen in tests.
483 *patch = aidlPatch.id;
484 LOG_ALWAYS_FATAL_IF(mFwkHandles.count(*patch) > 0,
485 "%s: patch id %d clashes with another framework patch handle",
486 __func__, *patch);
487 }
488 mFwkHandles.emplace(*patch, aidlPatch.id);
489 }
490 }
491 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000492 return OK;
493}
494
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800495status_t DeviceHalAidl::releaseAudioPatch(audio_patch_handle_t patch) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800496 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000497 TIME_CHECK();
498 if (!mModule) return NO_INIT;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800499 auto idMapIt = mFwkHandles.find(patch);
500 if (idMapIt == mFwkHandles.end()) {
501 return BAD_VALUE;
502 }
503 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->resetAudioPatch(idMapIt->second)));
504 mFwkHandles.erase(idMapIt);
Shunkai Yao51202502022-12-12 06:11:46 +0000505 return OK;
506}
507
Mikhail Naganov31d46652023-01-10 18:29:25 +0000508status_t DeviceHalAidl::getAudioPort(struct audio_port* port __unused) {
509 TIME_CHECK();
510 ALOGE("%s not implemented yet", __func__);
511 return INVALID_OPERATION;
512}
513
514status_t DeviceHalAidl::getAudioPort(struct audio_port_v7 *port __unused) {
515 TIME_CHECK();
516 ALOGE("%s not implemented yet", __func__);
517 return INVALID_OPERATION;
518}
519
520status_t DeviceHalAidl::setAudioPortConfig(const struct audio_port_config* config __unused) {
521 TIME_CHECK();
522 if (!mModule) return NO_INIT;
523 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000524 return OK;
525}
526
527status_t DeviceHalAidl::getMicrophones(
Mikhail Naganov31d46652023-01-10 18:29:25 +0000528 std::vector<audio_microphone_characteristic_t>* microphones __unused) {
529 TIME_CHECK();
530 if (!mModule) return NO_INIT;
531 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000532 return OK;
533}
534
Mikhail Naganov31d46652023-01-10 18:29:25 +0000535status_t DeviceHalAidl::addDeviceEffect(audio_port_handle_t device __unused,
536 sp<EffectHalInterface> effect) {
Shunkai Yao51202502022-12-12 06:11:46 +0000537 if (!effect) {
538 return BAD_VALUE;
539 }
Mikhail Naganov31d46652023-01-10 18:29:25 +0000540 TIME_CHECK();
541 if (!mModule) return NO_INIT;
542 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000543 return OK;
544}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000545status_t DeviceHalAidl::removeDeviceEffect(audio_port_handle_t device __unused,
Shunkai Yao51202502022-12-12 06:11:46 +0000546 sp<EffectHalInterface> effect) {
547 if (!effect) {
548 return BAD_VALUE;
549 }
Mikhail Naganov31d46652023-01-10 18:29:25 +0000550 TIME_CHECK();
551 if (!mModule) return NO_INIT;
552 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000553 return OK;
554}
555
556status_t DeviceHalAidl::getMmapPolicyInfos(
557 media::audio::common::AudioMMapPolicyType policyType __unused,
558 std::vector<media::audio::common::AudioMMapPolicyInfo>* policyInfos __unused) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000559 TIME_CHECK();
Shunkai Yao51202502022-12-12 06:11:46 +0000560 ALOGE("%s not implemented yet", __func__);
561 return OK;
562}
563
564int32_t DeviceHalAidl::getAAudioMixerBurstCount() {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000565 TIME_CHECK();
Shunkai Yao51202502022-12-12 06:11:46 +0000566 ALOGE("%s not implemented yet", __func__);
567 return OK;
568}
569
570int32_t DeviceHalAidl::getAAudioHardwareBurstMinUsec() {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000571 TIME_CHECK();
Shunkai Yao51202502022-12-12 06:11:46 +0000572 ALOGE("%s not implemented yet", __func__);
573 return OK;
574}
575
576error::Result<audio_hw_sync_t> DeviceHalAidl::getHwAvSync() {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000577 TIME_CHECK();
Shunkai Yao51202502022-12-12 06:11:46 +0000578 ALOGE("%s not implemented yet", __func__);
579 return base::unexpected(INVALID_OPERATION);
580}
581
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000582status_t DeviceHalAidl::dump(int fd, const Vector<String16>& args) {
583 TIME_CHECK();
584 if (!mModule) return NO_INIT;
585 return mModule->dump(fd, Args(args).args(), args.size());
Shunkai Yao51202502022-12-12 06:11:46 +0000586};
587
Mikhail Naganov31d46652023-01-10 18:29:25 +0000588int32_t DeviceHalAidl::supportsBluetoothVariableLatency(bool* supports __unused) {
589 TIME_CHECK();
Shunkai Yao51202502022-12-12 06:11:46 +0000590 ALOGE("%s not implemented yet", __func__);
591 return INVALID_OPERATION;
592}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000593
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800594bool DeviceHalAidl::audioDeviceMatches(const AudioDevice& device, const AudioPort& p) {
595 if (p.ext.getTag() != AudioPortExt::Tag::device) return false;
596 return p.ext.get<AudioPortExt::Tag::device>().device == device;
597}
598
599bool DeviceHalAidl::audioDeviceMatches(const AudioDevice& device, const AudioPortConfig& p) {
600 if (p.ext.getTag() != AudioPortExt::Tag::device) return false;
601 if (device.type.type == AudioDeviceType::IN_DEFAULT) {
602 return p.portId == mDefaultInputPortId;
603 } else if (device.type.type == AudioDeviceType::OUT_DEFAULT) {
604 return p.portId == mDefaultOutputPortId;
605 }
606 return p.ext.get<AudioPortExt::Tag::device>().device == device;
607}
608
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800609status_t DeviceHalAidl::createPortConfig(const AudioPortConfig& requestedPortConfig,
610 AudioPortConfig* appliedPortConfig) {
611 TIME_CHECK();
612 bool applied = false;
613 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPortConfig(
614 requestedPortConfig, appliedPortConfig, &applied)));
615 if (!applied) {
616 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPortConfig(
617 *appliedPortConfig, appliedPortConfig, &applied)));
618 if (!applied) {
619 ALOGE("%s: module %s did not apply suggested config %s",
620 __func__, mInstance.c_str(), appliedPortConfig->toString().c_str());
621 return NO_INIT;
622 }
623 }
624 mPortConfigs.emplace(appliedPortConfig->id, *appliedPortConfig);
625 return OK;
626}
627
628status_t DeviceHalAidl::findOrCreatePatch(
629 const AudioPatch& requestedPatch, AudioPatch* patch, bool* created) {
630 std::set<int32_t> sourcePortConfigIds(requestedPatch.sourcePortConfigIds.begin(),
631 requestedPatch.sourcePortConfigIds.end());
632 std::set<int32_t> sinkPortConfigIds(requestedPatch.sinkPortConfigIds.begin(),
633 requestedPatch.sinkPortConfigIds.end());
634 return findOrCreatePatch(sourcePortConfigIds, sinkPortConfigIds, patch, created);
635}
636
637status_t DeviceHalAidl::findOrCreatePatch(
638 const std::set<int32_t>& sourcePortConfigIds, const std::set<int32_t>& sinkPortConfigIds,
639 AudioPatch* patch, bool* created) {
640 auto patchIt = findPatch(sourcePortConfigIds, sinkPortConfigIds);
641 if (patchIt == mPatches.end()) {
642 TIME_CHECK();
643 AudioPatch requestedPatch, appliedPatch;
644 requestedPatch.sourcePortConfigIds.insert(requestedPatch.sourcePortConfigIds.end(),
645 sourcePortConfigIds.begin(), sourcePortConfigIds.end());
646 requestedPatch.sinkPortConfigIds.insert(requestedPatch.sinkPortConfigIds.end(),
647 sinkPortConfigIds.begin(), sinkPortConfigIds.end());
648 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPatch(
649 requestedPatch, &appliedPatch)));
650 patchIt = mPatches.insert(mPatches.end(), std::make_pair(appliedPatch.id, appliedPatch));
651 *created = true;
652 } else {
653 *created = false;
654 }
655 *patch = patchIt->second;
656 return OK;
657}
658
659status_t DeviceHalAidl::findOrCreatePortConfig(const AudioDevice& device,
660 AudioPortConfig* portConfig, bool* created) {
661 auto portConfigIt = findPortConfig(device);
662 if (portConfigIt == mPortConfigs.end()) {
663 auto portsIt = findPort(device);
664 if (portsIt == mPorts.end()) {
665 ALOGE("%s: device port for device %s is not found in the module %s",
666 __func__, device.toString().c_str(), mInstance.c_str());
667 return BAD_VALUE;
668 }
669 AudioPortConfig requestedPortConfig;
670 requestedPortConfig.portId = portsIt->first;
671 AudioPortConfig appliedPortConfig;
672 RETURN_STATUS_IF_ERROR(createPortConfig(requestedPortConfig, &appliedPortConfig));
673 portConfigIt = mPortConfigs.insert(
674 mPortConfigs.end(), std::make_pair(appliedPortConfig.id, appliedPortConfig));
675 *created = true;
676 } else {
677 *created = false;
678 }
679 *portConfig = portConfigIt->second;
680 return OK;
681}
682
683status_t DeviceHalAidl::findOrCreatePortConfig(
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800684 const AudioConfig& config, const std::optional<AudioIoFlags>& flags, int32_t ioHandle,
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800685 AudioPortConfig* portConfig, bool* created) {
686 auto portConfigIt = findPortConfig(config, flags, ioHandle);
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800687 if (portConfigIt == mPortConfigs.end() && flags.has_value()) {
688 auto portsIt = findPort(config, flags.value());
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800689 if (portsIt == mPorts.end()) {
690 ALOGE("%s: mix port for config %s, flags %s is not found in the module %s",
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800691 __func__, config.toString().c_str(), flags.value().toString().c_str(),
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800692 mInstance.c_str());
693 return BAD_VALUE;
694 }
695 AudioPortConfig requestedPortConfig;
696 requestedPortConfig.portId = portsIt->first;
697 setPortConfigFromConfig(&requestedPortConfig, config);
698 AudioPortConfig appliedPortConfig;
699 RETURN_STATUS_IF_ERROR(createPortConfig(requestedPortConfig, &appliedPortConfig));
700 appliedPortConfig.ext.get<AudioPortExt::Tag::mix>().handle = ioHandle;
701 portConfigIt = mPortConfigs.insert(
702 mPortConfigs.end(), std::make_pair(appliedPortConfig.id, appliedPortConfig));
703 *created = true;
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800704 } else if (!flags.has_value()) {
705 ALOGW("%s: mix port config for %s, handle %d not found in the module %s, "
706 "and was not created as flags are not specified",
707 __func__, config.toString().c_str(), ioHandle, mInstance.c_str());
708 return BAD_VALUE;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800709 } else {
710 *created = false;
711 }
712 *portConfig = portConfigIt->second;
713 return OK;
714}
715
716status_t DeviceHalAidl::findOrCreatePortConfig(
717 const AudioPortConfig& requestedPortConfig, AudioPortConfig* portConfig, bool* created) {
718 using Tag = AudioPortExt::Tag;
719 if (requestedPortConfig.ext.getTag() == Tag::mix) {
720 if (const auto& p = requestedPortConfig;
721 !p.sampleRate.has_value() || !p.channelMask.has_value() ||
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800722 !p.format.has_value()) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800723 ALOGW("%s: provided mix port config is not fully specified: %s",
724 __func__, p.toString().c_str());
725 return BAD_VALUE;
726 }
727 AudioConfig config;
728 setConfigFromPortConfig(&config, requestedPortConfig);
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800729 return findOrCreatePortConfig(config, requestedPortConfig.flags,
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800730 requestedPortConfig.ext.get<Tag::mix>().handle, portConfig, created);
731 } else if (requestedPortConfig.ext.getTag() == Tag::device) {
732 return findOrCreatePortConfig(
733 requestedPortConfig.ext.get<Tag::device>().device, portConfig, created);
734 }
735 ALOGW("%s: unsupported audio port config: %s",
736 __func__, requestedPortConfig.toString().c_str());
737 return BAD_VALUE;
738}
739
740DeviceHalAidl::Patches::iterator DeviceHalAidl::findPatch(
741 const std::set<int32_t>& sourcePortConfigIds, const std::set<int32_t>& sinkPortConfigIds) {
742 return std::find_if(mPatches.begin(), mPatches.end(),
743 [&](const auto& pair) {
744 const auto& p = pair.second;
745 std::set<int32_t> patchSrcs(
746 p.sourcePortConfigIds.begin(), p.sourcePortConfigIds.end());
747 std::set<int32_t> patchSinks(
748 p.sinkPortConfigIds.begin(), p.sinkPortConfigIds.end());
749 return sourcePortConfigIds == patchSrcs && sinkPortConfigIds == patchSinks; });
750}
751
752DeviceHalAidl::Ports::iterator DeviceHalAidl::findPort(const AudioDevice& device) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800753 if (device.type.type == AudioDeviceType::IN_DEFAULT) {
754 return mPorts.find(mDefaultInputPortId);
755 } else if (device.type.type == AudioDeviceType::OUT_DEFAULT) {
756 return mPorts.find(mDefaultOutputPortId);
757 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800758 return std::find_if(mPorts.begin(), mPorts.end(),
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800759 [&](const auto& pair) { return audioDeviceMatches(device, pair.second); });
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800760}
761
762DeviceHalAidl::Ports::iterator DeviceHalAidl::findPort(
763 const AudioConfig& config, const AudioIoFlags& flags) {
764 using Tag = AudioPortExt::Tag;
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800765 AudioIoFlags matchFlags = flags;
766 auto matcher = [&](const auto& pair) {
767 const auto& p = pair.second;
768 return p.ext.getTag() == Tag::mix &&
769 p.flags == matchFlags &&
770 std::find_if(p.profiles.begin(), p.profiles.end(),
771 [&](const auto& prof) {
772 return prof.format == config.base.format &&
773 std::find(prof.channelMasks.begin(), prof.channelMasks.end(),
774 config.base.channelMask) != prof.channelMasks.end() &&
775 std::find(prof.sampleRates.begin(), prof.sampleRates.end(),
776 config.base.sampleRate) != prof.sampleRates.end();
777 }) != p.profiles.end(); };
778 auto it = std::find_if(mPorts.begin(), mPorts.end(), matcher);
779 if (it == mPorts.end() && flags.getTag() == AudioIoFlags::Tag::input &&
780 isBitPositionFlagSet(flags.get<AudioIoFlags::Tag::input>(), AudioInputFlags::FAST)) {
781 // "Fast" input is not a mandatory flag, try without it.
782 matchFlags.set<AudioIoFlags::Tag::input>(flags.get<AudioIoFlags::Tag::input>() &
783 ~makeBitPositionFlagMask(AudioInputFlags::FAST));
784 it = std::find_if(mPorts.begin(), mPorts.end(), matcher);
785 }
786 return it;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800787}
788
789DeviceHalAidl::PortConfigs::iterator DeviceHalAidl::findPortConfig(const AudioDevice& device) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800790 return std::find_if(mPortConfigs.begin(), mPortConfigs.end(),
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800791 [&](const auto& pair) { return audioDeviceMatches(device, pair.second); });
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800792}
793
794DeviceHalAidl::PortConfigs::iterator DeviceHalAidl::findPortConfig(
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800795 const AudioConfig& config, const std::optional<AudioIoFlags>& flags, int32_t ioHandle) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800796 using Tag = AudioPortExt::Tag;
797 return std::find_if(mPortConfigs.begin(), mPortConfigs.end(),
798 [&](const auto& pair) {
799 const auto& p = pair.second;
800 LOG_ALWAYS_FATAL_IF(p.ext.getTag() == Tag::mix &&
801 !p.sampleRate.has_value() || !p.channelMask.has_value() ||
802 !p.format.has_value() || !p.flags.has_value(),
803 "%s: stored mix port config is not fully specified: %s",
804 __func__, p.toString().c_str());
805 return p.ext.getTag() == Tag::mix &&
806 isConfigEqualToPortConfig(config, p) &&
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800807 (!flags.has_value() || p.flags.value() == flags.value()) &&
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800808 p.ext.template get<Tag::mix>().handle == ioHandle; });
809}
810/*
811DeviceHalAidl::PortConfigs::iterator DeviceHalAidl::findPortConfig(
812 const AudioPortConfig& portConfig) {
813 using Tag = AudioPortExt::Tag;
814 if (portConfig.ext.getTag() == Tag::mix) {
815 return std::find_if(mPortConfigs.begin(), mPortConfigs.end(),
816 [&](const auto& pair) {
817 const auto& p = pair.second;
818 LOG_ALWAYS_FATAL_IF(p.ext.getTag() == Tag::mix &&
819 !p.sampleRate.has_value() || !p.channelMask.has_value() ||
820 !p.format.has_value() || !p.flags.has_value(),
821 "%s: stored mix port config is not fully specified: %s",
822 __func__, p.toString().c_str());
823 return p.ext.getTag() == Tag::mix &&
824 (!portConfig.sampleRate.has_value() ||
825 p.sampleRate == portConfig.sampleRate) &&
826 (!portConfig.channelMask.has_value() ||
827 p.channelMask == portConfig.channelMask) &&
828 (!portConfig.format.has_value() || p.format == portConfig.format) &&
829 (!portConfig.flags.has_value() || p.flags == portConfig.flags) &&
830 p.ext.template get<Tag::mix>().handle ==
831 portConfig.ext.template get<Tag::mix>().handle; });
832 } else if (portConfig.ext.getTag() == Tag::device) {
833 return findPortConfig(portConfig.ext.get<Tag::device>().device);
834 }
835 return mPortConfigs.end();
836}
837*/
838void DeviceHalAidl::resetPatch(int32_t patchId) {
839 if (auto it = mPatches.find(patchId); it != mPatches.end()) {
840 mPatches.erase(it);
841 TIME_CHECK();
842 if (ndk::ScopedAStatus status = mModule->resetAudioPatch(patchId); !status.isOk()) {
843 ALOGE("%s: error while resetting patch %d: %s",
844 __func__, patchId, status.getDescription().c_str());
845 }
846 return;
847 }
848 ALOGE("%s: patch id %d not found", __func__, patchId);
849}
850
851void DeviceHalAidl::resetPortConfig(int32_t portConfigId) {
852 if (auto it = mPortConfigs.find(portConfigId); it != mPortConfigs.end()) {
853 mPortConfigs.erase(it);
854 TIME_CHECK();
855 if (ndk::ScopedAStatus status = mModule->resetAudioPortConfig(portConfigId);
856 !status.isOk()) {
857 ALOGE("%s: error while resetting port config %d: %s",
858 __func__, portConfigId, status.getDescription().c_str());
859 }
860 return;
861 }
862 ALOGE("%s: port config id %d not found", __func__, portConfigId);
863}
864
Mikhail Naganov31d46652023-01-10 18:29:25 +0000865} // namespace android