blob: 2951752a11bc75c29bf67215aa43f56ef6182290 [file] [log] [blame]
Shunkai Yao51202502022-12-12 06:11:46 +00001/*
2 * Copyright (C) 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "DeviceHalAidl"
Vlad Popa03bd5bc2023-01-17 16:16:51 +010018// #define LOG_NDEBUG 0
Shunkai Yao51202502022-12-12 06:11:46 +000019
Mikhail Naganovf56ce782023-01-25 11:29:11 -080020#include <algorithm>
21#include <forward_list>
22
Mikhail Naganovb0c55252023-02-08 16:59:41 -080023#include <aidl/android/hardware/audio/core/BnStreamCallback.h>
24#include <aidl/android/hardware/audio/core/BnStreamOutEventCallback.h>
Mikhail Naganovfab697c2023-01-11 19:33:13 +000025#include <aidl/android/hardware/audio/core/StreamDescriptor.h>
26#include <error/expected_utils.h>
27#include <media/AidlConversionCppNdk.h>
28#include <media/AidlConversionUtil.h>
Mikhail Naganov31d46652023-01-10 18:29:25 +000029#include <mediautils/TimeCheck.h>
Mikhail Naganov8bd806e2023-01-30 12:33:18 -080030#include <Utils.h>
Mikhail Naganov31d46652023-01-10 18:29:25 +000031#include <utils/Log.h>
Shunkai Yao51202502022-12-12 06:11:46 +000032
Mikhail Naganov31d46652023-01-10 18:29:25 +000033#include "DeviceHalAidl.h"
34#include "StreamHalAidl.h"
35
Mikhail Naganovfab697c2023-01-11 19:33:13 +000036using aidl::android::aidl_utils::statusTFromBinderStatus;
Mikhail Naganovf56ce782023-01-25 11:29:11 -080037using aidl::android::media::audio::common::AudioConfig;
38using aidl::android::media::audio::common::AudioDevice;
Mikhail Naganov8bd806e2023-01-30 12:33:18 -080039using aidl::android::media::audio::common::AudioDeviceType;
40using aidl::android::media::audio::common::AudioInputFlags;
Mikhail Naganovf56ce782023-01-25 11:29:11 -080041using aidl::android::media::audio::common::AudioIoFlags;
Mikhail Naganovb0c55252023-02-08 16:59:41 -080042using aidl::android::media::audio::common::AudioLatencyMode;
Mikhail Naganovfab697c2023-01-11 19:33:13 +000043using aidl::android::media::audio::common::AudioMode;
Mikhail Naganovf56ce782023-01-25 11:29:11 -080044using aidl::android::media::audio::common::AudioOutputFlags;
45using aidl::android::media::audio::common::AudioPort;
46using aidl::android::media::audio::common::AudioPortConfig;
Mikhail Naganov8bd806e2023-01-30 12:33:18 -080047using aidl::android::media::audio::common::AudioPortDeviceExt;
Mikhail Naganovf56ce782023-01-25 11:29:11 -080048using aidl::android::media::audio::common::AudioPortExt;
49using aidl::android::media::audio::common::AudioSource;
50using aidl::android::media::audio::common::Int;
Mikhail Naganovfab697c2023-01-11 19:33:13 +000051using aidl::android::media::audio::common::Float;
Mikhail Naganovf56ce782023-01-25 11:29:11 -080052using aidl::android::hardware::audio::common::RecordTrackMetadata;
53using aidl::android::hardware::audio::core::AudioPatch;
Mikhail Naganovfab697c2023-01-11 19:33:13 +000054using aidl::android::hardware::audio::core::IModule;
55using aidl::android::hardware::audio::core::ITelephony;
56using aidl::android::hardware::audio::core::StreamDescriptor;
Vlad Popa03bd5bc2023-01-17 16:16:51 +010057using aidl::android::hardware::audio::core::sounddose::ISoundDose;
Mikhail Naganov8bd806e2023-01-30 12:33:18 -080058using android::hardware::audio::common::getFrameSizeInBytes;
59using android::hardware::audio::common::isBitPositionFlagSet;
60using android::hardware::audio::common::makeBitPositionFlagMask;
Mikhail Naganov31d46652023-01-10 18:29:25 +000061
62namespace android {
63
Mikhail Naganovf56ce782023-01-25 11:29:11 -080064namespace {
65
66bool isConfigEqualToPortConfig(const AudioConfig& config, const AudioPortConfig& portConfig) {
67 return portConfig.sampleRate.value().value == config.base.sampleRate &&
68 portConfig.channelMask.value() == config.base.channelMask &&
69 portConfig.format.value() == config.base.format;
70}
71
72void setConfigFromPortConfig(AudioConfig* config, const AudioPortConfig& portConfig) {
73 config->base.sampleRate = portConfig.sampleRate.value().value;
74 config->base.channelMask = portConfig.channelMask.value();
75 config->base.format = portConfig.format.value();
76}
77
78void setPortConfigFromConfig(AudioPortConfig* portConfig, const AudioConfig& config) {
79 portConfig->sampleRate = Int{ .value = config.base.sampleRate };
80 portConfig->channelMask = config.base.channelMask;
81 portConfig->format = config.base.format;
82}
83
84} // namespace
85
Mikhail Naganov31d46652023-01-10 18:29:25 +000086status_t DeviceHalAidl::getSupportedDevices(uint32_t*) {
87 // Obsolete.
88 return INVALID_OPERATION;
Shunkai Yao51202502022-12-12 06:11:46 +000089}
90
91status_t DeviceHalAidl::initCheck() {
Mikhail Naganovf56ce782023-01-25 11:29:11 -080092 TIME_CHECK();
Mikhail Naganov31d46652023-01-10 18:29:25 +000093 if (mModule == nullptr) return NO_INIT;
Mikhail Naganovf56ce782023-01-25 11:29:11 -080094 std::vector<AudioPort> ports;
95 RETURN_STATUS_IF_ERROR(
96 statusTFromBinderStatus(mModule->getAudioPorts(&ports)));
97 ALOGW_IF(ports.empty(), "%s: module %s returned an empty list of audio ports",
98 __func__, mInstance.c_str());
99 std::transform(ports.begin(), ports.end(), std::inserter(mPorts, mPorts.end()),
100 [](const auto& p) { return std::make_pair(p.id, p); });
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800101 mDefaultInputPortId = mDefaultOutputPortId = -1;
102 const int defaultDeviceFlag = 1 << AudioPortDeviceExt::FLAG_INDEX_DEFAULT_DEVICE;
103 for (const auto& pair : mPorts) {
104 const auto& p = pair.second;
105 if (p.ext.getTag() == AudioPortExt::Tag::device &&
106 (p.ext.get<AudioPortExt::Tag::device>().flags & defaultDeviceFlag) != 0) {
107 if (p.flags.getTag() == AudioIoFlags::Tag::input) {
108 mDefaultInputPortId = p.id;
109 } else if (p.flags.getTag() == AudioIoFlags::Tag::output) {
110 mDefaultOutputPortId = p.id;
111 }
112 }
113 }
114 ALOGI("%s: module %s default port ids: input %d, output %d",
115 __func__, mInstance.c_str(), mDefaultInputPortId, mDefaultOutputPortId);
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800116 std::vector<AudioPortConfig> portConfigs;
117 RETURN_STATUS_IF_ERROR(
118 statusTFromBinderStatus(mModule->getAudioPortConfigs(&portConfigs))); // OK if empty
119 std::transform(portConfigs.begin(), portConfigs.end(),
120 std::inserter(mPortConfigs, mPortConfigs.end()),
121 [](const auto& p) { return std::make_pair(p.id, p); });
122 std::vector<AudioPatch> patches;
123 RETURN_STATUS_IF_ERROR(
124 statusTFromBinderStatus(mModule->getAudioPatches(&patches))); // OK if empty
125 std::transform(patches.begin(), patches.end(),
126 std::inserter(mPatches, mPatches.end()),
127 [](const auto& p) { return std::make_pair(p.id, p); });
Shunkai Yao51202502022-12-12 06:11:46 +0000128 return OK;
129}
130
131status_t DeviceHalAidl::setVoiceVolume(float volume) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000132 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000133 if (!mModule) return NO_INIT;
134 std::shared_ptr<ITelephony> telephony;
135 if (ndk::ScopedAStatus status = mModule->getTelephony(&telephony);
136 status.isOk() && telephony != nullptr) {
137 ITelephony::TelecomConfig inConfig{ .voiceVolume = Float{volume} }, outConfig;
138 RETURN_STATUS_IF_ERROR(
139 statusTFromBinderStatus(telephony->setTelecomConfig(inConfig, &outConfig)));
140 ALOGW_IF(outConfig.voiceVolume.has_value() && volume != outConfig.voiceVolume.value().value,
141 "%s: the resulting voice volume %f is not the same as requested %f",
142 __func__, outConfig.voiceVolume.value().value, volume);
143 }
144 return INVALID_OPERATION;
Shunkai Yao51202502022-12-12 06:11:46 +0000145}
146
147status_t DeviceHalAidl::setMasterVolume(float volume) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000148 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000149 if (!mModule) return NO_INIT;
150 return statusTFromBinderStatus(mModule->setMasterVolume(volume));
Shunkai Yao51202502022-12-12 06:11:46 +0000151}
152
153status_t DeviceHalAidl::getMasterVolume(float *volume) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000154 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000155 if (!mModule) return NO_INIT;
156 return statusTFromBinderStatus(mModule->getMasterVolume(volume));
Shunkai Yao51202502022-12-12 06:11:46 +0000157}
158
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000159status_t DeviceHalAidl::setMode(audio_mode_t mode) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000160 TIME_CHECK();
161 if (!mModule) return NO_INIT;
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000162 AudioMode audioMode = VALUE_OR_FATAL(::aidl::android::legacy2aidl_audio_mode_t_AudioMode(mode));
163 std::shared_ptr<ITelephony> telephony;
164 if (ndk::ScopedAStatus status = mModule->getTelephony(&telephony);
165 status.isOk() && telephony != nullptr) {
166 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(telephony->switchAudioMode(audioMode)));
167 }
168 return statusTFromBinderStatus(mModule->updateAudioMode(audioMode));
Shunkai Yao51202502022-12-12 06:11:46 +0000169}
170
171status_t DeviceHalAidl::setMicMute(bool state) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000172 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000173 if (!mModule) return NO_INIT;
174 return statusTFromBinderStatus(mModule->setMicMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000175}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000176
Shunkai Yao51202502022-12-12 06:11:46 +0000177status_t DeviceHalAidl::getMicMute(bool *state) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000178 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000179 if (!mModule) return NO_INIT;
180 return statusTFromBinderStatus(mModule->getMicMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000181}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000182
Shunkai Yao51202502022-12-12 06:11:46 +0000183status_t DeviceHalAidl::setMasterMute(bool state) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000184 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000185 if (!mModule) return NO_INIT;
186 return statusTFromBinderStatus(mModule->setMasterMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000187}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000188
Shunkai Yao51202502022-12-12 06:11:46 +0000189status_t DeviceHalAidl::getMasterMute(bool *state) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000190 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000191 if (!mModule) return NO_INIT;
192 return statusTFromBinderStatus(mModule->getMasterMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000193}
194
Mikhail Naganov31d46652023-01-10 18:29:25 +0000195status_t DeviceHalAidl::setParameters(const String8& kvPairs __unused) {
196 TIME_CHECK();
197 if (!mModule) return NO_INIT;
198 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000199 return OK;
200}
201
Mikhail Naganov31d46652023-01-10 18:29:25 +0000202status_t DeviceHalAidl::getParameters(const String8& keys __unused, String8 *values) {
203 TIME_CHECK();
204 values->clear();
205 if (!mModule) return NO_INIT;
206 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000207 return OK;
208}
209
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800210namespace {
211
212class Cleanup {
213 public:
214 typedef void (DeviceHalAidl::*Cleaner)(int32_t);
215
216 Cleanup(DeviceHalAidl* device, Cleaner cleaner, int32_t id) :
217 mDevice(device), mCleaner(cleaner), mId(id) {}
218 ~Cleanup() { clean(); }
219 void clean() {
220 if (mDevice != nullptr) (mDevice->*mCleaner)(mId);
221 disarm();
222 }
223 void disarm() { mDevice = nullptr; }
224
225 private:
226 DeviceHalAidl* mDevice;
227 const Cleaner mCleaner;
228 const int32_t mId;
229};
230
231} // namespace
232
233// Since the order of container elements destruction is unspecified,
234// ensure that cleanups are performed from the most recent one and upwards.
235// This is the same as if there were individual Cleanup instances on the stack,
236// however the bonus is that we can disarm all of them with just one statement.
237class DeviceHalAidl::Cleanups : public std::forward_list<Cleanup> {
238 public:
239 ~Cleanups() { for (auto& c : *this) c.clean(); }
240 void disarmAll() { for (auto& c : *this) c.disarm(); }
241};
242
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800243status_t DeviceHalAidl::getInputBufferSize(const struct audio_config* config, size_t* size) {
244 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
245 if (size == nullptr) return BAD_VALUE;
246 TIME_CHECK();
247 if (!mModule) return NO_INIT;
248 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
249 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, true /*isInput*/));
250 AudioDevice aidlDevice;
251 aidlDevice.type.type = AudioDeviceType::IN_DEFAULT;
252 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::input>(0);
253 AudioPortConfig mixPortConfig;
254 Cleanups cleanups;
255 audio_config writableConfig = *config;
256 int32_t nominalLatency;
257 RETURN_STATUS_IF_ERROR(prepareToOpenStream(0 /*handle*/, aidlDevice, aidlFlags, &writableConfig,
258 &cleanups, &aidlConfig, &mixPortConfig, &nominalLatency));
259 *size = aidlConfig.frameCount *
260 getFrameSizeInBytes(aidlConfig.base.format, aidlConfig.base.channelMask);
261 // Do not disarm cleanups to release temporary port configs.
262 return OK;
263}
264
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800265status_t DeviceHalAidl::prepareToOpenStream(
266 int32_t aidlHandle, const AudioDevice& aidlDevice, const AudioIoFlags& aidlFlags,
267 struct audio_config* config,
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800268 Cleanups* cleanups, AudioConfig* aidlConfig, AudioPortConfig* mixPortConfig,
269 int32_t* nominalLatency) {
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800270 const bool isInput = aidlFlags.getTag() == AudioIoFlags::Tag::input;
271 // Find / create AudioPortConfigs for the device port and the mix port,
272 // then find / create a patch between them, and open a stream on the mix port.
273 AudioPortConfig devicePortConfig;
274 bool created = false;
275 RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(aidlDevice, &devicePortConfig, &created));
276 if (created) {
277 cleanups->emplace_front(this, &DeviceHalAidl::resetPortConfig, devicePortConfig.id);
278 }
279 RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(*aidlConfig, aidlFlags, aidlHandle,
280 mixPortConfig, &created));
281 if (created) {
282 cleanups->emplace_front(this, &DeviceHalAidl::resetPortConfig, mixPortConfig->id);
283 }
284 setConfigFromPortConfig(aidlConfig, *mixPortConfig);
285 AudioPatch patch;
286 if (isInput) {
287 RETURN_STATUS_IF_ERROR(findOrCreatePatch(
288 {devicePortConfig.id}, {mixPortConfig->id}, &patch, &created));
289 } else {
290 RETURN_STATUS_IF_ERROR(findOrCreatePatch(
291 {mixPortConfig->id}, {devicePortConfig.id}, &patch, &created));
292 }
293 if (created) {
294 cleanups->emplace_front(this, &DeviceHalAidl::resetPatch, patch.id);
295 }
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800296 *nominalLatency = patch.latenciesMs[0];
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800297 if (aidlConfig->frameCount <= 0) {
298 aidlConfig->frameCount = patch.minimumStreamBufferSizeFrames;
299 }
300 *config = VALUE_OR_RETURN_STATUS(
301 ::aidl::android::aidl2legacy_AudioConfig_audio_config_t(*aidlConfig, isInput));
302 return OK;
303}
304
Mikhail Naganovb0c55252023-02-08 16:59:41 -0800305namespace {
306
307class StreamCallbackBase {
308 protected:
309 explicit StreamCallbackBase(const sp<CallbackBroker>& broker) : mBroker(broker) {}
310 public:
311 void* getCookie() const { return mCookie; }
312 void setCookie(void* cookie) { mCookie = cookie; }
313 sp<CallbackBroker> getBroker() const {
314 if (void* cookie = mCookie; cookie != nullptr) return mBroker.promote();
315 return nullptr;
316 }
317 private:
318 const wp<CallbackBroker> mBroker;
319 std::atomic<void*> mCookie;
320};
321
322template<class C>
323class StreamCallbackBaseHelper {
324 protected:
325 explicit StreamCallbackBaseHelper(const StreamCallbackBase& base) : mBase(base) {}
326 sp<C> getCb(const sp<CallbackBroker>& broker, void* cookie);
327 using CbRef = const sp<C>&;
328 ndk::ScopedAStatus runCb(const std::function<void(CbRef cb)>& f) {
329 if (auto cb = getCb(mBase.getBroker(), mBase.getCookie()); cb != nullptr) f(cb);
330 return ndk::ScopedAStatus::ok();
331 }
332 private:
333 const StreamCallbackBase& mBase;
334};
335
336template<>
337sp<StreamOutHalInterfaceCallback> StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>::getCb(
338 const sp<CallbackBroker>& broker, void* cookie) {
339 if (broker != nullptr) return broker->getStreamOutCallback(cookie);
340 return nullptr;
341}
342
343template<>
344sp<StreamOutHalInterfaceEventCallback>
345StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>::getCb(
346 const sp<CallbackBroker>& broker, void* cookie) {
347 if (broker != nullptr) return broker->getStreamOutEventCallback(cookie);
348 return nullptr;
349}
350
351template<>
352sp<StreamOutHalInterfaceLatencyModeCallback>
353StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>::getCb(
354 const sp<CallbackBroker>& broker, void* cookie) {
355 if (broker != nullptr) return broker->getStreamOutLatencyModeCallback(cookie);
356 return nullptr;
357}
358
359/*
360Note on the callback ownership.
361
362In the Binder ownership model, the server implementation is kept alive
363as long as there is any client (proxy object) alive. This is done by
364incrementing the refcount of the server-side object by the Binder framework.
365When it detects that the last client is gone, it decrements the refcount back.
366
367Thus, it is not needed to keep any references to StreamCallback on our
368side (after we have sent an instance to the client), because we are
369the server-side. The callback object will be kept alive as long as the HAL server
370holds a strong ref to IStreamCallback proxy.
371*/
372
373class OutputStreamCallbackAidl : public StreamCallbackBase,
374 public StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>,
375 public ::aidl::android::hardware::audio::core::BnStreamCallback {
376 public:
377 explicit OutputStreamCallbackAidl(const sp<CallbackBroker>& broker)
378 : StreamCallbackBase(broker),
379 StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>(
380 *static_cast<StreamCallbackBase*>(this)) {}
381 ndk::ScopedAStatus onTransferReady() override {
382 return runCb([](CbRef cb) { cb->onWriteReady(); });
383 }
384 ndk::ScopedAStatus onError() override {
385 return runCb([](CbRef cb) { cb->onError(); });
386 }
387 ndk::ScopedAStatus onDrainReady() override {
388 return runCb([](CbRef cb) { cb->onDrainReady(); });
389 }
390};
391
392class OutputStreamEventCallbackAidl :
393 public StreamCallbackBase,
394 public StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>,
395 public StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>,
396 public ::aidl::android::hardware::audio::core::BnStreamOutEventCallback {
397 public:
398 explicit OutputStreamEventCallbackAidl(const sp<CallbackBroker>& broker)
399 : StreamCallbackBase(broker),
400 StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>(
401 *static_cast<StreamCallbackBase*>(this)),
402 StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>(
403 *static_cast<StreamCallbackBase*>(this)) {}
404 ndk::ScopedAStatus onCodecFormatChanged(const std::vector<uint8_t>& in_audioMetadata) override {
405 std::basic_string<uint8_t> halMetadata(in_audioMetadata.begin(), in_audioMetadata.end());
406 return StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>::runCb(
407 [&halMetadata](auto cb) { cb->onCodecFormatChanged(halMetadata); });
408 }
409 ndk::ScopedAStatus onRecommendedLatencyModeChanged(
410 const std::vector<AudioLatencyMode>& in_modes) override {
411 auto halModes = VALUE_OR_FATAL(
412 ::aidl::android::convertContainer<std::vector<audio_latency_mode_t>>(
413 in_modes,
414 ::aidl::android::aidl2legacy_AudioLatencyMode_audio_latency_mode_t));
415 return StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>::runCb(
416 [&halModes](auto cb) { cb->onRecommendedLatencyModeChanged(halModes); });
417 }
418};
419
420} // namespace
421
Mikhail Naganov31d46652023-01-10 18:29:25 +0000422status_t DeviceHalAidl::openOutputStream(
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800423 audio_io_handle_t handle, audio_devices_t devices,
424 audio_output_flags_t flags, struct audio_config* config,
425 const char* address,
Mikhail Naganov31d46652023-01-10 18:29:25 +0000426 sp<StreamOutHalInterface>* outStream) {
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800427 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000428 if (!outStream || !config) {
429 return BAD_VALUE;
430 }
431 TIME_CHECK();
432 if (!mModule) return NO_INIT;
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800433 int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
434 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(handle));
435 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
436 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, false /*isInput*/));
437 AudioDevice aidlDevice = VALUE_OR_RETURN_STATUS(
438 ::aidl::android::legacy2aidl_audio_device_AudioDevice(devices, address));
439 int32_t aidlOutputFlags = VALUE_OR_RETURN_STATUS(
440 ::aidl::android::legacy2aidl_audio_output_flags_t_int32_t_mask(flags));
441 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::output>(aidlOutputFlags);
442 AudioPortConfig mixPortConfig;
443 Cleanups cleanups;
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800444 int32_t nominalLatency;
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800445 RETURN_STATUS_IF_ERROR(prepareToOpenStream(aidlHandle, aidlDevice, aidlFlags, config,
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800446 &cleanups, &aidlConfig, &mixPortConfig, &nominalLatency));
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800447 ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamArguments args;
448 args.portConfigId = mixPortConfig.id;
Mikhail Naganovb0c55252023-02-08 16:59:41 -0800449 const bool isOffload = isBitPositionFlagSet(
450 aidlOutputFlags, AudioOutputFlags::COMPRESS_OFFLOAD);
451 std::shared_ptr<OutputStreamCallbackAidl> streamCb;
452 if (isOffload) {
453 streamCb = ndk::SharedRefBase::make<OutputStreamCallbackAidl>(this);
454 }
455 auto eventCb = ndk::SharedRefBase::make<OutputStreamEventCallbackAidl>(this);
456 if (isOffload) {
457 args.offloadInfo = aidlConfig.offloadInfo;
458 args.callback = streamCb;
459 }
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800460 args.bufferSizeFrames = aidlConfig.frameCount;
Mikhail Naganovb0c55252023-02-08 16:59:41 -0800461 args.eventCallback = eventCb;
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800462 ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamReturn ret;
463 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openOutputStream(args, &ret)));
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800464 StreamContextAidl context(ret.desc);
465 if (!context.isValid()) {
466 ALOGE("%s: Failed to created a valid stream context from the descriptor: %s",
467 __func__, ret.desc.toString().c_str());
468 return NO_INIT;
469 }
470 *outStream = sp<StreamOutHalAidl>::make(*config, std::move(context), nominalLatency,
Mikhail Naganovb0c55252023-02-08 16:59:41 -0800471 std::move(ret.stream), this /*callbackBroker*/);
472 void* cbCookie = (*outStream).get();
473 {
474 std::lock_guard l(mLock);
475 mCallbacks.emplace(cbCookie, Callbacks{});
476 }
477 if (streamCb) streamCb->setCookie(cbCookie);
478 eventCb->setCookie(cbCookie);
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800479 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000480 return OK;
481}
482
Mikhail Naganov31d46652023-01-10 18:29:25 +0000483status_t DeviceHalAidl::openInputStream(
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800484 audio_io_handle_t handle, audio_devices_t devices,
485 struct audio_config* config, audio_input_flags_t flags,
486 const char* address, audio_source_t source,
487 audio_devices_t outputDevice, const char* outputDeviceAddress,
Mikhail Naganov31d46652023-01-10 18:29:25 +0000488 sp<StreamInHalInterface>* inStream) {
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800489 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000490 if (!inStream || !config) {
491 return BAD_VALUE;
492 }
493 TIME_CHECK();
494 if (!mModule) return NO_INIT;
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800495 int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
496 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(handle));
497 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
498 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, true /*isInput*/));
499 AudioDevice aidlDevice = VALUE_OR_RETURN_STATUS(
500 ::aidl::android::legacy2aidl_audio_device_AudioDevice(devices, address));
501 int32_t aidlInputFlags = VALUE_OR_RETURN_STATUS(
502 ::aidl::android::legacy2aidl_audio_input_flags_t_int32_t_mask(flags));
503 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::input>(aidlInputFlags);
504 AudioSource aidlSource = VALUE_OR_RETURN_STATUS(
505 ::aidl::android::legacy2aidl_audio_source_t_AudioSource(source));
506 AudioPortConfig mixPortConfig;
507 Cleanups cleanups;
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800508 int32_t nominalLatency;
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800509 RETURN_STATUS_IF_ERROR(prepareToOpenStream(aidlHandle, aidlDevice, aidlFlags, config,
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800510 &cleanups, &aidlConfig, &mixPortConfig, &nominalLatency));
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800511 ::aidl::android::hardware::audio::core::IModule::OpenInputStreamArguments args;
512 args.portConfigId = mixPortConfig.id;
513 RecordTrackMetadata aidlTrackMetadata{
514 .source = aidlSource, .gain = 1, .channelMask = aidlConfig.base.channelMask };
515 if (outputDevice != AUDIO_DEVICE_NONE) {
516 aidlTrackMetadata.destinationDevice = VALUE_OR_RETURN_STATUS(
517 ::aidl::android::legacy2aidl_audio_device_AudioDevice(
518 outputDevice, outputDeviceAddress));
519 }
520 args.sinkMetadata.tracks.push_back(std::move(aidlTrackMetadata));
521 args.bufferSizeFrames = aidlConfig.frameCount;
522 ::aidl::android::hardware::audio::core::IModule::OpenInputStreamReturn ret;
523 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openInputStream(args, &ret)));
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800524 StreamContextAidl context(ret.desc);
525 if (!context.isValid()) {
526 ALOGE("%s: Failed to created a valid stream context from the descriptor: %s",
527 __func__, ret.desc.toString().c_str());
528 return NO_INIT;
529 }
530 *inStream = sp<StreamInHalAidl>::make(*config, std::move(context), nominalLatency,
531 std::move(ret.stream));
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800532 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000533 return OK;
534}
535
536status_t DeviceHalAidl::supportsAudioPatches(bool* supportsPatches) {
537 *supportsPatches = true;
538 return OK;
539}
540
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800541status_t DeviceHalAidl::createAudioPatch(unsigned int num_sources,
542 const struct audio_port_config* sources,
543 unsigned int num_sinks,
544 const struct audio_port_config* sinks,
545 audio_patch_handle_t* patch) {
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800546 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000547 TIME_CHECK();
548 if (!mModule) return NO_INIT;
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800549 if (num_sinks > AUDIO_PATCH_PORTS_MAX || num_sources > AUDIO_PATCH_PORTS_MAX ||
550 sources == nullptr || sinks == nullptr || patch == nullptr) {
551 return BAD_VALUE;
552 }
553 // Note that the patch handle (*patch) is provided by the framework.
554 // In tests it's possible that its value is AUDIO_PATCH_HANDLE_NONE.
555
556 // Upon conversion, mix port configs contain audio configuration, while
557 // device port configs contain device address. This data is used to find
558 // or create HAL configs.
559 std::vector<AudioPortConfig> aidlSources, aidlSinks;
560 for (unsigned int i = 0; i < num_sources; ++i) {
561 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
562 sources[i].role, sources[i].type)) ==
563 ::aidl::android::AudioPortDirection::INPUT;
564 aidlSources.push_back(VALUE_OR_RETURN_STATUS(
565 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
566 sources[i], isInput, 0)));
567 }
568 for (unsigned int i = 0; i < num_sinks; ++i) {
569 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
570 sinks[i].role, sinks[i].type)) ==
571 ::aidl::android::AudioPortDirection::INPUT;
572 aidlSinks.push_back(VALUE_OR_RETURN_STATUS(
573 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
574 sinks[i], isInput, 0)));
575 }
576 Cleanups cleanups;
577 auto existingPatchIt = mPatches.end();
578 auto fwkHandlesIt = *patch != AUDIO_PATCH_HANDLE_NONE ?
579 mFwkHandles.find(*patch) : mFwkHandles.end();
580 AudioPatch aidlPatch;
581 if (fwkHandlesIt != mFwkHandles.end()) {
582 existingPatchIt = mPatches.find(fwkHandlesIt->second);
583 if (existingPatchIt != mPatches.end()) {
584 aidlPatch = existingPatchIt->second;
585 aidlPatch.sourcePortConfigIds.clear();
586 aidlPatch.sinkPortConfigIds.clear();
587 }
588 }
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800589 ALOGD("%s: sources: %s, sinks: %s",
590 __func__, ::android::internal::ToString(aidlSources).c_str(),
591 ::android::internal::ToString(aidlSinks).c_str());
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800592 auto fillPortConfigs = [&](
593 const std::vector<AudioPortConfig>& configs, std::vector<int32_t>* ids) -> status_t {
594 for (const auto& s : configs) {
595 AudioPortConfig portConfig;
596 bool created = false;
597 RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(s, &portConfig, &created));
598 if (created) {
599 cleanups.emplace_front(this, &DeviceHalAidl::resetPortConfig, portConfig.id);
600 }
601 ids->push_back(portConfig.id);
602 }
603 return OK;
604 };
605 RETURN_STATUS_IF_ERROR(fillPortConfigs(aidlSources, &aidlPatch.sourcePortConfigIds));
606 RETURN_STATUS_IF_ERROR(fillPortConfigs(aidlSinks, &aidlPatch.sinkPortConfigIds));
607 if (existingPatchIt != mPatches.end()) {
608 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
609 mModule->setAudioPatch(aidlPatch, &aidlPatch)));
610 existingPatchIt->second = aidlPatch;
611 } else {
612 bool created = false;
613 RETURN_STATUS_IF_ERROR(findOrCreatePatch(aidlPatch, &aidlPatch, &created));
614 // Since no cleanup of the patch is needed, 'created' is ignored.
615 if (fwkHandlesIt != mFwkHandles.end()) {
616 fwkHandlesIt->second = aidlPatch.id;
617 // Patch handle (*patch) stays the same.
618 } else {
619 if (*patch == AUDIO_PATCH_HANDLE_NONE) {
620 // This isn't good as the module can't provide a handle which is really unique.
621 // However, this situation should only happen in tests.
622 *patch = aidlPatch.id;
623 LOG_ALWAYS_FATAL_IF(mFwkHandles.count(*patch) > 0,
624 "%s: patch id %d clashes with another framework patch handle",
625 __func__, *patch);
626 }
627 mFwkHandles.emplace(*patch, aidlPatch.id);
628 }
629 }
630 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000631 return OK;
632}
633
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800634status_t DeviceHalAidl::releaseAudioPatch(audio_patch_handle_t patch) {
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800635 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000636 TIME_CHECK();
637 if (!mModule) return NO_INIT;
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800638 auto idMapIt = mFwkHandles.find(patch);
639 if (idMapIt == mFwkHandles.end()) {
640 return BAD_VALUE;
641 }
642 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->resetAudioPatch(idMapIt->second)));
643 mFwkHandles.erase(idMapIt);
Shunkai Yao51202502022-12-12 06:11:46 +0000644 return OK;
645}
646
Mikhail Naganov31d46652023-01-10 18:29:25 +0000647status_t DeviceHalAidl::getAudioPort(struct audio_port* port __unused) {
648 TIME_CHECK();
649 ALOGE("%s not implemented yet", __func__);
650 return INVALID_OPERATION;
651}
652
653status_t DeviceHalAidl::getAudioPort(struct audio_port_v7 *port __unused) {
654 TIME_CHECK();
655 ALOGE("%s not implemented yet", __func__);
656 return INVALID_OPERATION;
657}
658
659status_t DeviceHalAidl::setAudioPortConfig(const struct audio_port_config* config __unused) {
660 TIME_CHECK();
661 if (!mModule) return NO_INIT;
662 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000663 return OK;
664}
665
666status_t DeviceHalAidl::getMicrophones(
Mikhail Naganov31d46652023-01-10 18:29:25 +0000667 std::vector<audio_microphone_characteristic_t>* microphones __unused) {
668 TIME_CHECK();
669 if (!mModule) return NO_INIT;
670 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000671 return OK;
672}
673
Mikhail Naganov31d46652023-01-10 18:29:25 +0000674status_t DeviceHalAidl::addDeviceEffect(audio_port_handle_t device __unused,
675 sp<EffectHalInterface> effect) {
Shunkai Yao51202502022-12-12 06:11:46 +0000676 if (!effect) {
677 return BAD_VALUE;
678 }
Mikhail Naganov31d46652023-01-10 18:29:25 +0000679 TIME_CHECK();
680 if (!mModule) return NO_INIT;
681 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000682 return OK;
683}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000684status_t DeviceHalAidl::removeDeviceEffect(audio_port_handle_t device __unused,
Shunkai Yao51202502022-12-12 06:11:46 +0000685 sp<EffectHalInterface> effect) {
686 if (!effect) {
687 return BAD_VALUE;
688 }
Mikhail Naganov31d46652023-01-10 18:29:25 +0000689 TIME_CHECK();
690 if (!mModule) return NO_INIT;
691 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000692 return OK;
693}
694
695status_t DeviceHalAidl::getMmapPolicyInfos(
696 media::audio::common::AudioMMapPolicyType policyType __unused,
697 std::vector<media::audio::common::AudioMMapPolicyInfo>* policyInfos __unused) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000698 TIME_CHECK();
Shunkai Yao51202502022-12-12 06:11:46 +0000699 ALOGE("%s not implemented yet", __func__);
700 return OK;
701}
702
703int32_t DeviceHalAidl::getAAudioMixerBurstCount() {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000704 TIME_CHECK();
Shunkai Yao51202502022-12-12 06:11:46 +0000705 ALOGE("%s not implemented yet", __func__);
706 return OK;
707}
708
709int32_t DeviceHalAidl::getAAudioHardwareBurstMinUsec() {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000710 TIME_CHECK();
Shunkai Yao51202502022-12-12 06:11:46 +0000711 ALOGE("%s not implemented yet", __func__);
712 return OK;
713}
714
715error::Result<audio_hw_sync_t> DeviceHalAidl::getHwAvSync() {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000716 TIME_CHECK();
Shunkai Yao51202502022-12-12 06:11:46 +0000717 ALOGE("%s not implemented yet", __func__);
718 return base::unexpected(INVALID_OPERATION);
719}
720
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000721status_t DeviceHalAidl::dump(int fd, const Vector<String16>& args) {
722 TIME_CHECK();
723 if (!mModule) return NO_INIT;
724 return mModule->dump(fd, Args(args).args(), args.size());
Shunkai Yao51202502022-12-12 06:11:46 +0000725};
726
Mikhail Naganov31d46652023-01-10 18:29:25 +0000727int32_t DeviceHalAidl::supportsBluetoothVariableLatency(bool* supports __unused) {
728 TIME_CHECK();
Shunkai Yao51202502022-12-12 06:11:46 +0000729 ALOGE("%s not implemented yet", __func__);
730 return INVALID_OPERATION;
731}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000732
Vlad Popa03bd5bc2023-01-17 16:16:51 +0100733status_t DeviceHalAidl::getSoundDoseInterface(const std::string& module,
734 ::ndk::SpAIBinder* soundDoseBinder) {
735 TIME_CHECK();
736 if (!mModule) return NO_INIT;
737 if (mSoundDose == nullptr) {
738 ndk::ScopedAStatus status = mModule->getSoundDose(&mSoundDose);
739 if (!status.isOk()) {
740 ALOGE("%s failed to return the sound dose interface for module %s: %s",
741 __func__,
742 module.c_str(),
743 status.getDescription().c_str());
744 return BAD_VALUE;
745 }
746 }
747 *soundDoseBinder = mSoundDose->asBinder();
748 ALOGI("%s using audio AIDL HAL sound dose interface", __func__);
749
750 return OK;
751}
752
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800753bool DeviceHalAidl::audioDeviceMatches(const AudioDevice& device, const AudioPort& p) {
754 if (p.ext.getTag() != AudioPortExt::Tag::device) return false;
755 return p.ext.get<AudioPortExt::Tag::device>().device == device;
756}
757
758bool DeviceHalAidl::audioDeviceMatches(const AudioDevice& device, const AudioPortConfig& p) {
759 if (p.ext.getTag() != AudioPortExt::Tag::device) return false;
760 if (device.type.type == AudioDeviceType::IN_DEFAULT) {
761 return p.portId == mDefaultInputPortId;
762 } else if (device.type.type == AudioDeviceType::OUT_DEFAULT) {
763 return p.portId == mDefaultOutputPortId;
764 }
765 return p.ext.get<AudioPortExt::Tag::device>().device == device;
766}
767
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800768status_t DeviceHalAidl::createPortConfig(const AudioPortConfig& requestedPortConfig,
769 AudioPortConfig* appliedPortConfig) {
770 TIME_CHECK();
771 bool applied = false;
772 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPortConfig(
773 requestedPortConfig, appliedPortConfig, &applied)));
774 if (!applied) {
775 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPortConfig(
776 *appliedPortConfig, appliedPortConfig, &applied)));
777 if (!applied) {
778 ALOGE("%s: module %s did not apply suggested config %s",
779 __func__, mInstance.c_str(), appliedPortConfig->toString().c_str());
780 return NO_INIT;
781 }
782 }
783 mPortConfigs.emplace(appliedPortConfig->id, *appliedPortConfig);
784 return OK;
785}
786
787status_t DeviceHalAidl::findOrCreatePatch(
788 const AudioPatch& requestedPatch, AudioPatch* patch, bool* created) {
789 std::set<int32_t> sourcePortConfigIds(requestedPatch.sourcePortConfigIds.begin(),
790 requestedPatch.sourcePortConfigIds.end());
791 std::set<int32_t> sinkPortConfigIds(requestedPatch.sinkPortConfigIds.begin(),
792 requestedPatch.sinkPortConfigIds.end());
793 return findOrCreatePatch(sourcePortConfigIds, sinkPortConfigIds, patch, created);
794}
795
796status_t DeviceHalAidl::findOrCreatePatch(
797 const std::set<int32_t>& sourcePortConfigIds, const std::set<int32_t>& sinkPortConfigIds,
798 AudioPatch* patch, bool* created) {
799 auto patchIt = findPatch(sourcePortConfigIds, sinkPortConfigIds);
800 if (patchIt == mPatches.end()) {
801 TIME_CHECK();
802 AudioPatch requestedPatch, appliedPatch;
803 requestedPatch.sourcePortConfigIds.insert(requestedPatch.sourcePortConfigIds.end(),
804 sourcePortConfigIds.begin(), sourcePortConfigIds.end());
805 requestedPatch.sinkPortConfigIds.insert(requestedPatch.sinkPortConfigIds.end(),
806 sinkPortConfigIds.begin(), sinkPortConfigIds.end());
807 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPatch(
808 requestedPatch, &appliedPatch)));
809 patchIt = mPatches.insert(mPatches.end(), std::make_pair(appliedPatch.id, appliedPatch));
810 *created = true;
811 } else {
812 *created = false;
813 }
814 *patch = patchIt->second;
815 return OK;
816}
817
818status_t DeviceHalAidl::findOrCreatePortConfig(const AudioDevice& device,
819 AudioPortConfig* portConfig, bool* created) {
820 auto portConfigIt = findPortConfig(device);
821 if (portConfigIt == mPortConfigs.end()) {
822 auto portsIt = findPort(device);
823 if (portsIt == mPorts.end()) {
824 ALOGE("%s: device port for device %s is not found in the module %s",
825 __func__, device.toString().c_str(), mInstance.c_str());
826 return BAD_VALUE;
827 }
828 AudioPortConfig requestedPortConfig;
829 requestedPortConfig.portId = portsIt->first;
830 AudioPortConfig appliedPortConfig;
831 RETURN_STATUS_IF_ERROR(createPortConfig(requestedPortConfig, &appliedPortConfig));
832 portConfigIt = mPortConfigs.insert(
833 mPortConfigs.end(), std::make_pair(appliedPortConfig.id, appliedPortConfig));
834 *created = true;
835 } else {
836 *created = false;
837 }
838 *portConfig = portConfigIt->second;
839 return OK;
840}
841
842status_t DeviceHalAidl::findOrCreatePortConfig(
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800843 const AudioConfig& config, const std::optional<AudioIoFlags>& flags, int32_t ioHandle,
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800844 AudioPortConfig* portConfig, bool* created) {
845 auto portConfigIt = findPortConfig(config, flags, ioHandle);
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800846 if (portConfigIt == mPortConfigs.end() && flags.has_value()) {
847 auto portsIt = findPort(config, flags.value());
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800848 if (portsIt == mPorts.end()) {
849 ALOGE("%s: mix port for config %s, flags %s is not found in the module %s",
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800850 __func__, config.toString().c_str(), flags.value().toString().c_str(),
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800851 mInstance.c_str());
852 return BAD_VALUE;
853 }
854 AudioPortConfig requestedPortConfig;
855 requestedPortConfig.portId = portsIt->first;
856 setPortConfigFromConfig(&requestedPortConfig, config);
857 AudioPortConfig appliedPortConfig;
858 RETURN_STATUS_IF_ERROR(createPortConfig(requestedPortConfig, &appliedPortConfig));
859 appliedPortConfig.ext.get<AudioPortExt::Tag::mix>().handle = ioHandle;
860 portConfigIt = mPortConfigs.insert(
861 mPortConfigs.end(), std::make_pair(appliedPortConfig.id, appliedPortConfig));
862 *created = true;
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800863 } else if (!flags.has_value()) {
864 ALOGW("%s: mix port config for %s, handle %d not found in the module %s, "
865 "and was not created as flags are not specified",
866 __func__, config.toString().c_str(), ioHandle, mInstance.c_str());
867 return BAD_VALUE;
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800868 } else {
869 *created = false;
870 }
871 *portConfig = portConfigIt->second;
872 return OK;
873}
874
875status_t DeviceHalAidl::findOrCreatePortConfig(
876 const AudioPortConfig& requestedPortConfig, AudioPortConfig* portConfig, bool* created) {
877 using Tag = AudioPortExt::Tag;
878 if (requestedPortConfig.ext.getTag() == Tag::mix) {
879 if (const auto& p = requestedPortConfig;
880 !p.sampleRate.has_value() || !p.channelMask.has_value() ||
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800881 !p.format.has_value()) {
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800882 ALOGW("%s: provided mix port config is not fully specified: %s",
883 __func__, p.toString().c_str());
884 return BAD_VALUE;
885 }
886 AudioConfig config;
887 setConfigFromPortConfig(&config, requestedPortConfig);
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800888 return findOrCreatePortConfig(config, requestedPortConfig.flags,
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800889 requestedPortConfig.ext.get<Tag::mix>().handle, portConfig, created);
890 } else if (requestedPortConfig.ext.getTag() == Tag::device) {
891 return findOrCreatePortConfig(
892 requestedPortConfig.ext.get<Tag::device>().device, portConfig, created);
893 }
894 ALOGW("%s: unsupported audio port config: %s",
895 __func__, requestedPortConfig.toString().c_str());
896 return BAD_VALUE;
897}
898
899DeviceHalAidl::Patches::iterator DeviceHalAidl::findPatch(
900 const std::set<int32_t>& sourcePortConfigIds, const std::set<int32_t>& sinkPortConfigIds) {
901 return std::find_if(mPatches.begin(), mPatches.end(),
902 [&](const auto& pair) {
903 const auto& p = pair.second;
904 std::set<int32_t> patchSrcs(
905 p.sourcePortConfigIds.begin(), p.sourcePortConfigIds.end());
906 std::set<int32_t> patchSinks(
907 p.sinkPortConfigIds.begin(), p.sinkPortConfigIds.end());
908 return sourcePortConfigIds == patchSrcs && sinkPortConfigIds == patchSinks; });
909}
910
911DeviceHalAidl::Ports::iterator DeviceHalAidl::findPort(const AudioDevice& device) {
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800912 if (device.type.type == AudioDeviceType::IN_DEFAULT) {
913 return mPorts.find(mDefaultInputPortId);
914 } else if (device.type.type == AudioDeviceType::OUT_DEFAULT) {
915 return mPorts.find(mDefaultOutputPortId);
916 }
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800917 return std::find_if(mPorts.begin(), mPorts.end(),
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800918 [&](const auto& pair) { return audioDeviceMatches(device, pair.second); });
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800919}
920
921DeviceHalAidl::Ports::iterator DeviceHalAidl::findPort(
922 const AudioConfig& config, const AudioIoFlags& flags) {
923 using Tag = AudioPortExt::Tag;
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800924 AudioIoFlags matchFlags = flags;
925 auto matcher = [&](const auto& pair) {
926 const auto& p = pair.second;
927 return p.ext.getTag() == Tag::mix &&
928 p.flags == matchFlags &&
929 std::find_if(p.profiles.begin(), p.profiles.end(),
930 [&](const auto& prof) {
931 return prof.format == config.base.format &&
932 std::find(prof.channelMasks.begin(), prof.channelMasks.end(),
933 config.base.channelMask) != prof.channelMasks.end() &&
934 std::find(prof.sampleRates.begin(), prof.sampleRates.end(),
935 config.base.sampleRate) != prof.sampleRates.end();
936 }) != p.profiles.end(); };
937 auto it = std::find_if(mPorts.begin(), mPorts.end(), matcher);
938 if (it == mPorts.end() && flags.getTag() == AudioIoFlags::Tag::input &&
939 isBitPositionFlagSet(flags.get<AudioIoFlags::Tag::input>(), AudioInputFlags::FAST)) {
940 // "Fast" input is not a mandatory flag, try without it.
941 matchFlags.set<AudioIoFlags::Tag::input>(flags.get<AudioIoFlags::Tag::input>() &
942 ~makeBitPositionFlagMask(AudioInputFlags::FAST));
943 it = std::find_if(mPorts.begin(), mPorts.end(), matcher);
944 }
945 return it;
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800946}
947
948DeviceHalAidl::PortConfigs::iterator DeviceHalAidl::findPortConfig(const AudioDevice& device) {
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800949 return std::find_if(mPortConfigs.begin(), mPortConfigs.end(),
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800950 [&](const auto& pair) { return audioDeviceMatches(device, pair.second); });
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800951}
952
953DeviceHalAidl::PortConfigs::iterator DeviceHalAidl::findPortConfig(
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800954 const AudioConfig& config, const std::optional<AudioIoFlags>& flags, int32_t ioHandle) {
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800955 using Tag = AudioPortExt::Tag;
956 return std::find_if(mPortConfigs.begin(), mPortConfigs.end(),
957 [&](const auto& pair) {
958 const auto& p = pair.second;
959 LOG_ALWAYS_FATAL_IF(p.ext.getTag() == Tag::mix &&
960 !p.sampleRate.has_value() || !p.channelMask.has_value() ||
961 !p.format.has_value() || !p.flags.has_value(),
962 "%s: stored mix port config is not fully specified: %s",
963 __func__, p.toString().c_str());
964 return p.ext.getTag() == Tag::mix &&
965 isConfigEqualToPortConfig(config, p) &&
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800966 (!flags.has_value() || p.flags.value() == flags.value()) &&
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800967 p.ext.template get<Tag::mix>().handle == ioHandle; });
968}
969/*
970DeviceHalAidl::PortConfigs::iterator DeviceHalAidl::findPortConfig(
971 const AudioPortConfig& portConfig) {
972 using Tag = AudioPortExt::Tag;
973 if (portConfig.ext.getTag() == Tag::mix) {
974 return std::find_if(mPortConfigs.begin(), mPortConfigs.end(),
975 [&](const auto& pair) {
976 const auto& p = pair.second;
977 LOG_ALWAYS_FATAL_IF(p.ext.getTag() == Tag::mix &&
978 !p.sampleRate.has_value() || !p.channelMask.has_value() ||
979 !p.format.has_value() || !p.flags.has_value(),
980 "%s: stored mix port config is not fully specified: %s",
981 __func__, p.toString().c_str());
982 return p.ext.getTag() == Tag::mix &&
983 (!portConfig.sampleRate.has_value() ||
984 p.sampleRate == portConfig.sampleRate) &&
985 (!portConfig.channelMask.has_value() ||
986 p.channelMask == portConfig.channelMask) &&
987 (!portConfig.format.has_value() || p.format == portConfig.format) &&
988 (!portConfig.flags.has_value() || p.flags == portConfig.flags) &&
989 p.ext.template get<Tag::mix>().handle ==
990 portConfig.ext.template get<Tag::mix>().handle; });
991 } else if (portConfig.ext.getTag() == Tag::device) {
992 return findPortConfig(portConfig.ext.get<Tag::device>().device);
993 }
994 return mPortConfigs.end();
995}
996*/
997void DeviceHalAidl::resetPatch(int32_t patchId) {
998 if (auto it = mPatches.find(patchId); it != mPatches.end()) {
999 mPatches.erase(it);
1000 TIME_CHECK();
1001 if (ndk::ScopedAStatus status = mModule->resetAudioPatch(patchId); !status.isOk()) {
1002 ALOGE("%s: error while resetting patch %d: %s",
1003 __func__, patchId, status.getDescription().c_str());
1004 }
1005 return;
1006 }
1007 ALOGE("%s: patch id %d not found", __func__, patchId);
1008}
1009
1010void DeviceHalAidl::resetPortConfig(int32_t portConfigId) {
1011 if (auto it = mPortConfigs.find(portConfigId); it != mPortConfigs.end()) {
1012 mPortConfigs.erase(it);
1013 TIME_CHECK();
1014 if (ndk::ScopedAStatus status = mModule->resetAudioPortConfig(portConfigId);
1015 !status.isOk()) {
1016 ALOGE("%s: error while resetting port config %d: %s",
1017 __func__, portConfigId, status.getDescription().c_str());
1018 }
1019 return;
1020 }
1021 ALOGE("%s: port config id %d not found", __func__, portConfigId);
1022}
1023
Mikhail Naganovb0c55252023-02-08 16:59:41 -08001024void DeviceHalAidl::clearCallbacks(void* cookie) {
1025 std::lock_guard l(mLock);
1026 mCallbacks.erase(cookie);
1027}
1028
1029sp<StreamOutHalInterfaceCallback> DeviceHalAidl::getStreamOutCallback(void* cookie) {
1030 return getCallbackImpl(cookie, &Callbacks::out);
1031}
1032
1033void DeviceHalAidl::setStreamOutCallback(
1034 void* cookie, const sp<StreamOutHalInterfaceCallback>& cb) {
1035 setCallbackImpl(cookie, &Callbacks::out, cb);
1036}
1037
1038sp<StreamOutHalInterfaceEventCallback> DeviceHalAidl::getStreamOutEventCallback(
1039 void* cookie) {
1040 return getCallbackImpl(cookie, &Callbacks::event);
1041}
1042
1043void DeviceHalAidl::setStreamOutEventCallback(
1044 void* cookie, const sp<StreamOutHalInterfaceEventCallback>& cb) {
1045 setCallbackImpl(cookie, &Callbacks::event, cb);
1046}
1047
1048sp<StreamOutHalInterfaceLatencyModeCallback> DeviceHalAidl::getStreamOutLatencyModeCallback(
1049 void* cookie) {
1050 return getCallbackImpl(cookie, &Callbacks::latency);
1051}
1052
1053void DeviceHalAidl::setStreamOutLatencyModeCallback(
1054 void* cookie, const sp<StreamOutHalInterfaceLatencyModeCallback>& cb) {
1055 setCallbackImpl(cookie, &Callbacks::latency, cb);
1056}
1057
1058template<class C>
1059sp<C> DeviceHalAidl::getCallbackImpl(void* cookie, wp<C> DeviceHalAidl::Callbacks::* field) {
1060 std::lock_guard l(mLock);
1061 if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
1062 return ((it->second).*field).promote();
1063 }
1064 return nullptr;
1065}
1066template<class C>
1067void DeviceHalAidl::setCallbackImpl(
1068 void* cookie, wp<C> DeviceHalAidl::Callbacks::* field, const sp<C>& cb) {
1069 std::lock_guard l(mLock);
1070 if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
1071 (it->second).*field = cb;
1072 }
1073}
1074
Mikhail Naganov31d46652023-01-10 18:29:25 +00001075} // namespace android