blob: 1445e49529662e432deeef0d959e4c90dcfcdbb1 [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>
28#include <utils/Log.h>
Shunkai Yao51202502022-12-12 06:11:46 +000029
Mikhail Naganov31d46652023-01-10 18:29:25 +000030#include "DeviceHalAidl.h"
31#include "StreamHalAidl.h"
32
Mikhail Naganovfab697c2023-01-11 19:33:13 +000033using aidl::android::aidl_utils::statusTFromBinderStatus;
Mikhail Naganovf56ce782023-01-25 11:29:11 -080034using aidl::android::media::audio::common::AudioConfig;
35using aidl::android::media::audio::common::AudioDevice;
36using aidl::android::media::audio::common::AudioIoFlags;
Mikhail Naganovfab697c2023-01-11 19:33:13 +000037using aidl::android::media::audio::common::AudioMode;
Mikhail Naganovf56ce782023-01-25 11:29:11 -080038using aidl::android::media::audio::common::AudioOutputFlags;
39using aidl::android::media::audio::common::AudioPort;
40using aidl::android::media::audio::common::AudioPortConfig;
41using aidl::android::media::audio::common::AudioPortExt;
42using aidl::android::media::audio::common::AudioSource;
43using aidl::android::media::audio::common::Int;
Mikhail Naganovfab697c2023-01-11 19:33:13 +000044using aidl::android::media::audio::common::Float;
Mikhail Naganovf56ce782023-01-25 11:29:11 -080045using aidl::android::hardware::audio::common::RecordTrackMetadata;
46using aidl::android::hardware::audio::core::AudioPatch;
Mikhail Naganovfab697c2023-01-11 19:33:13 +000047using aidl::android::hardware::audio::core::IModule;
48using aidl::android::hardware::audio::core::ITelephony;
49using aidl::android::hardware::audio::core::StreamDescriptor;
Vlad Popa03bd5bc2023-01-17 16:16:51 +010050using aidl::android::hardware::audio::core::sounddose::ISoundDose;
Mikhail Naganov31d46652023-01-10 18:29:25 +000051
52namespace android {
53
Mikhail Naganovf56ce782023-01-25 11:29:11 -080054namespace {
55
56bool isConfigEqualToPortConfig(const AudioConfig& config, const AudioPortConfig& portConfig) {
57 return portConfig.sampleRate.value().value == config.base.sampleRate &&
58 portConfig.channelMask.value() == config.base.channelMask &&
59 portConfig.format.value() == config.base.format;
60}
61
62void setConfigFromPortConfig(AudioConfig* config, const AudioPortConfig& portConfig) {
63 config->base.sampleRate = portConfig.sampleRate.value().value;
64 config->base.channelMask = portConfig.channelMask.value();
65 config->base.format = portConfig.format.value();
66}
67
68void setPortConfigFromConfig(AudioPortConfig* portConfig, const AudioConfig& config) {
69 portConfig->sampleRate = Int{ .value = config.base.sampleRate };
70 portConfig->channelMask = config.base.channelMask;
71 portConfig->format = config.base.format;
72}
73
74} // namespace
75
Mikhail Naganov31d46652023-01-10 18:29:25 +000076status_t DeviceHalAidl::getSupportedDevices(uint32_t*) {
77 // Obsolete.
78 return INVALID_OPERATION;
Shunkai Yao51202502022-12-12 06:11:46 +000079}
80
81status_t DeviceHalAidl::initCheck() {
Mikhail Naganovf56ce782023-01-25 11:29:11 -080082 TIME_CHECK();
Mikhail Naganov31d46652023-01-10 18:29:25 +000083 if (mModule == nullptr) return NO_INIT;
Mikhail Naganovf56ce782023-01-25 11:29:11 -080084 std::vector<AudioPort> ports;
85 RETURN_STATUS_IF_ERROR(
86 statusTFromBinderStatus(mModule->getAudioPorts(&ports)));
87 ALOGW_IF(ports.empty(), "%s: module %s returned an empty list of audio ports",
88 __func__, mInstance.c_str());
89 std::transform(ports.begin(), ports.end(), std::inserter(mPorts, mPorts.end()),
90 [](const auto& p) { return std::make_pair(p.id, p); });
91 std::vector<AudioPortConfig> portConfigs;
92 RETURN_STATUS_IF_ERROR(
93 statusTFromBinderStatus(mModule->getAudioPortConfigs(&portConfigs))); // OK if empty
94 std::transform(portConfigs.begin(), portConfigs.end(),
95 std::inserter(mPortConfigs, mPortConfigs.end()),
96 [](const auto& p) { return std::make_pair(p.id, p); });
97 std::vector<AudioPatch> patches;
98 RETURN_STATUS_IF_ERROR(
99 statusTFromBinderStatus(mModule->getAudioPatches(&patches))); // OK if empty
100 std::transform(patches.begin(), patches.end(),
101 std::inserter(mPatches, mPatches.end()),
102 [](const auto& p) { return std::make_pair(p.id, p); });
Shunkai Yao51202502022-12-12 06:11:46 +0000103 return OK;
104}
105
106status_t DeviceHalAidl::setVoiceVolume(float volume) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000107 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000108 if (!mModule) return NO_INIT;
109 std::shared_ptr<ITelephony> telephony;
110 if (ndk::ScopedAStatus status = mModule->getTelephony(&telephony);
111 status.isOk() && telephony != nullptr) {
112 ITelephony::TelecomConfig inConfig{ .voiceVolume = Float{volume} }, outConfig;
113 RETURN_STATUS_IF_ERROR(
114 statusTFromBinderStatus(telephony->setTelecomConfig(inConfig, &outConfig)));
115 ALOGW_IF(outConfig.voiceVolume.has_value() && volume != outConfig.voiceVolume.value().value,
116 "%s: the resulting voice volume %f is not the same as requested %f",
117 __func__, outConfig.voiceVolume.value().value, volume);
118 }
119 return INVALID_OPERATION;
Shunkai Yao51202502022-12-12 06:11:46 +0000120}
121
122status_t DeviceHalAidl::setMasterVolume(float volume) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000123 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000124 if (!mModule) return NO_INIT;
125 return statusTFromBinderStatus(mModule->setMasterVolume(volume));
Shunkai Yao51202502022-12-12 06:11:46 +0000126}
127
128status_t DeviceHalAidl::getMasterVolume(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 return statusTFromBinderStatus(mModule->getMasterVolume(volume));
Shunkai Yao51202502022-12-12 06:11:46 +0000132}
133
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000134status_t DeviceHalAidl::setMode(audio_mode_t mode) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000135 TIME_CHECK();
136 if (!mModule) return NO_INIT;
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000137 AudioMode audioMode = VALUE_OR_FATAL(::aidl::android::legacy2aidl_audio_mode_t_AudioMode(mode));
138 std::shared_ptr<ITelephony> telephony;
139 if (ndk::ScopedAStatus status = mModule->getTelephony(&telephony);
140 status.isOk() && telephony != nullptr) {
141 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(telephony->switchAudioMode(audioMode)));
142 }
143 return statusTFromBinderStatus(mModule->updateAudioMode(audioMode));
Shunkai Yao51202502022-12-12 06:11:46 +0000144}
145
146status_t DeviceHalAidl::setMicMute(bool state) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000147 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000148 if (!mModule) return NO_INIT;
149 return statusTFromBinderStatus(mModule->setMicMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000150}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000151
Shunkai Yao51202502022-12-12 06:11:46 +0000152status_t DeviceHalAidl::getMicMute(bool *state) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000153 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000154 if (!mModule) return NO_INIT;
155 return statusTFromBinderStatus(mModule->getMicMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000156}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000157
Shunkai Yao51202502022-12-12 06:11:46 +0000158status_t DeviceHalAidl::setMasterMute(bool state) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000159 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000160 if (!mModule) return NO_INIT;
161 return statusTFromBinderStatus(mModule->setMasterMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000162}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000163
Shunkai Yao51202502022-12-12 06:11:46 +0000164status_t DeviceHalAidl::getMasterMute(bool *state) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000165 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000166 if (!mModule) return NO_INIT;
167 return statusTFromBinderStatus(mModule->getMasterMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000168}
169
Mikhail Naganov31d46652023-01-10 18:29:25 +0000170status_t DeviceHalAidl::setParameters(const String8& kvPairs __unused) {
171 TIME_CHECK();
172 if (!mModule) return NO_INIT;
173 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000174 return OK;
175}
176
Mikhail Naganov31d46652023-01-10 18:29:25 +0000177status_t DeviceHalAidl::getParameters(const String8& keys __unused, String8 *values) {
178 TIME_CHECK();
179 values->clear();
180 if (!mModule) return NO_INIT;
181 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000182 return OK;
183}
184
Mikhail Naganov31d46652023-01-10 18:29:25 +0000185status_t DeviceHalAidl::getInputBufferSize(
186 const struct audio_config* config __unused, size_t* size __unused) {
187 TIME_CHECK();
188 if (!mModule) return NO_INIT;
189 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000190 return OK;
191}
192
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800193namespace {
194
195class Cleanup {
196 public:
197 typedef void (DeviceHalAidl::*Cleaner)(int32_t);
198
199 Cleanup(DeviceHalAidl* device, Cleaner cleaner, int32_t id) :
200 mDevice(device), mCleaner(cleaner), mId(id) {}
201 ~Cleanup() { clean(); }
202 void clean() {
203 if (mDevice != nullptr) (mDevice->*mCleaner)(mId);
204 disarm();
205 }
206 void disarm() { mDevice = nullptr; }
207
208 private:
209 DeviceHalAidl* mDevice;
210 const Cleaner mCleaner;
211 const int32_t mId;
212};
213
214} // namespace
215
216// Since the order of container elements destruction is unspecified,
217// ensure that cleanups are performed from the most recent one and upwards.
218// This is the same as if there were individual Cleanup instances on the stack,
219// however the bonus is that we can disarm all of them with just one statement.
220class DeviceHalAidl::Cleanups : public std::forward_list<Cleanup> {
221 public:
222 ~Cleanups() { for (auto& c : *this) c.clean(); }
223 void disarmAll() { for (auto& c : *this) c.disarm(); }
224};
225
226status_t DeviceHalAidl::prepareToOpenStream(
227 int32_t aidlHandle, const AudioDevice& aidlDevice, const AudioIoFlags& aidlFlags,
228 struct audio_config* config,
229 Cleanups* cleanups, AudioConfig* aidlConfig, AudioPortConfig* mixPortConfig) {
230 const bool isInput = aidlFlags.getTag() == AudioIoFlags::Tag::input;
231 // Find / create AudioPortConfigs for the device port and the mix port,
232 // then find / create a patch between them, and open a stream on the mix port.
233 AudioPortConfig devicePortConfig;
234 bool created = false;
235 RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(aidlDevice, &devicePortConfig, &created));
236 if (created) {
237 cleanups->emplace_front(this, &DeviceHalAidl::resetPortConfig, devicePortConfig.id);
238 }
239 RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(*aidlConfig, aidlFlags, aidlHandle,
240 mixPortConfig, &created));
241 if (created) {
242 cleanups->emplace_front(this, &DeviceHalAidl::resetPortConfig, mixPortConfig->id);
243 }
244 setConfigFromPortConfig(aidlConfig, *mixPortConfig);
245 AudioPatch patch;
246 if (isInput) {
247 RETURN_STATUS_IF_ERROR(findOrCreatePatch(
248 {devicePortConfig.id}, {mixPortConfig->id}, &patch, &created));
249 } else {
250 RETURN_STATUS_IF_ERROR(findOrCreatePatch(
251 {mixPortConfig->id}, {devicePortConfig.id}, &patch, &created));
252 }
253 if (created) {
254 cleanups->emplace_front(this, &DeviceHalAidl::resetPatch, patch.id);
255 }
256 if (aidlConfig->frameCount <= 0) {
257 aidlConfig->frameCount = patch.minimumStreamBufferSizeFrames;
258 }
259 *config = VALUE_OR_RETURN_STATUS(
260 ::aidl::android::aidl2legacy_AudioConfig_audio_config_t(*aidlConfig, isInput));
261 return OK;
262}
263
Mikhail Naganov31d46652023-01-10 18:29:25 +0000264status_t DeviceHalAidl::openOutputStream(
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800265 audio_io_handle_t handle, audio_devices_t devices,
266 audio_output_flags_t flags, struct audio_config* config,
267 const char* address,
Mikhail Naganov31d46652023-01-10 18:29:25 +0000268 sp<StreamOutHalInterface>* outStream) {
269 if (!outStream || !config) {
270 return BAD_VALUE;
271 }
272 TIME_CHECK();
273 if (!mModule) return NO_INIT;
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800274 int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
275 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(handle));
276 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
277 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, false /*isInput*/));
278 AudioDevice aidlDevice = VALUE_OR_RETURN_STATUS(
279 ::aidl::android::legacy2aidl_audio_device_AudioDevice(devices, address));
280 int32_t aidlOutputFlags = VALUE_OR_RETURN_STATUS(
281 ::aidl::android::legacy2aidl_audio_output_flags_t_int32_t_mask(flags));
282 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::output>(aidlOutputFlags);
283 AudioPortConfig mixPortConfig;
284 Cleanups cleanups;
285 RETURN_STATUS_IF_ERROR(prepareToOpenStream(aidlHandle, aidlDevice, aidlFlags, config,
286 &cleanups, &aidlConfig, &mixPortConfig));
287 ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamArguments args;
288 args.portConfigId = mixPortConfig.id;
289 args.offloadInfo = aidlConfig.offloadInfo;
290 args.bufferSizeFrames = aidlConfig.frameCount;
291 ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamReturn ret;
292 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openOutputStream(args, &ret)));
293 *outStream = sp<StreamOutHalAidl>::make(*config, std::move(ret.desc), std::move(ret.stream));
294 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000295 return OK;
296}
297
Mikhail Naganov31d46652023-01-10 18:29:25 +0000298status_t DeviceHalAidl::openInputStream(
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800299 audio_io_handle_t handle, audio_devices_t devices,
300 struct audio_config* config, audio_input_flags_t flags,
301 const char* address, audio_source_t source,
302 audio_devices_t outputDevice, const char* outputDeviceAddress,
Mikhail Naganov31d46652023-01-10 18:29:25 +0000303 sp<StreamInHalInterface>* inStream) {
304 if (!inStream || !config) {
305 return BAD_VALUE;
306 }
307 TIME_CHECK();
308 if (!mModule) return NO_INIT;
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800309 int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
310 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(handle));
311 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
312 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, true /*isInput*/));
313 AudioDevice aidlDevice = VALUE_OR_RETURN_STATUS(
314 ::aidl::android::legacy2aidl_audio_device_AudioDevice(devices, address));
315 int32_t aidlInputFlags = VALUE_OR_RETURN_STATUS(
316 ::aidl::android::legacy2aidl_audio_input_flags_t_int32_t_mask(flags));
317 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::input>(aidlInputFlags);
318 AudioSource aidlSource = VALUE_OR_RETURN_STATUS(
319 ::aidl::android::legacy2aidl_audio_source_t_AudioSource(source));
320 AudioPortConfig mixPortConfig;
321 Cleanups cleanups;
322 RETURN_STATUS_IF_ERROR(prepareToOpenStream(aidlHandle, aidlDevice, aidlFlags, config,
323 &cleanups, &aidlConfig, &mixPortConfig));
324 ::aidl::android::hardware::audio::core::IModule::OpenInputStreamArguments args;
325 args.portConfigId = mixPortConfig.id;
326 RecordTrackMetadata aidlTrackMetadata{
327 .source = aidlSource, .gain = 1, .channelMask = aidlConfig.base.channelMask };
328 if (outputDevice != AUDIO_DEVICE_NONE) {
329 aidlTrackMetadata.destinationDevice = VALUE_OR_RETURN_STATUS(
330 ::aidl::android::legacy2aidl_audio_device_AudioDevice(
331 outputDevice, outputDeviceAddress));
332 }
333 args.sinkMetadata.tracks.push_back(std::move(aidlTrackMetadata));
334 args.bufferSizeFrames = aidlConfig.frameCount;
335 ::aidl::android::hardware::audio::core::IModule::OpenInputStreamReturn ret;
336 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openInputStream(args, &ret)));
337 *inStream = sp<StreamInHalAidl>::make(*config, std::move(ret.desc), std::move(ret.stream));
338 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000339 return OK;
340}
341
342status_t DeviceHalAidl::supportsAudioPatches(bool* supportsPatches) {
343 *supportsPatches = true;
344 return OK;
345}
346
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800347status_t DeviceHalAidl::createAudioPatch(unsigned int num_sources,
348 const struct audio_port_config* sources,
349 unsigned int num_sinks,
350 const struct audio_port_config* sinks,
351 audio_patch_handle_t* patch) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000352 TIME_CHECK();
353 if (!mModule) return NO_INIT;
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800354 if (num_sinks > AUDIO_PATCH_PORTS_MAX || num_sources > AUDIO_PATCH_PORTS_MAX ||
355 sources == nullptr || sinks == nullptr || patch == nullptr) {
356 return BAD_VALUE;
357 }
358 // Note that the patch handle (*patch) is provided by the framework.
359 // In tests it's possible that its value is AUDIO_PATCH_HANDLE_NONE.
360
361 // Upon conversion, mix port configs contain audio configuration, while
362 // device port configs contain device address. This data is used to find
363 // or create HAL configs.
364 std::vector<AudioPortConfig> aidlSources, aidlSinks;
365 for (unsigned int i = 0; i < num_sources; ++i) {
366 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
367 sources[i].role, sources[i].type)) ==
368 ::aidl::android::AudioPortDirection::INPUT;
369 aidlSources.push_back(VALUE_OR_RETURN_STATUS(
370 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
371 sources[i], isInput, 0)));
372 }
373 for (unsigned int i = 0; i < num_sinks; ++i) {
374 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
375 sinks[i].role, sinks[i].type)) ==
376 ::aidl::android::AudioPortDirection::INPUT;
377 aidlSinks.push_back(VALUE_OR_RETURN_STATUS(
378 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
379 sinks[i], isInput, 0)));
380 }
381 Cleanups cleanups;
382 auto existingPatchIt = mPatches.end();
383 auto fwkHandlesIt = *patch != AUDIO_PATCH_HANDLE_NONE ?
384 mFwkHandles.find(*patch) : mFwkHandles.end();
385 AudioPatch aidlPatch;
386 if (fwkHandlesIt != mFwkHandles.end()) {
387 existingPatchIt = mPatches.find(fwkHandlesIt->second);
388 if (existingPatchIt != mPatches.end()) {
389 aidlPatch = existingPatchIt->second;
390 aidlPatch.sourcePortConfigIds.clear();
391 aidlPatch.sinkPortConfigIds.clear();
392 }
393 }
394 auto fillPortConfigs = [&](
395 const std::vector<AudioPortConfig>& configs, std::vector<int32_t>* ids) -> status_t {
396 for (const auto& s : configs) {
397 AudioPortConfig portConfig;
398 bool created = false;
399 RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(s, &portConfig, &created));
400 if (created) {
401 cleanups.emplace_front(this, &DeviceHalAidl::resetPortConfig, portConfig.id);
402 }
403 ids->push_back(portConfig.id);
404 }
405 return OK;
406 };
407 RETURN_STATUS_IF_ERROR(fillPortConfigs(aidlSources, &aidlPatch.sourcePortConfigIds));
408 RETURN_STATUS_IF_ERROR(fillPortConfigs(aidlSinks, &aidlPatch.sinkPortConfigIds));
409 if (existingPatchIt != mPatches.end()) {
410 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
411 mModule->setAudioPatch(aidlPatch, &aidlPatch)));
412 existingPatchIt->second = aidlPatch;
413 } else {
414 bool created = false;
415 RETURN_STATUS_IF_ERROR(findOrCreatePatch(aidlPatch, &aidlPatch, &created));
416 // Since no cleanup of the patch is needed, 'created' is ignored.
417 if (fwkHandlesIt != mFwkHandles.end()) {
418 fwkHandlesIt->second = aidlPatch.id;
419 // Patch handle (*patch) stays the same.
420 } else {
421 if (*patch == AUDIO_PATCH_HANDLE_NONE) {
422 // This isn't good as the module can't provide a handle which is really unique.
423 // However, this situation should only happen in tests.
424 *patch = aidlPatch.id;
425 LOG_ALWAYS_FATAL_IF(mFwkHandles.count(*patch) > 0,
426 "%s: patch id %d clashes with another framework patch handle",
427 __func__, *patch);
428 }
429 mFwkHandles.emplace(*patch, aidlPatch.id);
430 }
431 }
432 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000433 return OK;
434}
435
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800436status_t DeviceHalAidl::releaseAudioPatch(audio_patch_handle_t patch) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000437 TIME_CHECK();
438 if (!mModule) return NO_INIT;
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800439 auto idMapIt = mFwkHandles.find(patch);
440 if (idMapIt == mFwkHandles.end()) {
441 return BAD_VALUE;
442 }
443 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->resetAudioPatch(idMapIt->second)));
444 mFwkHandles.erase(idMapIt);
Shunkai Yao51202502022-12-12 06:11:46 +0000445 return OK;
446}
447
Mikhail Naganov31d46652023-01-10 18:29:25 +0000448status_t DeviceHalAidl::getAudioPort(struct audio_port* port __unused) {
449 TIME_CHECK();
450 ALOGE("%s not implemented yet", __func__);
451 return INVALID_OPERATION;
452}
453
454status_t DeviceHalAidl::getAudioPort(struct audio_port_v7 *port __unused) {
455 TIME_CHECK();
456 ALOGE("%s not implemented yet", __func__);
457 return INVALID_OPERATION;
458}
459
460status_t DeviceHalAidl::setAudioPortConfig(const struct audio_port_config* config __unused) {
461 TIME_CHECK();
462 if (!mModule) return NO_INIT;
463 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000464 return OK;
465}
466
467status_t DeviceHalAidl::getMicrophones(
Mikhail Naganov31d46652023-01-10 18:29:25 +0000468 std::vector<audio_microphone_characteristic_t>* microphones __unused) {
469 TIME_CHECK();
470 if (!mModule) return NO_INIT;
471 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000472 return OK;
473}
474
Mikhail Naganov31d46652023-01-10 18:29:25 +0000475status_t DeviceHalAidl::addDeviceEffect(audio_port_handle_t device __unused,
476 sp<EffectHalInterface> effect) {
Shunkai Yao51202502022-12-12 06:11:46 +0000477 if (!effect) {
478 return BAD_VALUE;
479 }
Mikhail Naganov31d46652023-01-10 18:29:25 +0000480 TIME_CHECK();
481 if (!mModule) return NO_INIT;
482 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000483 return OK;
484}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000485status_t DeviceHalAidl::removeDeviceEffect(audio_port_handle_t device __unused,
Shunkai Yao51202502022-12-12 06:11:46 +0000486 sp<EffectHalInterface> effect) {
487 if (!effect) {
488 return BAD_VALUE;
489 }
Mikhail Naganov31d46652023-01-10 18:29:25 +0000490 TIME_CHECK();
491 if (!mModule) return NO_INIT;
492 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000493 return OK;
494}
495
496status_t DeviceHalAidl::getMmapPolicyInfos(
497 media::audio::common::AudioMMapPolicyType policyType __unused,
498 std::vector<media::audio::common::AudioMMapPolicyInfo>* policyInfos __unused) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000499 TIME_CHECK();
Shunkai Yao51202502022-12-12 06:11:46 +0000500 ALOGE("%s not implemented yet", __func__);
501 return OK;
502}
503
504int32_t DeviceHalAidl::getAAudioMixerBurstCount() {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000505 TIME_CHECK();
Shunkai Yao51202502022-12-12 06:11:46 +0000506 ALOGE("%s not implemented yet", __func__);
507 return OK;
508}
509
510int32_t DeviceHalAidl::getAAudioHardwareBurstMinUsec() {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000511 TIME_CHECK();
Shunkai Yao51202502022-12-12 06:11:46 +0000512 ALOGE("%s not implemented yet", __func__);
513 return OK;
514}
515
516error::Result<audio_hw_sync_t> DeviceHalAidl::getHwAvSync() {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000517 TIME_CHECK();
Shunkai Yao51202502022-12-12 06:11:46 +0000518 ALOGE("%s not implemented yet", __func__);
519 return base::unexpected(INVALID_OPERATION);
520}
521
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000522status_t DeviceHalAidl::dump(int fd, const Vector<String16>& args) {
523 TIME_CHECK();
524 if (!mModule) return NO_INIT;
525 return mModule->dump(fd, Args(args).args(), args.size());
Shunkai Yao51202502022-12-12 06:11:46 +0000526};
527
Mikhail Naganov31d46652023-01-10 18:29:25 +0000528int32_t DeviceHalAidl::supportsBluetoothVariableLatency(bool* supports __unused) {
529 TIME_CHECK();
Shunkai Yao51202502022-12-12 06:11:46 +0000530 ALOGE("%s not implemented yet", __func__);
531 return INVALID_OPERATION;
532}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000533
Vlad Popa03bd5bc2023-01-17 16:16:51 +0100534status_t DeviceHalAidl::getSoundDoseInterface(const std::string& module,
535 ::ndk::SpAIBinder* soundDoseBinder) {
536 TIME_CHECK();
537 if (!mModule) return NO_INIT;
538 if (mSoundDose == nullptr) {
539 ndk::ScopedAStatus status = mModule->getSoundDose(&mSoundDose);
540 if (!status.isOk()) {
541 ALOGE("%s failed to return the sound dose interface for module %s: %s",
542 __func__,
543 module.c_str(),
544 status.getDescription().c_str());
545 return BAD_VALUE;
546 }
547 }
548 *soundDoseBinder = mSoundDose->asBinder();
549 ALOGI("%s using audio AIDL HAL sound dose interface", __func__);
550
551 return OK;
552}
553
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800554status_t DeviceHalAidl::createPortConfig(const AudioPortConfig& requestedPortConfig,
555 AudioPortConfig* appliedPortConfig) {
556 TIME_CHECK();
557 bool applied = false;
558 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPortConfig(
559 requestedPortConfig, appliedPortConfig, &applied)));
560 if (!applied) {
561 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPortConfig(
562 *appliedPortConfig, appliedPortConfig, &applied)));
563 if (!applied) {
564 ALOGE("%s: module %s did not apply suggested config %s",
565 __func__, mInstance.c_str(), appliedPortConfig->toString().c_str());
566 return NO_INIT;
567 }
568 }
569 mPortConfigs.emplace(appliedPortConfig->id, *appliedPortConfig);
570 return OK;
571}
572
573status_t DeviceHalAidl::findOrCreatePatch(
574 const AudioPatch& requestedPatch, AudioPatch* patch, bool* created) {
575 std::set<int32_t> sourcePortConfigIds(requestedPatch.sourcePortConfigIds.begin(),
576 requestedPatch.sourcePortConfigIds.end());
577 std::set<int32_t> sinkPortConfigIds(requestedPatch.sinkPortConfigIds.begin(),
578 requestedPatch.sinkPortConfigIds.end());
579 return findOrCreatePatch(sourcePortConfigIds, sinkPortConfigIds, patch, created);
580}
581
582status_t DeviceHalAidl::findOrCreatePatch(
583 const std::set<int32_t>& sourcePortConfigIds, const std::set<int32_t>& sinkPortConfigIds,
584 AudioPatch* patch, bool* created) {
585 auto patchIt = findPatch(sourcePortConfigIds, sinkPortConfigIds);
586 if (patchIt == mPatches.end()) {
587 TIME_CHECK();
588 AudioPatch requestedPatch, appliedPatch;
589 requestedPatch.sourcePortConfigIds.insert(requestedPatch.sourcePortConfigIds.end(),
590 sourcePortConfigIds.begin(), sourcePortConfigIds.end());
591 requestedPatch.sinkPortConfigIds.insert(requestedPatch.sinkPortConfigIds.end(),
592 sinkPortConfigIds.begin(), sinkPortConfigIds.end());
593 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPatch(
594 requestedPatch, &appliedPatch)));
595 patchIt = mPatches.insert(mPatches.end(), std::make_pair(appliedPatch.id, appliedPatch));
596 *created = true;
597 } else {
598 *created = false;
599 }
600 *patch = patchIt->second;
601 return OK;
602}
603
604status_t DeviceHalAidl::findOrCreatePortConfig(const AudioDevice& device,
605 AudioPortConfig* portConfig, bool* created) {
606 auto portConfigIt = findPortConfig(device);
607 if (portConfigIt == mPortConfigs.end()) {
608 auto portsIt = findPort(device);
609 if (portsIt == mPorts.end()) {
610 ALOGE("%s: device port for device %s is not found in the module %s",
611 __func__, device.toString().c_str(), mInstance.c_str());
612 return BAD_VALUE;
613 }
614 AudioPortConfig requestedPortConfig;
615 requestedPortConfig.portId = portsIt->first;
616 AudioPortConfig appliedPortConfig;
617 RETURN_STATUS_IF_ERROR(createPortConfig(requestedPortConfig, &appliedPortConfig));
618 portConfigIt = mPortConfigs.insert(
619 mPortConfigs.end(), std::make_pair(appliedPortConfig.id, appliedPortConfig));
620 *created = true;
621 } else {
622 *created = false;
623 }
624 *portConfig = portConfigIt->second;
625 return OK;
626}
627
628status_t DeviceHalAidl::findOrCreatePortConfig(
629 const AudioConfig& config, const AudioIoFlags& flags, int32_t ioHandle,
630 AudioPortConfig* portConfig, bool* created) {
631 auto portConfigIt = findPortConfig(config, flags, ioHandle);
632 if (portConfigIt == mPortConfigs.end()) {
633 auto portsIt = findPort(config, flags);
634 if (portsIt == mPorts.end()) {
635 ALOGE("%s: mix port for config %s, flags %s is not found in the module %s",
636 __func__, config.toString().c_str(), flags.toString().c_str(),
637 mInstance.c_str());
638 return BAD_VALUE;
639 }
640 AudioPortConfig requestedPortConfig;
641 requestedPortConfig.portId = portsIt->first;
642 setPortConfigFromConfig(&requestedPortConfig, config);
643 AudioPortConfig appliedPortConfig;
644 RETURN_STATUS_IF_ERROR(createPortConfig(requestedPortConfig, &appliedPortConfig));
645 appliedPortConfig.ext.get<AudioPortExt::Tag::mix>().handle = ioHandle;
646 portConfigIt = mPortConfigs.insert(
647 mPortConfigs.end(), std::make_pair(appliedPortConfig.id, appliedPortConfig));
648 *created = true;
649 } else {
650 *created = false;
651 }
652 *portConfig = portConfigIt->second;
653 return OK;
654}
655
656status_t DeviceHalAidl::findOrCreatePortConfig(
657 const AudioPortConfig& requestedPortConfig, AudioPortConfig* portConfig, bool* created) {
658 using Tag = AudioPortExt::Tag;
659 if (requestedPortConfig.ext.getTag() == Tag::mix) {
660 if (const auto& p = requestedPortConfig;
661 !p.sampleRate.has_value() || !p.channelMask.has_value() ||
662 !p.format.has_value() || !p.flags.has_value()) {
663 ALOGW("%s: provided mix port config is not fully specified: %s",
664 __func__, p.toString().c_str());
665 return BAD_VALUE;
666 }
667 AudioConfig config;
668 setConfigFromPortConfig(&config, requestedPortConfig);
669 return findOrCreatePortConfig(config, requestedPortConfig.flags.value(),
670 requestedPortConfig.ext.get<Tag::mix>().handle, portConfig, created);
671 } else if (requestedPortConfig.ext.getTag() == Tag::device) {
672 return findOrCreatePortConfig(
673 requestedPortConfig.ext.get<Tag::device>().device, portConfig, created);
674 }
675 ALOGW("%s: unsupported audio port config: %s",
676 __func__, requestedPortConfig.toString().c_str());
677 return BAD_VALUE;
678}
679
680DeviceHalAidl::Patches::iterator DeviceHalAidl::findPatch(
681 const std::set<int32_t>& sourcePortConfigIds, const std::set<int32_t>& sinkPortConfigIds) {
682 return std::find_if(mPatches.begin(), mPatches.end(),
683 [&](const auto& pair) {
684 const auto& p = pair.second;
685 std::set<int32_t> patchSrcs(
686 p.sourcePortConfigIds.begin(), p.sourcePortConfigIds.end());
687 std::set<int32_t> patchSinks(
688 p.sinkPortConfigIds.begin(), p.sinkPortConfigIds.end());
689 return sourcePortConfigIds == patchSrcs && sinkPortConfigIds == patchSinks; });
690}
691
692DeviceHalAidl::Ports::iterator DeviceHalAidl::findPort(const AudioDevice& device) {
693 using Tag = AudioPortExt::Tag;
694 return std::find_if(mPorts.begin(), mPorts.end(),
695 [&](const auto& pair) {
696 const auto& p = pair.second;
697 return p.ext.getTag() == Tag::device &&
698 p.ext.template get<Tag::device>().device == device; });
699}
700
701DeviceHalAidl::Ports::iterator DeviceHalAidl::findPort(
702 const AudioConfig& config, const AudioIoFlags& flags) {
703 using Tag = AudioPortExt::Tag;
704 return std::find_if(mPorts.begin(), mPorts.end(),
705 [&](const auto& pair) {
706 const auto& p = pair.second;
707 return p.ext.getTag() == Tag::mix &&
708 p.flags == flags &&
709 std::find_if(p.profiles.begin(), p.profiles.end(),
710 [&](const auto& prof) {
711 return prof.format == config.base.format &&
712 std::find(prof.channelMasks.begin(),
713 prof.channelMasks.end(),
714 config.base.channelMask) !=
715 prof.channelMasks.end() &&
716 std::find(prof.sampleRates.begin(),
717 prof.sampleRates.end(),
718 config.base.sampleRate) !=
719 prof.sampleRates.end();
720 }) != p.profiles.end(); });
721}
722
723DeviceHalAidl::PortConfigs::iterator DeviceHalAidl::findPortConfig(const AudioDevice& device) {
724 using Tag = AudioPortExt::Tag;
725 return std::find_if(mPortConfigs.begin(), mPortConfigs.end(),
726 [&](const auto& pair) {
727 const auto& p = pair.second;
728 return p.ext.getTag() == Tag::device &&
729 p.ext.template get<Tag::device>().device == device; });
730}
731
732DeviceHalAidl::PortConfigs::iterator DeviceHalAidl::findPortConfig(
733 const AudioConfig& config, const AudioIoFlags& flags, int32_t ioHandle) {
734 using Tag = AudioPortExt::Tag;
735 return std::find_if(mPortConfigs.begin(), mPortConfigs.end(),
736 [&](const auto& pair) {
737 const auto& p = pair.second;
738 LOG_ALWAYS_FATAL_IF(p.ext.getTag() == Tag::mix &&
739 !p.sampleRate.has_value() || !p.channelMask.has_value() ||
740 !p.format.has_value() || !p.flags.has_value(),
741 "%s: stored mix port config is not fully specified: %s",
742 __func__, p.toString().c_str());
743 return p.ext.getTag() == Tag::mix &&
744 isConfigEqualToPortConfig(config, p) &&
745 p.flags.value() == flags &&
746 p.ext.template get<Tag::mix>().handle == ioHandle; });
747}
748/*
749DeviceHalAidl::PortConfigs::iterator DeviceHalAidl::findPortConfig(
750 const AudioPortConfig& portConfig) {
751 using Tag = AudioPortExt::Tag;
752 if (portConfig.ext.getTag() == Tag::mix) {
753 return std::find_if(mPortConfigs.begin(), mPortConfigs.end(),
754 [&](const auto& pair) {
755 const auto& p = pair.second;
756 LOG_ALWAYS_FATAL_IF(p.ext.getTag() == Tag::mix &&
757 !p.sampleRate.has_value() || !p.channelMask.has_value() ||
758 !p.format.has_value() || !p.flags.has_value(),
759 "%s: stored mix port config is not fully specified: %s",
760 __func__, p.toString().c_str());
761 return p.ext.getTag() == Tag::mix &&
762 (!portConfig.sampleRate.has_value() ||
763 p.sampleRate == portConfig.sampleRate) &&
764 (!portConfig.channelMask.has_value() ||
765 p.channelMask == portConfig.channelMask) &&
766 (!portConfig.format.has_value() || p.format == portConfig.format) &&
767 (!portConfig.flags.has_value() || p.flags == portConfig.flags) &&
768 p.ext.template get<Tag::mix>().handle ==
769 portConfig.ext.template get<Tag::mix>().handle; });
770 } else if (portConfig.ext.getTag() == Tag::device) {
771 return findPortConfig(portConfig.ext.get<Tag::device>().device);
772 }
773 return mPortConfigs.end();
774}
775*/
776void DeviceHalAidl::resetPatch(int32_t patchId) {
777 if (auto it = mPatches.find(patchId); it != mPatches.end()) {
778 mPatches.erase(it);
779 TIME_CHECK();
780 if (ndk::ScopedAStatus status = mModule->resetAudioPatch(patchId); !status.isOk()) {
781 ALOGE("%s: error while resetting patch %d: %s",
782 __func__, patchId, status.getDescription().c_str());
783 }
784 return;
785 }
786 ALOGE("%s: patch id %d not found", __func__, patchId);
787}
788
789void DeviceHalAidl::resetPortConfig(int32_t portConfigId) {
790 if (auto it = mPortConfigs.find(portConfigId); it != mPortConfigs.end()) {
791 mPortConfigs.erase(it);
792 TIME_CHECK();
793 if (ndk::ScopedAStatus status = mModule->resetAudioPortConfig(portConfigId);
794 !status.isOk()) {
795 ALOGE("%s: error while resetting port config %d: %s",
796 __func__, portConfigId, status.getDescription().c_str());
797 }
798 return;
799 }
800 ALOGE("%s: port config id %d not found", __func__, portConfigId);
801}
802
Mikhail Naganov31d46652023-01-10 18:29:25 +0000803} // namespace android