blob: 0d6bb3f1653e5caaa5c8fa7d1f4d72ac278cfe82 [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 Naganov1a44bc62023-02-16 17:35:06 -080048using aidl::android::media::audio::common::AudioPortMixExt;
Mikhail Naganovd8d01f72023-03-09 16:24:40 -080049using aidl::android::media::audio::common::AudioPortMixExtUseCase;
Mikhail Naganovf56ce782023-01-25 11:29:11 -080050using aidl::android::media::audio::common::AudioPortExt;
51using aidl::android::media::audio::common::AudioSource;
52using aidl::android::media::audio::common::Int;
Mikhail Naganovfab697c2023-01-11 19:33:13 +000053using aidl::android::media::audio::common::Float;
Mikhail Naganov6352e822023-03-09 18:22:36 -080054using aidl::android::hardware::audio::common::getFrameSizeInBytes;
55using aidl::android::hardware::audio::common::isBitPositionFlagSet;
56using aidl::android::hardware::audio::common::makeBitPositionFlagMask;
Mikhail Naganovcad0afe2023-03-10 14:25:57 -080057using aidl::android::media::audio::common::MicrophoneDynamicInfo;
58using aidl::android::media::audio::common::MicrophoneInfo;
Mikhail Naganovf56ce782023-01-25 11:29:11 -080059using aidl::android::hardware::audio::common::RecordTrackMetadata;
60using aidl::android::hardware::audio::core::AudioPatch;
Mikhail Naganovfab697c2023-01-11 19:33:13 +000061using aidl::android::hardware::audio::core::IModule;
62using aidl::android::hardware::audio::core::ITelephony;
63using aidl::android::hardware::audio::core::StreamDescriptor;
Mikhail Naganov31d46652023-01-10 18:29:25 +000064
65namespace android {
66
Mikhail Naganovf56ce782023-01-25 11:29:11 -080067namespace {
68
69bool isConfigEqualToPortConfig(const AudioConfig& config, const AudioPortConfig& portConfig) {
70 return portConfig.sampleRate.value().value == config.base.sampleRate &&
71 portConfig.channelMask.value() == config.base.channelMask &&
72 portConfig.format.value() == config.base.format;
73}
74
75void setConfigFromPortConfig(AudioConfig* config, const AudioPortConfig& portConfig) {
76 config->base.sampleRate = portConfig.sampleRate.value().value;
77 config->base.channelMask = portConfig.channelMask.value();
78 config->base.format = portConfig.format.value();
79}
80
81void setPortConfigFromConfig(AudioPortConfig* portConfig, const AudioConfig& config) {
82 portConfig->sampleRate = Int{ .value = config.base.sampleRate };
83 portConfig->channelMask = config.base.channelMask;
84 portConfig->format = config.base.format;
85}
86
87} // namespace
88
Mikhail Naganov31d46652023-01-10 18:29:25 +000089status_t DeviceHalAidl::getSupportedDevices(uint32_t*) {
90 // Obsolete.
91 return INVALID_OPERATION;
Shunkai Yao51202502022-12-12 06:11:46 +000092}
93
94status_t DeviceHalAidl::initCheck() {
Mikhail Naganovf56ce782023-01-25 11:29:11 -080095 TIME_CHECK();
Mikhail Naganov31d46652023-01-10 18:29:25 +000096 if (mModule == nullptr) return NO_INIT;
Mikhail Naganovf56ce782023-01-25 11:29:11 -080097 std::vector<AudioPort> ports;
98 RETURN_STATUS_IF_ERROR(
99 statusTFromBinderStatus(mModule->getAudioPorts(&ports)));
100 ALOGW_IF(ports.empty(), "%s: module %s returned an empty list of audio ports",
101 __func__, mInstance.c_str());
102 std::transform(ports.begin(), ports.end(), std::inserter(mPorts, mPorts.end()),
103 [](const auto& p) { return std::make_pair(p.id, p); });
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800104 mDefaultInputPortId = mDefaultOutputPortId = -1;
105 const int defaultDeviceFlag = 1 << AudioPortDeviceExt::FLAG_INDEX_DEFAULT_DEVICE;
106 for (const auto& pair : mPorts) {
107 const auto& p = pair.second;
108 if (p.ext.getTag() == AudioPortExt::Tag::device &&
109 (p.ext.get<AudioPortExt::Tag::device>().flags & defaultDeviceFlag) != 0) {
110 if (p.flags.getTag() == AudioIoFlags::Tag::input) {
111 mDefaultInputPortId = p.id;
112 } else if (p.flags.getTag() == AudioIoFlags::Tag::output) {
113 mDefaultOutputPortId = p.id;
114 }
115 }
116 }
117 ALOGI("%s: module %s default port ids: input %d, output %d",
118 __func__, mInstance.c_str(), mDefaultInputPortId, mDefaultOutputPortId);
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800119 std::vector<AudioPortConfig> portConfigs;
120 RETURN_STATUS_IF_ERROR(
121 statusTFromBinderStatus(mModule->getAudioPortConfigs(&portConfigs))); // OK if empty
122 std::transform(portConfigs.begin(), portConfigs.end(),
123 std::inserter(mPortConfigs, mPortConfigs.end()),
124 [](const auto& p) { return std::make_pair(p.id, p); });
125 std::vector<AudioPatch> patches;
126 RETURN_STATUS_IF_ERROR(
127 statusTFromBinderStatus(mModule->getAudioPatches(&patches))); // OK if empty
128 std::transform(patches.begin(), patches.end(),
129 std::inserter(mPatches, mPatches.end()),
130 [](const auto& p) { return std::make_pair(p.id, p); });
Shunkai Yao51202502022-12-12 06:11:46 +0000131 return OK;
132}
133
134status_t DeviceHalAidl::setVoiceVolume(float volume) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000135 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000136 if (!mModule) return NO_INIT;
137 std::shared_ptr<ITelephony> telephony;
138 if (ndk::ScopedAStatus status = mModule->getTelephony(&telephony);
139 status.isOk() && telephony != nullptr) {
140 ITelephony::TelecomConfig inConfig{ .voiceVolume = Float{volume} }, outConfig;
141 RETURN_STATUS_IF_ERROR(
142 statusTFromBinderStatus(telephony->setTelecomConfig(inConfig, &outConfig)));
143 ALOGW_IF(outConfig.voiceVolume.has_value() && volume != outConfig.voiceVolume.value().value,
144 "%s: the resulting voice volume %f is not the same as requested %f",
145 __func__, outConfig.voiceVolume.value().value, volume);
146 }
147 return INVALID_OPERATION;
Shunkai Yao51202502022-12-12 06:11:46 +0000148}
149
150status_t DeviceHalAidl::setMasterVolume(float volume) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000151 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000152 if (!mModule) return NO_INIT;
153 return statusTFromBinderStatus(mModule->setMasterVolume(volume));
Shunkai Yao51202502022-12-12 06:11:46 +0000154}
155
156status_t DeviceHalAidl::getMasterVolume(float *volume) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000157 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000158 if (!mModule) return NO_INIT;
159 return statusTFromBinderStatus(mModule->getMasterVolume(volume));
Shunkai Yao51202502022-12-12 06:11:46 +0000160}
161
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000162status_t DeviceHalAidl::setMode(audio_mode_t mode) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000163 TIME_CHECK();
164 if (!mModule) return NO_INIT;
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000165 AudioMode audioMode = VALUE_OR_FATAL(::aidl::android::legacy2aidl_audio_mode_t_AudioMode(mode));
166 std::shared_ptr<ITelephony> telephony;
167 if (ndk::ScopedAStatus status = mModule->getTelephony(&telephony);
168 status.isOk() && telephony != nullptr) {
169 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(telephony->switchAudioMode(audioMode)));
170 }
171 return statusTFromBinderStatus(mModule->updateAudioMode(audioMode));
Shunkai Yao51202502022-12-12 06:11:46 +0000172}
173
174status_t DeviceHalAidl::setMicMute(bool state) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000175 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000176 if (!mModule) return NO_INIT;
177 return statusTFromBinderStatus(mModule->setMicMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000178}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000179
Shunkai Yao51202502022-12-12 06:11:46 +0000180status_t DeviceHalAidl::getMicMute(bool *state) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000181 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000182 if (!mModule) return NO_INIT;
183 return statusTFromBinderStatus(mModule->getMicMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000184}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000185
Shunkai Yao51202502022-12-12 06:11:46 +0000186status_t DeviceHalAidl::setMasterMute(bool state) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000187 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000188 if (!mModule) return NO_INIT;
189 return statusTFromBinderStatus(mModule->setMasterMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000190}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000191
Shunkai Yao51202502022-12-12 06:11:46 +0000192status_t DeviceHalAidl::getMasterMute(bool *state) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000193 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000194 if (!mModule) return NO_INIT;
195 return statusTFromBinderStatus(mModule->getMasterMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000196}
197
Mikhail Naganov31d46652023-01-10 18:29:25 +0000198status_t DeviceHalAidl::setParameters(const String8& kvPairs __unused) {
199 TIME_CHECK();
200 if (!mModule) return NO_INIT;
201 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000202 return OK;
203}
204
Mikhail Naganov31d46652023-01-10 18:29:25 +0000205status_t DeviceHalAidl::getParameters(const String8& keys __unused, String8 *values) {
206 TIME_CHECK();
207 values->clear();
208 if (!mModule) return NO_INIT;
209 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000210 return OK;
211}
212
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800213namespace {
214
215class Cleanup {
216 public:
217 typedef void (DeviceHalAidl::*Cleaner)(int32_t);
218
219 Cleanup(DeviceHalAidl* device, Cleaner cleaner, int32_t id) :
220 mDevice(device), mCleaner(cleaner), mId(id) {}
221 ~Cleanup() { clean(); }
222 void clean() {
223 if (mDevice != nullptr) (mDevice->*mCleaner)(mId);
224 disarm();
225 }
226 void disarm() { mDevice = nullptr; }
227
228 private:
229 DeviceHalAidl* mDevice;
230 const Cleaner mCleaner;
231 const int32_t mId;
232};
233
234} // namespace
235
236// Since the order of container elements destruction is unspecified,
237// ensure that cleanups are performed from the most recent one and upwards.
238// This is the same as if there were individual Cleanup instances on the stack,
239// however the bonus is that we can disarm all of them with just one statement.
240class DeviceHalAidl::Cleanups : public std::forward_list<Cleanup> {
241 public:
242 ~Cleanups() { for (auto& c : *this) c.clean(); }
243 void disarmAll() { for (auto& c : *this) c.disarm(); }
244};
245
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800246status_t DeviceHalAidl::getInputBufferSize(const struct audio_config* config, size_t* size) {
247 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
248 if (size == nullptr) return BAD_VALUE;
249 TIME_CHECK();
250 if (!mModule) return NO_INIT;
251 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
252 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, true /*isInput*/));
253 AudioDevice aidlDevice;
254 aidlDevice.type.type = AudioDeviceType::IN_DEFAULT;
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800255 AudioSource aidlSource = AudioSource::DEFAULT;
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800256 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::input>(0);
257 AudioPortConfig mixPortConfig;
258 Cleanups cleanups;
259 audio_config writableConfig = *config;
260 int32_t nominalLatency;
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800261 RETURN_STATUS_IF_ERROR(prepareToOpenStream(0 /*handle*/, aidlDevice, aidlFlags, aidlSource,
262 &writableConfig, &cleanups, &aidlConfig, &mixPortConfig, &nominalLatency));
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800263 *size = aidlConfig.frameCount *
264 getFrameSizeInBytes(aidlConfig.base.format, aidlConfig.base.channelMask);
265 // Do not disarm cleanups to release temporary port configs.
266 return OK;
267}
268
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800269status_t DeviceHalAidl::prepareToOpenStream(
270 int32_t aidlHandle, const AudioDevice& aidlDevice, const AudioIoFlags& aidlFlags,
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800271 AudioSource aidlSource, struct audio_config* config,
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800272 Cleanups* cleanups, AudioConfig* aidlConfig, AudioPortConfig* mixPortConfig,
273 int32_t* nominalLatency) {
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800274 const bool isInput = aidlFlags.getTag() == AudioIoFlags::Tag::input;
275 // Find / create AudioPortConfigs for the device port and the mix port,
276 // then find / create a patch between them, and open a stream on the mix port.
277 AudioPortConfig devicePortConfig;
278 bool created = false;
279 RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(aidlDevice, &devicePortConfig, &created));
280 if (created) {
281 cleanups->emplace_front(this, &DeviceHalAidl::resetPortConfig, devicePortConfig.id);
282 }
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800283 RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(*aidlConfig, aidlFlags, aidlHandle, aidlSource,
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800284 mixPortConfig, &created));
285 if (created) {
286 cleanups->emplace_front(this, &DeviceHalAidl::resetPortConfig, mixPortConfig->id);
287 }
288 setConfigFromPortConfig(aidlConfig, *mixPortConfig);
289 AudioPatch patch;
290 if (isInput) {
291 RETURN_STATUS_IF_ERROR(findOrCreatePatch(
292 {devicePortConfig.id}, {mixPortConfig->id}, &patch, &created));
293 } else {
294 RETURN_STATUS_IF_ERROR(findOrCreatePatch(
295 {mixPortConfig->id}, {devicePortConfig.id}, &patch, &created));
296 }
297 if (created) {
298 cleanups->emplace_front(this, &DeviceHalAidl::resetPatch, patch.id);
299 }
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800300 *nominalLatency = patch.latenciesMs[0];
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800301 if (aidlConfig->frameCount <= 0) {
302 aidlConfig->frameCount = patch.minimumStreamBufferSizeFrames;
303 }
304 *config = VALUE_OR_RETURN_STATUS(
305 ::aidl::android::aidl2legacy_AudioConfig_audio_config_t(*aidlConfig, isInput));
306 return OK;
307}
308
Mikhail Naganovb0c55252023-02-08 16:59:41 -0800309namespace {
310
311class StreamCallbackBase {
312 protected:
313 explicit StreamCallbackBase(const sp<CallbackBroker>& broker) : mBroker(broker) {}
314 public:
315 void* getCookie() const { return mCookie; }
316 void setCookie(void* cookie) { mCookie = cookie; }
317 sp<CallbackBroker> getBroker() const {
318 if (void* cookie = mCookie; cookie != nullptr) return mBroker.promote();
319 return nullptr;
320 }
321 private:
322 const wp<CallbackBroker> mBroker;
323 std::atomic<void*> mCookie;
324};
325
326template<class C>
327class StreamCallbackBaseHelper {
328 protected:
329 explicit StreamCallbackBaseHelper(const StreamCallbackBase& base) : mBase(base) {}
330 sp<C> getCb(const sp<CallbackBroker>& broker, void* cookie);
331 using CbRef = const sp<C>&;
332 ndk::ScopedAStatus runCb(const std::function<void(CbRef cb)>& f) {
333 if (auto cb = getCb(mBase.getBroker(), mBase.getCookie()); cb != nullptr) f(cb);
334 return ndk::ScopedAStatus::ok();
335 }
336 private:
337 const StreamCallbackBase& mBase;
338};
339
340template<>
341sp<StreamOutHalInterfaceCallback> StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>::getCb(
342 const sp<CallbackBroker>& broker, void* cookie) {
343 if (broker != nullptr) return broker->getStreamOutCallback(cookie);
344 return nullptr;
345}
346
347template<>
348sp<StreamOutHalInterfaceEventCallback>
349StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>::getCb(
350 const sp<CallbackBroker>& broker, void* cookie) {
351 if (broker != nullptr) return broker->getStreamOutEventCallback(cookie);
352 return nullptr;
353}
354
355template<>
356sp<StreamOutHalInterfaceLatencyModeCallback>
357StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>::getCb(
358 const sp<CallbackBroker>& broker, void* cookie) {
359 if (broker != nullptr) return broker->getStreamOutLatencyModeCallback(cookie);
360 return nullptr;
361}
362
363/*
364Note on the callback ownership.
365
366In the Binder ownership model, the server implementation is kept alive
367as long as there is any client (proxy object) alive. This is done by
368incrementing the refcount of the server-side object by the Binder framework.
369When it detects that the last client is gone, it decrements the refcount back.
370
371Thus, it is not needed to keep any references to StreamCallback on our
372side (after we have sent an instance to the client), because we are
373the server-side. The callback object will be kept alive as long as the HAL server
374holds a strong ref to IStreamCallback proxy.
375*/
376
377class OutputStreamCallbackAidl : public StreamCallbackBase,
378 public StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>,
379 public ::aidl::android::hardware::audio::core::BnStreamCallback {
380 public:
381 explicit OutputStreamCallbackAidl(const sp<CallbackBroker>& broker)
382 : StreamCallbackBase(broker),
383 StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>(
384 *static_cast<StreamCallbackBase*>(this)) {}
385 ndk::ScopedAStatus onTransferReady() override {
386 return runCb([](CbRef cb) { cb->onWriteReady(); });
387 }
388 ndk::ScopedAStatus onError() override {
389 return runCb([](CbRef cb) { cb->onError(); });
390 }
391 ndk::ScopedAStatus onDrainReady() override {
392 return runCb([](CbRef cb) { cb->onDrainReady(); });
393 }
394};
395
396class OutputStreamEventCallbackAidl :
397 public StreamCallbackBase,
398 public StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>,
399 public StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>,
400 public ::aidl::android::hardware::audio::core::BnStreamOutEventCallback {
401 public:
402 explicit OutputStreamEventCallbackAidl(const sp<CallbackBroker>& broker)
403 : StreamCallbackBase(broker),
404 StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>(
405 *static_cast<StreamCallbackBase*>(this)),
406 StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>(
407 *static_cast<StreamCallbackBase*>(this)) {}
408 ndk::ScopedAStatus onCodecFormatChanged(const std::vector<uint8_t>& in_audioMetadata) override {
409 std::basic_string<uint8_t> halMetadata(in_audioMetadata.begin(), in_audioMetadata.end());
410 return StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>::runCb(
411 [&halMetadata](auto cb) { cb->onCodecFormatChanged(halMetadata); });
412 }
413 ndk::ScopedAStatus onRecommendedLatencyModeChanged(
414 const std::vector<AudioLatencyMode>& in_modes) override {
415 auto halModes = VALUE_OR_FATAL(
416 ::aidl::android::convertContainer<std::vector<audio_latency_mode_t>>(
417 in_modes,
418 ::aidl::android::aidl2legacy_AudioLatencyMode_audio_latency_mode_t));
419 return StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>::runCb(
420 [&halModes](auto cb) { cb->onRecommendedLatencyModeChanged(halModes); });
421 }
422};
423
424} // namespace
425
Mikhail Naganov31d46652023-01-10 18:29:25 +0000426status_t DeviceHalAidl::openOutputStream(
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800427 audio_io_handle_t handle, audio_devices_t devices,
428 audio_output_flags_t flags, struct audio_config* config,
429 const char* address,
Mikhail Naganov31d46652023-01-10 18:29:25 +0000430 sp<StreamOutHalInterface>* outStream) {
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800431 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000432 if (!outStream || !config) {
433 return BAD_VALUE;
434 }
435 TIME_CHECK();
436 if (!mModule) return NO_INIT;
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800437 int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
438 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(handle));
439 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
440 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, false /*isInput*/));
441 AudioDevice aidlDevice = VALUE_OR_RETURN_STATUS(
442 ::aidl::android::legacy2aidl_audio_device_AudioDevice(devices, address));
443 int32_t aidlOutputFlags = VALUE_OR_RETURN_STATUS(
444 ::aidl::android::legacy2aidl_audio_output_flags_t_int32_t_mask(flags));
445 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::output>(aidlOutputFlags);
446 AudioPortConfig mixPortConfig;
447 Cleanups cleanups;
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800448 int32_t nominalLatency;
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800449 RETURN_STATUS_IF_ERROR(prepareToOpenStream(aidlHandle, aidlDevice, aidlFlags,
450 AudioSource::SYS_RESERVED_INVALID /*only needed for input*/,
451 config, &cleanups, &aidlConfig, &mixPortConfig, &nominalLatency));
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800452 ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamArguments args;
453 args.portConfigId = mixPortConfig.id;
Mikhail Naganovb0c55252023-02-08 16:59:41 -0800454 const bool isOffload = isBitPositionFlagSet(
455 aidlOutputFlags, AudioOutputFlags::COMPRESS_OFFLOAD);
456 std::shared_ptr<OutputStreamCallbackAidl> streamCb;
457 if (isOffload) {
458 streamCb = ndk::SharedRefBase::make<OutputStreamCallbackAidl>(this);
459 }
460 auto eventCb = ndk::SharedRefBase::make<OutputStreamEventCallbackAidl>(this);
461 if (isOffload) {
462 args.offloadInfo = aidlConfig.offloadInfo;
463 args.callback = streamCb;
464 }
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800465 args.bufferSizeFrames = aidlConfig.frameCount;
Mikhail Naganovb0c55252023-02-08 16:59:41 -0800466 args.eventCallback = eventCb;
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800467 ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamReturn ret;
468 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openOutputStream(args, &ret)));
Mikhail Naganov712d71b2023-02-23 17:57:16 -0800469 StreamContextAidl context(ret.desc, isOffload);
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800470 if (!context.isValid()) {
471 ALOGE("%s: Failed to created a valid stream context from the descriptor: %s",
472 __func__, ret.desc.toString().c_str());
473 return NO_INIT;
474 }
475 *outStream = sp<StreamOutHalAidl>::make(*config, std::move(context), nominalLatency,
Mikhail Naganovb0c55252023-02-08 16:59:41 -0800476 std::move(ret.stream), this /*callbackBroker*/);
477 void* cbCookie = (*outStream).get();
478 {
479 std::lock_guard l(mLock);
480 mCallbacks.emplace(cbCookie, Callbacks{});
481 }
482 if (streamCb) streamCb->setCookie(cbCookie);
483 eventCb->setCookie(cbCookie);
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800484 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000485 return OK;
486}
487
Mikhail Naganov31d46652023-01-10 18:29:25 +0000488status_t DeviceHalAidl::openInputStream(
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800489 audio_io_handle_t handle, audio_devices_t devices,
490 struct audio_config* config, audio_input_flags_t flags,
491 const char* address, audio_source_t source,
492 audio_devices_t outputDevice, const char* outputDeviceAddress,
Mikhail Naganov31d46652023-01-10 18:29:25 +0000493 sp<StreamInHalInterface>* inStream) {
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800494 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000495 if (!inStream || !config) {
496 return BAD_VALUE;
497 }
498 TIME_CHECK();
499 if (!mModule) return NO_INIT;
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800500 int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
501 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(handle));
502 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
503 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, true /*isInput*/));
504 AudioDevice aidlDevice = VALUE_OR_RETURN_STATUS(
505 ::aidl::android::legacy2aidl_audio_device_AudioDevice(devices, address));
506 int32_t aidlInputFlags = VALUE_OR_RETURN_STATUS(
507 ::aidl::android::legacy2aidl_audio_input_flags_t_int32_t_mask(flags));
508 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::input>(aidlInputFlags);
509 AudioSource aidlSource = VALUE_OR_RETURN_STATUS(
510 ::aidl::android::legacy2aidl_audio_source_t_AudioSource(source));
511 AudioPortConfig mixPortConfig;
512 Cleanups cleanups;
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800513 int32_t nominalLatency;
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800514 RETURN_STATUS_IF_ERROR(prepareToOpenStream(aidlHandle, aidlDevice, aidlFlags, aidlSource,
515 config, &cleanups, &aidlConfig, &mixPortConfig, &nominalLatency));
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800516 ::aidl::android::hardware::audio::core::IModule::OpenInputStreamArguments args;
517 args.portConfigId = mixPortConfig.id;
518 RecordTrackMetadata aidlTrackMetadata{
519 .source = aidlSource, .gain = 1, .channelMask = aidlConfig.base.channelMask };
520 if (outputDevice != AUDIO_DEVICE_NONE) {
521 aidlTrackMetadata.destinationDevice = VALUE_OR_RETURN_STATUS(
522 ::aidl::android::legacy2aidl_audio_device_AudioDevice(
523 outputDevice, outputDeviceAddress));
524 }
525 args.sinkMetadata.tracks.push_back(std::move(aidlTrackMetadata));
526 args.bufferSizeFrames = aidlConfig.frameCount;
527 ::aidl::android::hardware::audio::core::IModule::OpenInputStreamReturn ret;
528 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openInputStream(args, &ret)));
Mikhail Naganov712d71b2023-02-23 17:57:16 -0800529 StreamContextAidl context(ret.desc, false /*isAsynchronous*/);
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800530 if (!context.isValid()) {
531 ALOGE("%s: Failed to created a valid stream context from the descriptor: %s",
532 __func__, ret.desc.toString().c_str());
533 return NO_INIT;
534 }
535 *inStream = sp<StreamInHalAidl>::make(*config, std::move(context), nominalLatency,
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800536 std::move(ret.stream), this /*micInfoProvider*/);
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800537 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000538 return OK;
539}
540
541status_t DeviceHalAidl::supportsAudioPatches(bool* supportsPatches) {
542 *supportsPatches = true;
543 return OK;
544}
545
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800546status_t DeviceHalAidl::createAudioPatch(unsigned int num_sources,
547 const struct audio_port_config* sources,
548 unsigned int num_sinks,
549 const struct audio_port_config* sinks,
550 audio_patch_handle_t* patch) {
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800551 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000552 TIME_CHECK();
553 if (!mModule) return NO_INIT;
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800554 if (num_sinks > AUDIO_PATCH_PORTS_MAX || num_sources > AUDIO_PATCH_PORTS_MAX ||
555 sources == nullptr || sinks == nullptr || patch == nullptr) {
556 return BAD_VALUE;
557 }
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800558 // When the patch handle (*patch) is AUDIO_PATCH_HANDLE_NONE, it means
559 // the framework wants to create a new patch. The handle has to be generated
560 // by the HAL. Since handles generated this way can only be unique within
561 // a HAL module, the framework generates a globally unique handle, and maps
562 // it on the <HAL module, patch handle> pair.
563 // When the patch handle is set, it meant the framework intends to update
564 // an existing patch.
565 //
566 // This behavior corresponds to HAL module behavior, with the only difference
567 // that the HAL module uses `int32_t` for patch IDs. The following assert ensures
568 // that both the framework and the HAL use the same value for "no ID":
569 static_assert(AUDIO_PATCH_HANDLE_NONE == 0);
570 int32_t halPatchId = static_cast<int32_t>(*patch);
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800571
572 // Upon conversion, mix port configs contain audio configuration, while
573 // device port configs contain device address. This data is used to find
574 // or create HAL configs.
575 std::vector<AudioPortConfig> aidlSources, aidlSinks;
576 for (unsigned int i = 0; i < num_sources; ++i) {
577 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
578 sources[i].role, sources[i].type)) ==
579 ::aidl::android::AudioPortDirection::INPUT;
580 aidlSources.push_back(VALUE_OR_RETURN_STATUS(
581 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
582 sources[i], isInput, 0)));
583 }
584 for (unsigned int i = 0; i < num_sinks; ++i) {
585 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
586 sinks[i].role, sinks[i].type)) ==
587 ::aidl::android::AudioPortDirection::INPUT;
588 aidlSinks.push_back(VALUE_OR_RETURN_STATUS(
589 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
590 sinks[i], isInput, 0)));
591 }
592 Cleanups cleanups;
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800593 auto existingPatchIt = halPatchId != 0 ? mPatches.find(halPatchId): mPatches.end();
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800594 AudioPatch aidlPatch;
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800595 if (existingPatchIt != mPatches.end()) {
596 aidlPatch = existingPatchIt->second;
597 aidlPatch.sourcePortConfigIds.clear();
598 aidlPatch.sinkPortConfigIds.clear();
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800599 }
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800600 ALOGD("%s: sources: %s, sinks: %s",
601 __func__, ::android::internal::ToString(aidlSources).c_str(),
602 ::android::internal::ToString(aidlSinks).c_str());
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800603 auto fillPortConfigs = [&](
604 const std::vector<AudioPortConfig>& configs, std::vector<int32_t>* ids) -> status_t {
605 for (const auto& s : configs) {
606 AudioPortConfig portConfig;
607 bool created = false;
608 RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(s, &portConfig, &created));
609 if (created) {
610 cleanups.emplace_front(this, &DeviceHalAidl::resetPortConfig, portConfig.id);
611 }
612 ids->push_back(portConfig.id);
613 }
614 return OK;
615 };
616 RETURN_STATUS_IF_ERROR(fillPortConfigs(aidlSources, &aidlPatch.sourcePortConfigIds));
617 RETURN_STATUS_IF_ERROR(fillPortConfigs(aidlSinks, &aidlPatch.sinkPortConfigIds));
618 if (existingPatchIt != mPatches.end()) {
619 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
620 mModule->setAudioPatch(aidlPatch, &aidlPatch)));
621 existingPatchIt->second = aidlPatch;
622 } else {
623 bool created = false;
624 RETURN_STATUS_IF_ERROR(findOrCreatePatch(aidlPatch, &aidlPatch, &created));
625 // Since no cleanup of the patch is needed, 'created' is ignored.
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800626 halPatchId = aidlPatch.id;
627 *patch = static_cast<audio_patch_handle_t>(halPatchId);
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800628 }
629 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000630 return OK;
631}
632
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800633status_t DeviceHalAidl::releaseAudioPatch(audio_patch_handle_t patch) {
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800634 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000635 TIME_CHECK();
636 if (!mModule) return NO_INIT;
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800637 static_assert(AUDIO_PATCH_HANDLE_NONE == 0);
638 if (patch == AUDIO_PATCH_HANDLE_NONE) {
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800639 return BAD_VALUE;
640 }
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800641 int32_t halPatchId = static_cast<int32_t>(patch);
642 auto patchIt = mPatches.find(halPatchId);
643 if (patchIt == mPatches.end()) {
644 ALOGE("%s: patch with id %d not found", __func__, halPatchId);
645 return BAD_VALUE;
646 }
647 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->resetAudioPatch(halPatchId)));
648 mPatches.erase(patchIt);
Shunkai Yao51202502022-12-12 06:11:46 +0000649 return OK;
650}
651
Mikhail Naganov31d46652023-01-10 18:29:25 +0000652status_t DeviceHalAidl::getAudioPort(struct audio_port* port __unused) {
653 TIME_CHECK();
654 ALOGE("%s not implemented yet", __func__);
655 return INVALID_OPERATION;
656}
657
658status_t DeviceHalAidl::getAudioPort(struct audio_port_v7 *port __unused) {
659 TIME_CHECK();
660 ALOGE("%s not implemented yet", __func__);
661 return INVALID_OPERATION;
662}
663
664status_t DeviceHalAidl::setAudioPortConfig(const struct audio_port_config* config __unused) {
665 TIME_CHECK();
666 if (!mModule) return NO_INIT;
667 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000668 return OK;
669}
670
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800671MicrophoneInfoProvider::Info const* DeviceHalAidl::getMicrophoneInfo() {
672 if (mMicrophones.status == Microphones::Status::UNKNOWN) {
673 TIME_CHECK();
674 std::vector<MicrophoneInfo> aidlInfo;
675 status_t status = statusTFromBinderStatus(mModule->getMicrophones(&aidlInfo));
676 if (status == OK) {
677 mMicrophones.status = Microphones::Status::QUERIED;
678 mMicrophones.info = std::move(aidlInfo);
679 } else if (status == INVALID_OPERATION) {
680 mMicrophones.status = Microphones::Status::NOT_SUPPORTED;
681 } else {
682 ALOGE("%s: Unexpected status from 'IModule.getMicrophones': %d", __func__, status);
683 return {};
684 }
685 }
686 if (mMicrophones.status == Microphones::Status::QUERIED) {
687 return &mMicrophones.info;
688 }
689 return {}; // NOT_SUPPORTED
690}
691
Shunkai Yao51202502022-12-12 06:11:46 +0000692status_t DeviceHalAidl::getMicrophones(
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800693 std::vector<audio_microphone_characteristic_t>* microphones) {
694 if (!microphones) {
695 return BAD_VALUE;
696 }
Mikhail Naganov31d46652023-01-10 18:29:25 +0000697 TIME_CHECK();
698 if (!mModule) return NO_INIT;
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800699 auto staticInfo = getMicrophoneInfo();
700 if (!staticInfo) return INVALID_OPERATION;
701 std::vector<MicrophoneDynamicInfo> emptyDynamicInfo;
702 emptyDynamicInfo.reserve(staticInfo->size());
703 std::transform(staticInfo->begin(), staticInfo->end(), std::back_inserter(emptyDynamicInfo),
704 [](const auto& info) { return MicrophoneDynamicInfo{ .id = info.id }; });
705 *microphones = VALUE_OR_RETURN_STATUS(
706 ::aidl::android::convertContainers<std::vector<audio_microphone_characteristic_t>>(
707 *staticInfo, emptyDynamicInfo,
708 ::aidl::android::aidl2legacy_MicrophoneInfos_audio_microphone_characteristic_t)
709 );
Shunkai Yao51202502022-12-12 06:11:46 +0000710 return OK;
711}
712
Mikhail Naganov31d46652023-01-10 18:29:25 +0000713status_t DeviceHalAidl::addDeviceEffect(audio_port_handle_t device __unused,
714 sp<EffectHalInterface> effect) {
Shunkai Yao51202502022-12-12 06:11:46 +0000715 if (!effect) {
716 return BAD_VALUE;
717 }
Mikhail Naganov31d46652023-01-10 18:29:25 +0000718 TIME_CHECK();
719 if (!mModule) return NO_INIT;
720 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000721 return OK;
722}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000723status_t DeviceHalAidl::removeDeviceEffect(audio_port_handle_t device __unused,
Shunkai Yao51202502022-12-12 06:11:46 +0000724 sp<EffectHalInterface> effect) {
725 if (!effect) {
726 return BAD_VALUE;
727 }
Mikhail Naganov31d46652023-01-10 18:29:25 +0000728 TIME_CHECK();
729 if (!mModule) return NO_INIT;
730 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000731 return OK;
732}
733
734status_t DeviceHalAidl::getMmapPolicyInfos(
735 media::audio::common::AudioMMapPolicyType policyType __unused,
736 std::vector<media::audio::common::AudioMMapPolicyInfo>* policyInfos __unused) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000737 TIME_CHECK();
Shunkai Yao51202502022-12-12 06:11:46 +0000738 ALOGE("%s not implemented yet", __func__);
739 return OK;
740}
741
742int32_t DeviceHalAidl::getAAudioMixerBurstCount() {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000743 TIME_CHECK();
Shunkai Yao51202502022-12-12 06:11:46 +0000744 ALOGE("%s not implemented yet", __func__);
745 return OK;
746}
747
748int32_t DeviceHalAidl::getAAudioHardwareBurstMinUsec() {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000749 TIME_CHECK();
Shunkai Yao51202502022-12-12 06:11:46 +0000750 ALOGE("%s not implemented yet", __func__);
751 return OK;
752}
753
754error::Result<audio_hw_sync_t> DeviceHalAidl::getHwAvSync() {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000755 TIME_CHECK();
Mikhail Naganov08a62ab2023-03-14 17:11:51 -0700756 if (!mModule) return NO_INIT;
757 int32_t aidlHwAvSync;
758 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->generateHwAvSyncId(&aidlHwAvSync)));
759 return VALUE_OR_RETURN_STATUS(
760 ::aidl::android::aidl2legacy_int32_t_audio_hw_sync_t(aidlHwAvSync));
Shunkai Yao51202502022-12-12 06:11:46 +0000761}
762
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000763status_t DeviceHalAidl::dump(int fd, const Vector<String16>& args) {
764 TIME_CHECK();
765 if (!mModule) return NO_INIT;
766 return mModule->dump(fd, Args(args).args(), args.size());
Shunkai Yao51202502022-12-12 06:11:46 +0000767};
768
Mikhail Naganov31d46652023-01-10 18:29:25 +0000769int32_t DeviceHalAidl::supportsBluetoothVariableLatency(bool* supports __unused) {
770 TIME_CHECK();
Shunkai Yao51202502022-12-12 06:11:46 +0000771 ALOGE("%s not implemented yet", __func__);
772 return INVALID_OPERATION;
773}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000774
Vlad Popa03bd5bc2023-01-17 16:16:51 +0100775status_t DeviceHalAidl::getSoundDoseInterface(const std::string& module,
776 ::ndk::SpAIBinder* soundDoseBinder) {
777 TIME_CHECK();
778 if (!mModule) return NO_INIT;
779 if (mSoundDose == nullptr) {
780 ndk::ScopedAStatus status = mModule->getSoundDose(&mSoundDose);
781 if (!status.isOk()) {
782 ALOGE("%s failed to return the sound dose interface for module %s: %s",
783 __func__,
784 module.c_str(),
785 status.getDescription().c_str());
786 return BAD_VALUE;
787 }
788 }
789 *soundDoseBinder = mSoundDose->asBinder();
790 ALOGI("%s using audio AIDL HAL sound dose interface", __func__);
791
792 return OK;
793}
794
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800795bool DeviceHalAidl::audioDeviceMatches(const AudioDevice& device, const AudioPort& p) {
796 if (p.ext.getTag() != AudioPortExt::Tag::device) return false;
797 return p.ext.get<AudioPortExt::Tag::device>().device == device;
798}
799
800bool DeviceHalAidl::audioDeviceMatches(const AudioDevice& device, const AudioPortConfig& p) {
801 if (p.ext.getTag() != AudioPortExt::Tag::device) return false;
802 if (device.type.type == AudioDeviceType::IN_DEFAULT) {
803 return p.portId == mDefaultInputPortId;
804 } else if (device.type.type == AudioDeviceType::OUT_DEFAULT) {
805 return p.portId == mDefaultOutputPortId;
806 }
807 return p.ext.get<AudioPortExt::Tag::device>().device == device;
808}
809
Mikhail Naganov1a44bc62023-02-16 17:35:06 -0800810status_t DeviceHalAidl::createPortConfig(
811 const AudioPortConfig& requestedPortConfig, PortConfigs::iterator* result) {
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800812 TIME_CHECK();
Mikhail Naganov1a44bc62023-02-16 17:35:06 -0800813 AudioPortConfig appliedPortConfig;
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800814 bool applied = false;
815 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPortConfig(
Mikhail Naganov1a44bc62023-02-16 17:35:06 -0800816 requestedPortConfig, &appliedPortConfig, &applied)));
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800817 if (!applied) {
818 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPortConfig(
Mikhail Naganov1a44bc62023-02-16 17:35:06 -0800819 appliedPortConfig, &appliedPortConfig, &applied)));
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800820 if (!applied) {
821 ALOGE("%s: module %s did not apply suggested config %s",
Mikhail Naganov1a44bc62023-02-16 17:35:06 -0800822 __func__, mInstance.c_str(), appliedPortConfig.toString().c_str());
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800823 return NO_INIT;
824 }
825 }
Mikhail Naganov1a44bc62023-02-16 17:35:06 -0800826 auto id = appliedPortConfig.id;
827 auto [it, inserted] = mPortConfigs.emplace(std::move(id), std::move(appliedPortConfig));
828 LOG_ALWAYS_FATAL_IF(!inserted, "%s: port config with id %d already exists",
829 __func__, it->first);
830 *result = it;
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800831 return OK;
832}
833
834status_t DeviceHalAidl::findOrCreatePatch(
835 const AudioPatch& requestedPatch, AudioPatch* patch, bool* created) {
836 std::set<int32_t> sourcePortConfigIds(requestedPatch.sourcePortConfigIds.begin(),
837 requestedPatch.sourcePortConfigIds.end());
838 std::set<int32_t> sinkPortConfigIds(requestedPatch.sinkPortConfigIds.begin(),
839 requestedPatch.sinkPortConfigIds.end());
840 return findOrCreatePatch(sourcePortConfigIds, sinkPortConfigIds, patch, created);
841}
842
843status_t DeviceHalAidl::findOrCreatePatch(
844 const std::set<int32_t>& sourcePortConfigIds, const std::set<int32_t>& sinkPortConfigIds,
845 AudioPatch* patch, bool* created) {
846 auto patchIt = findPatch(sourcePortConfigIds, sinkPortConfigIds);
847 if (patchIt == mPatches.end()) {
848 TIME_CHECK();
849 AudioPatch requestedPatch, appliedPatch;
850 requestedPatch.sourcePortConfigIds.insert(requestedPatch.sourcePortConfigIds.end(),
851 sourcePortConfigIds.begin(), sourcePortConfigIds.end());
852 requestedPatch.sinkPortConfigIds.insert(requestedPatch.sinkPortConfigIds.end(),
853 sinkPortConfigIds.begin(), sinkPortConfigIds.end());
854 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPatch(
855 requestedPatch, &appliedPatch)));
856 patchIt = mPatches.insert(mPatches.end(), std::make_pair(appliedPatch.id, appliedPatch));
857 *created = true;
858 } else {
859 *created = false;
860 }
861 *patch = patchIt->second;
862 return OK;
863}
864
865status_t DeviceHalAidl::findOrCreatePortConfig(const AudioDevice& device,
866 AudioPortConfig* portConfig, bool* created) {
867 auto portConfigIt = findPortConfig(device);
868 if (portConfigIt == mPortConfigs.end()) {
869 auto portsIt = findPort(device);
870 if (portsIt == mPorts.end()) {
871 ALOGE("%s: device port for device %s is not found in the module %s",
872 __func__, device.toString().c_str(), mInstance.c_str());
873 return BAD_VALUE;
874 }
875 AudioPortConfig requestedPortConfig;
876 requestedPortConfig.portId = portsIt->first;
Mikhail Naganov1a44bc62023-02-16 17:35:06 -0800877 RETURN_STATUS_IF_ERROR(createPortConfig(requestedPortConfig, &portConfigIt));
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800878 *created = true;
879 } else {
880 *created = false;
881 }
882 *portConfig = portConfigIt->second;
883 return OK;
884}
885
886status_t DeviceHalAidl::findOrCreatePortConfig(
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800887 const AudioConfig& config, const std::optional<AudioIoFlags>& flags, int32_t ioHandle,
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800888 AudioSource source, AudioPortConfig* portConfig, bool* created) {
Mikhail Naganov1a44bc62023-02-16 17:35:06 -0800889 // These flags get removed one by one in this order when retrying port finding.
890 static const std::vector<AudioInputFlags> kOptionalInputFlags{
891 AudioInputFlags::FAST, AudioInputFlags::RAW };
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800892 auto portConfigIt = findPortConfig(config, flags, ioHandle);
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800893 if (portConfigIt == mPortConfigs.end() && flags.has_value()) {
Mikhail Naganov1a44bc62023-02-16 17:35:06 -0800894 auto optionalInputFlagsIt = kOptionalInputFlags.begin();
895 AudioIoFlags matchFlags = flags.value();
896 auto portsIt = findPort(config, matchFlags);
897 while (portsIt == mPorts.end() && matchFlags.getTag() == AudioIoFlags::Tag::input
898 && optionalInputFlagsIt != kOptionalInputFlags.end()) {
899 if (!isBitPositionFlagSet(
900 matchFlags.get<AudioIoFlags::Tag::input>(), *optionalInputFlagsIt)) {
901 ++optionalInputFlagsIt;
902 continue;
903 }
904 matchFlags.set<AudioIoFlags::Tag::input>(matchFlags.get<AudioIoFlags::Tag::input>() &
905 ~makeBitPositionFlagMask(*optionalInputFlagsIt++));
906 portsIt = findPort(config, matchFlags);
907 ALOGI("%s: mix port for config %s, flags %s was not found in the module %s, "
908 "retried with flags %s", __func__, config.toString().c_str(),
909 flags.value().toString().c_str(), mInstance.c_str(),
910 matchFlags.toString().c_str());
911 }
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800912 if (portsIt == mPorts.end()) {
913 ALOGE("%s: mix port for config %s, flags %s is not found in the module %s",
Mikhail Naganov1a44bc62023-02-16 17:35:06 -0800914 __func__, config.toString().c_str(), matchFlags.toString().c_str(),
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800915 mInstance.c_str());
916 return BAD_VALUE;
917 }
918 AudioPortConfig requestedPortConfig;
919 requestedPortConfig.portId = portsIt->first;
920 setPortConfigFromConfig(&requestedPortConfig, config);
Mikhail Naganov1a44bc62023-02-16 17:35:06 -0800921 requestedPortConfig.ext = AudioPortMixExt{ .handle = ioHandle };
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800922 if (matchFlags.getTag() == AudioIoFlags::Tag::input
923 && source != AudioSource::SYS_RESERVED_INVALID) {
924 requestedPortConfig.ext.get<AudioPortExt::Tag::mix>().usecase =
925 AudioPortMixExtUseCase::make<AudioPortMixExtUseCase::Tag::source>(source);
926 }
Mikhail Naganov1a44bc62023-02-16 17:35:06 -0800927 RETURN_STATUS_IF_ERROR(createPortConfig(requestedPortConfig, &portConfigIt));
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800928 *created = true;
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800929 } else if (!flags.has_value()) {
930 ALOGW("%s: mix port config for %s, handle %d not found in the module %s, "
931 "and was not created as flags are not specified",
932 __func__, config.toString().c_str(), ioHandle, mInstance.c_str());
933 return BAD_VALUE;
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800934 } else {
935 *created = false;
936 }
937 *portConfig = portConfigIt->second;
938 return OK;
939}
940
941status_t DeviceHalAidl::findOrCreatePortConfig(
942 const AudioPortConfig& requestedPortConfig, AudioPortConfig* portConfig, bool* created) {
943 using Tag = AudioPortExt::Tag;
944 if (requestedPortConfig.ext.getTag() == Tag::mix) {
945 if (const auto& p = requestedPortConfig;
946 !p.sampleRate.has_value() || !p.channelMask.has_value() ||
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800947 !p.format.has_value()) {
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800948 ALOGW("%s: provided mix port config is not fully specified: %s",
949 __func__, p.toString().c_str());
950 return BAD_VALUE;
951 }
952 AudioConfig config;
953 setConfigFromPortConfig(&config, requestedPortConfig);
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800954 AudioSource source = requestedPortConfig.ext.get<Tag::mix>().usecase.getTag() ==
955 AudioPortMixExtUseCase::Tag::source ?
956 requestedPortConfig.ext.get<Tag::mix>().usecase.
957 get<AudioPortMixExtUseCase::Tag::source>() : AudioSource::SYS_RESERVED_INVALID;
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800958 return findOrCreatePortConfig(config, requestedPortConfig.flags,
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800959 requestedPortConfig.ext.get<Tag::mix>().handle, source, portConfig, created);
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800960 } else if (requestedPortConfig.ext.getTag() == Tag::device) {
961 return findOrCreatePortConfig(
962 requestedPortConfig.ext.get<Tag::device>().device, portConfig, created);
963 }
964 ALOGW("%s: unsupported audio port config: %s",
965 __func__, requestedPortConfig.toString().c_str());
966 return BAD_VALUE;
967}
968
969DeviceHalAidl::Patches::iterator DeviceHalAidl::findPatch(
970 const std::set<int32_t>& sourcePortConfigIds, const std::set<int32_t>& sinkPortConfigIds) {
971 return std::find_if(mPatches.begin(), mPatches.end(),
972 [&](const auto& pair) {
973 const auto& p = pair.second;
974 std::set<int32_t> patchSrcs(
975 p.sourcePortConfigIds.begin(), p.sourcePortConfigIds.end());
976 std::set<int32_t> patchSinks(
977 p.sinkPortConfigIds.begin(), p.sinkPortConfigIds.end());
978 return sourcePortConfigIds == patchSrcs && sinkPortConfigIds == patchSinks; });
979}
980
981DeviceHalAidl::Ports::iterator DeviceHalAidl::findPort(const AudioDevice& device) {
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800982 if (device.type.type == AudioDeviceType::IN_DEFAULT) {
983 return mPorts.find(mDefaultInputPortId);
984 } else if (device.type.type == AudioDeviceType::OUT_DEFAULT) {
985 return mPorts.find(mDefaultOutputPortId);
986 }
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800987 return std::find_if(mPorts.begin(), mPorts.end(),
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800988 [&](const auto& pair) { return audioDeviceMatches(device, pair.second); });
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800989}
990
991DeviceHalAidl::Ports::iterator DeviceHalAidl::findPort(
992 const AudioConfig& config, const AudioIoFlags& flags) {
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800993 auto matcher = [&](const auto& pair) {
994 const auto& p = pair.second;
Mikhail Naganov1a44bc62023-02-16 17:35:06 -0800995 return p.ext.getTag() == AudioPortExt::Tag::mix &&
996 p.flags == flags &&
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800997 std::find_if(p.profiles.begin(), p.profiles.end(),
998 [&](const auto& prof) {
999 return prof.format == config.base.format &&
1000 std::find(prof.channelMasks.begin(), prof.channelMasks.end(),
1001 config.base.channelMask) != prof.channelMasks.end() &&
1002 std::find(prof.sampleRates.begin(), prof.sampleRates.end(),
1003 config.base.sampleRate) != prof.sampleRates.end();
1004 }) != p.profiles.end(); };
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001005 return std::find_if(mPorts.begin(), mPorts.end(), matcher);
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001006}
1007
1008DeviceHalAidl::PortConfigs::iterator DeviceHalAidl::findPortConfig(const AudioDevice& device) {
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001009 return std::find_if(mPortConfigs.begin(), mPortConfigs.end(),
Mikhail Naganov8bd806e2023-01-30 12:33:18 -08001010 [&](const auto& pair) { return audioDeviceMatches(device, pair.second); });
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001011}
1012
1013DeviceHalAidl::PortConfigs::iterator DeviceHalAidl::findPortConfig(
Mikhail Naganov8bd806e2023-01-30 12:33:18 -08001014 const AudioConfig& config, const std::optional<AudioIoFlags>& flags, int32_t ioHandle) {
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001015 using Tag = AudioPortExt::Tag;
1016 return std::find_if(mPortConfigs.begin(), mPortConfigs.end(),
1017 [&](const auto& pair) {
1018 const auto& p = pair.second;
1019 LOG_ALWAYS_FATAL_IF(p.ext.getTag() == Tag::mix &&
1020 !p.sampleRate.has_value() || !p.channelMask.has_value() ||
1021 !p.format.has_value() || !p.flags.has_value(),
1022 "%s: stored mix port config is not fully specified: %s",
1023 __func__, p.toString().c_str());
1024 return p.ext.getTag() == Tag::mix &&
1025 isConfigEqualToPortConfig(config, p) &&
Mikhail Naganov8bd806e2023-01-30 12:33:18 -08001026 (!flags.has_value() || p.flags.value() == flags.value()) &&
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001027 p.ext.template get<Tag::mix>().handle == ioHandle; });
1028}
1029/*
1030DeviceHalAidl::PortConfigs::iterator DeviceHalAidl::findPortConfig(
1031 const AudioPortConfig& portConfig) {
1032 using Tag = AudioPortExt::Tag;
1033 if (portConfig.ext.getTag() == Tag::mix) {
1034 return std::find_if(mPortConfigs.begin(), mPortConfigs.end(),
1035 [&](const auto& pair) {
1036 const auto& p = pair.second;
1037 LOG_ALWAYS_FATAL_IF(p.ext.getTag() == Tag::mix &&
1038 !p.sampleRate.has_value() || !p.channelMask.has_value() ||
1039 !p.format.has_value() || !p.flags.has_value(),
1040 "%s: stored mix port config is not fully specified: %s",
1041 __func__, p.toString().c_str());
1042 return p.ext.getTag() == Tag::mix &&
1043 (!portConfig.sampleRate.has_value() ||
1044 p.sampleRate == portConfig.sampleRate) &&
1045 (!portConfig.channelMask.has_value() ||
1046 p.channelMask == portConfig.channelMask) &&
1047 (!portConfig.format.has_value() || p.format == portConfig.format) &&
1048 (!portConfig.flags.has_value() || p.flags == portConfig.flags) &&
1049 p.ext.template get<Tag::mix>().handle ==
1050 portConfig.ext.template get<Tag::mix>().handle; });
1051 } else if (portConfig.ext.getTag() == Tag::device) {
1052 return findPortConfig(portConfig.ext.get<Tag::device>().device);
1053 }
1054 return mPortConfigs.end();
1055}
1056*/
1057void DeviceHalAidl::resetPatch(int32_t patchId) {
1058 if (auto it = mPatches.find(patchId); it != mPatches.end()) {
1059 mPatches.erase(it);
1060 TIME_CHECK();
1061 if (ndk::ScopedAStatus status = mModule->resetAudioPatch(patchId); !status.isOk()) {
1062 ALOGE("%s: error while resetting patch %d: %s",
1063 __func__, patchId, status.getDescription().c_str());
1064 }
1065 return;
1066 }
1067 ALOGE("%s: patch id %d not found", __func__, patchId);
1068}
1069
1070void DeviceHalAidl::resetPortConfig(int32_t portConfigId) {
1071 if (auto it = mPortConfigs.find(portConfigId); it != mPortConfigs.end()) {
1072 mPortConfigs.erase(it);
1073 TIME_CHECK();
1074 if (ndk::ScopedAStatus status = mModule->resetAudioPortConfig(portConfigId);
1075 !status.isOk()) {
1076 ALOGE("%s: error while resetting port config %d: %s",
1077 __func__, portConfigId, status.getDescription().c_str());
1078 }
1079 return;
1080 }
1081 ALOGE("%s: port config id %d not found", __func__, portConfigId);
1082}
1083
Mikhail Naganovb0c55252023-02-08 16:59:41 -08001084void DeviceHalAidl::clearCallbacks(void* cookie) {
1085 std::lock_guard l(mLock);
1086 mCallbacks.erase(cookie);
1087}
1088
1089sp<StreamOutHalInterfaceCallback> DeviceHalAidl::getStreamOutCallback(void* cookie) {
1090 return getCallbackImpl(cookie, &Callbacks::out);
1091}
1092
1093void DeviceHalAidl::setStreamOutCallback(
1094 void* cookie, const sp<StreamOutHalInterfaceCallback>& cb) {
1095 setCallbackImpl(cookie, &Callbacks::out, cb);
1096}
1097
1098sp<StreamOutHalInterfaceEventCallback> DeviceHalAidl::getStreamOutEventCallback(
1099 void* cookie) {
1100 return getCallbackImpl(cookie, &Callbacks::event);
1101}
1102
1103void DeviceHalAidl::setStreamOutEventCallback(
1104 void* cookie, const sp<StreamOutHalInterfaceEventCallback>& cb) {
1105 setCallbackImpl(cookie, &Callbacks::event, cb);
1106}
1107
1108sp<StreamOutHalInterfaceLatencyModeCallback> DeviceHalAidl::getStreamOutLatencyModeCallback(
1109 void* cookie) {
1110 return getCallbackImpl(cookie, &Callbacks::latency);
1111}
1112
1113void DeviceHalAidl::setStreamOutLatencyModeCallback(
1114 void* cookie, const sp<StreamOutHalInterfaceLatencyModeCallback>& cb) {
1115 setCallbackImpl(cookie, &Callbacks::latency, cb);
1116}
1117
1118template<class C>
1119sp<C> DeviceHalAidl::getCallbackImpl(void* cookie, wp<C> DeviceHalAidl::Callbacks::* field) {
1120 std::lock_guard l(mLock);
1121 if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
1122 return ((it->second).*field).promote();
1123 }
1124 return nullptr;
1125}
1126template<class C>
1127void DeviceHalAidl::setCallbackImpl(
1128 void* cookie, wp<C> DeviceHalAidl::Callbacks::* field, const sp<C>& cb) {
1129 std::lock_guard l(mLock);
1130 if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
1131 (it->second).*field = cb;
1132 }
1133}
1134
Mikhail Naganov31d46652023-01-10 18:29:25 +00001135} // namespace android