blob: 32ebe3659a8189543bf0c3ba0dc1c20bebc3dd21 [file] [log] [blame]
Shunkai Yao51202502022-12-12 06:11:46 +00001/*
2 * Copyright (C) 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "DeviceHalAidl"
Mikhail Naganov89a9f742023-01-30 12:33:18 -080018// #define LOG_NDEBUG 0
Shunkai Yao51202502022-12-12 06:11:46 +000019
Mikhail Naganov5b1eed12023-01-25 11:29:11 -080020#include <algorithm>
21#include <forward_list>
22
Mikhail Naganovdfd594e2023-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 Naganov89a9f742023-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 Naganov5b1eed12023-01-25 11:29:11 -080037using aidl::android::media::audio::common::AudioConfig;
38using aidl::android::media::audio::common::AudioDevice;
Mikhail Naganov89a9f742023-01-30 12:33:18 -080039using aidl::android::media::audio::common::AudioDeviceType;
40using aidl::android::media::audio::common::AudioInputFlags;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -080041using aidl::android::media::audio::common::AudioIoFlags;
Mikhail Naganovdfd594e2023-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 Naganov5b1eed12023-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 Naganov89a9f742023-01-30 12:33:18 -080047using aidl::android::media::audio::common::AudioPortDeviceExt;
Mikhail Naganov5b1eed12023-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 Naganov5b1eed12023-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;
Mikhail Naganov89a9f742023-01-30 12:33:18 -080057using android::hardware::audio::common::getFrameSizeInBytes;
58using android::hardware::audio::common::isBitPositionFlagSet;
59using android::hardware::audio::common::makeBitPositionFlagMask;
Mikhail Naganov31d46652023-01-10 18:29:25 +000060
61namespace android {
62
Mikhail Naganov5b1eed12023-01-25 11:29:11 -080063namespace {
64
65bool isConfigEqualToPortConfig(const AudioConfig& config, const AudioPortConfig& portConfig) {
66 return portConfig.sampleRate.value().value == config.base.sampleRate &&
67 portConfig.channelMask.value() == config.base.channelMask &&
68 portConfig.format.value() == config.base.format;
69}
70
71void setConfigFromPortConfig(AudioConfig* config, const AudioPortConfig& portConfig) {
72 config->base.sampleRate = portConfig.sampleRate.value().value;
73 config->base.channelMask = portConfig.channelMask.value();
74 config->base.format = portConfig.format.value();
75}
76
77void setPortConfigFromConfig(AudioPortConfig* portConfig, const AudioConfig& config) {
78 portConfig->sampleRate = Int{ .value = config.base.sampleRate };
79 portConfig->channelMask = config.base.channelMask;
80 portConfig->format = config.base.format;
81}
82
83} // namespace
84
Mikhail Naganov31d46652023-01-10 18:29:25 +000085status_t DeviceHalAidl::getSupportedDevices(uint32_t*) {
86 // Obsolete.
87 return INVALID_OPERATION;
Shunkai Yao51202502022-12-12 06:11:46 +000088}
89
90status_t DeviceHalAidl::initCheck() {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -080091 TIME_CHECK();
Mikhail Naganov31d46652023-01-10 18:29:25 +000092 if (mModule == nullptr) return NO_INIT;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -080093 std::vector<AudioPort> ports;
94 RETURN_STATUS_IF_ERROR(
95 statusTFromBinderStatus(mModule->getAudioPorts(&ports)));
96 ALOGW_IF(ports.empty(), "%s: module %s returned an empty list of audio ports",
97 __func__, mInstance.c_str());
98 std::transform(ports.begin(), ports.end(), std::inserter(mPorts, mPorts.end()),
99 [](const auto& p) { return std::make_pair(p.id, p); });
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800100 mDefaultInputPortId = mDefaultOutputPortId = -1;
101 const int defaultDeviceFlag = 1 << AudioPortDeviceExt::FLAG_INDEX_DEFAULT_DEVICE;
102 for (const auto& pair : mPorts) {
103 const auto& p = pair.second;
104 if (p.ext.getTag() == AudioPortExt::Tag::device &&
105 (p.ext.get<AudioPortExt::Tag::device>().flags & defaultDeviceFlag) != 0) {
106 if (p.flags.getTag() == AudioIoFlags::Tag::input) {
107 mDefaultInputPortId = p.id;
108 } else if (p.flags.getTag() == AudioIoFlags::Tag::output) {
109 mDefaultOutputPortId = p.id;
110 }
111 }
112 }
113 ALOGI("%s: module %s default port ids: input %d, output %d",
114 __func__, mInstance.c_str(), mDefaultInputPortId, mDefaultOutputPortId);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800115 std::vector<AudioPortConfig> portConfigs;
116 RETURN_STATUS_IF_ERROR(
117 statusTFromBinderStatus(mModule->getAudioPortConfigs(&portConfigs))); // OK if empty
118 std::transform(portConfigs.begin(), portConfigs.end(),
119 std::inserter(mPortConfigs, mPortConfigs.end()),
120 [](const auto& p) { return std::make_pair(p.id, p); });
121 std::vector<AudioPatch> patches;
122 RETURN_STATUS_IF_ERROR(
123 statusTFromBinderStatus(mModule->getAudioPatches(&patches))); // OK if empty
124 std::transform(patches.begin(), patches.end(),
125 std::inserter(mPatches, mPatches.end()),
126 [](const auto& p) { return std::make_pair(p.id, p); });
Shunkai Yao51202502022-12-12 06:11:46 +0000127 return OK;
128}
129
130status_t DeviceHalAidl::setVoiceVolume(float volume) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000131 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000132 if (!mModule) return NO_INIT;
133 std::shared_ptr<ITelephony> telephony;
134 if (ndk::ScopedAStatus status = mModule->getTelephony(&telephony);
135 status.isOk() && telephony != nullptr) {
136 ITelephony::TelecomConfig inConfig{ .voiceVolume = Float{volume} }, outConfig;
137 RETURN_STATUS_IF_ERROR(
138 statusTFromBinderStatus(telephony->setTelecomConfig(inConfig, &outConfig)));
139 ALOGW_IF(outConfig.voiceVolume.has_value() && volume != outConfig.voiceVolume.value().value,
140 "%s: the resulting voice volume %f is not the same as requested %f",
141 __func__, outConfig.voiceVolume.value().value, volume);
142 }
143 return INVALID_OPERATION;
Shunkai Yao51202502022-12-12 06:11:46 +0000144}
145
146status_t DeviceHalAidl::setMasterVolume(float volume) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000147 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000148 if (!mModule) return NO_INIT;
149 return statusTFromBinderStatus(mModule->setMasterVolume(volume));
Shunkai Yao51202502022-12-12 06:11:46 +0000150}
151
152status_t DeviceHalAidl::getMasterVolume(float *volume) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000153 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000154 if (!mModule) return NO_INIT;
155 return statusTFromBinderStatus(mModule->getMasterVolume(volume));
Shunkai Yao51202502022-12-12 06:11:46 +0000156}
157
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000158status_t DeviceHalAidl::setMode(audio_mode_t mode) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000159 TIME_CHECK();
160 if (!mModule) return NO_INIT;
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000161 AudioMode audioMode = VALUE_OR_FATAL(::aidl::android::legacy2aidl_audio_mode_t_AudioMode(mode));
162 std::shared_ptr<ITelephony> telephony;
163 if (ndk::ScopedAStatus status = mModule->getTelephony(&telephony);
164 status.isOk() && telephony != nullptr) {
165 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(telephony->switchAudioMode(audioMode)));
166 }
167 return statusTFromBinderStatus(mModule->updateAudioMode(audioMode));
Shunkai Yao51202502022-12-12 06:11:46 +0000168}
169
170status_t DeviceHalAidl::setMicMute(bool state) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000171 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000172 if (!mModule) return NO_INIT;
173 return statusTFromBinderStatus(mModule->setMicMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000174}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000175
Shunkai Yao51202502022-12-12 06:11:46 +0000176status_t DeviceHalAidl::getMicMute(bool *state) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000177 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000178 if (!mModule) return NO_INIT;
179 return statusTFromBinderStatus(mModule->getMicMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000180}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000181
Shunkai Yao51202502022-12-12 06:11:46 +0000182status_t DeviceHalAidl::setMasterMute(bool state) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000183 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000184 if (!mModule) return NO_INIT;
185 return statusTFromBinderStatus(mModule->setMasterMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000186}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000187
Shunkai Yao51202502022-12-12 06:11:46 +0000188status_t DeviceHalAidl::getMasterMute(bool *state) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000189 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000190 if (!mModule) return NO_INIT;
191 return statusTFromBinderStatus(mModule->getMasterMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000192}
193
Mikhail Naganov31d46652023-01-10 18:29:25 +0000194status_t DeviceHalAidl::setParameters(const String8& kvPairs __unused) {
195 TIME_CHECK();
196 if (!mModule) return NO_INIT;
197 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000198 return OK;
199}
200
Mikhail Naganov31d46652023-01-10 18:29:25 +0000201status_t DeviceHalAidl::getParameters(const String8& keys __unused, String8 *values) {
202 TIME_CHECK();
203 values->clear();
204 if (!mModule) return NO_INIT;
205 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000206 return OK;
207}
208
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800209namespace {
210
211class Cleanup {
212 public:
213 typedef void (DeviceHalAidl::*Cleaner)(int32_t);
214
215 Cleanup(DeviceHalAidl* device, Cleaner cleaner, int32_t id) :
216 mDevice(device), mCleaner(cleaner), mId(id) {}
217 ~Cleanup() { clean(); }
218 void clean() {
219 if (mDevice != nullptr) (mDevice->*mCleaner)(mId);
220 disarm();
221 }
222 void disarm() { mDevice = nullptr; }
223
224 private:
225 DeviceHalAidl* mDevice;
226 const Cleaner mCleaner;
227 const int32_t mId;
228};
229
230} // namespace
231
232// Since the order of container elements destruction is unspecified,
233// ensure that cleanups are performed from the most recent one and upwards.
234// This is the same as if there were individual Cleanup instances on the stack,
235// however the bonus is that we can disarm all of them with just one statement.
236class DeviceHalAidl::Cleanups : public std::forward_list<Cleanup> {
237 public:
238 ~Cleanups() { for (auto& c : *this) c.clean(); }
239 void disarmAll() { for (auto& c : *this) c.disarm(); }
240};
241
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800242status_t DeviceHalAidl::getInputBufferSize(const struct audio_config* config, size_t* size) {
243 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
244 if (size == nullptr) return BAD_VALUE;
245 TIME_CHECK();
246 if (!mModule) return NO_INIT;
247 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
248 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, true /*isInput*/));
249 AudioDevice aidlDevice;
250 aidlDevice.type.type = AudioDeviceType::IN_DEFAULT;
251 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::input>(0);
252 AudioPortConfig mixPortConfig;
253 Cleanups cleanups;
254 audio_config writableConfig = *config;
255 int32_t nominalLatency;
256 RETURN_STATUS_IF_ERROR(prepareToOpenStream(0 /*handle*/, aidlDevice, aidlFlags, &writableConfig,
257 &cleanups, &aidlConfig, &mixPortConfig, &nominalLatency));
258 *size = aidlConfig.frameCount *
259 getFrameSizeInBytes(aidlConfig.base.format, aidlConfig.base.channelMask);
260 // Do not disarm cleanups to release temporary port configs.
261 return OK;
262}
263
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800264status_t DeviceHalAidl::prepareToOpenStream(
265 int32_t aidlHandle, const AudioDevice& aidlDevice, const AudioIoFlags& aidlFlags,
266 struct audio_config* config,
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800267 Cleanups* cleanups, AudioConfig* aidlConfig, AudioPortConfig* mixPortConfig,
268 int32_t* nominalLatency) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800269 const bool isInput = aidlFlags.getTag() == AudioIoFlags::Tag::input;
270 // Find / create AudioPortConfigs for the device port and the mix port,
271 // then find / create a patch between them, and open a stream on the mix port.
272 AudioPortConfig devicePortConfig;
273 bool created = false;
274 RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(aidlDevice, &devicePortConfig, &created));
275 if (created) {
276 cleanups->emplace_front(this, &DeviceHalAidl::resetPortConfig, devicePortConfig.id);
277 }
278 RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(*aidlConfig, aidlFlags, aidlHandle,
279 mixPortConfig, &created));
280 if (created) {
281 cleanups->emplace_front(this, &DeviceHalAidl::resetPortConfig, mixPortConfig->id);
282 }
283 setConfigFromPortConfig(aidlConfig, *mixPortConfig);
284 AudioPatch patch;
285 if (isInput) {
286 RETURN_STATUS_IF_ERROR(findOrCreatePatch(
287 {devicePortConfig.id}, {mixPortConfig->id}, &patch, &created));
288 } else {
289 RETURN_STATUS_IF_ERROR(findOrCreatePatch(
290 {mixPortConfig->id}, {devicePortConfig.id}, &patch, &created));
291 }
292 if (created) {
293 cleanups->emplace_front(this, &DeviceHalAidl::resetPatch, patch.id);
294 }
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800295 *nominalLatency = patch.latenciesMs[0];
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800296 if (aidlConfig->frameCount <= 0) {
297 aidlConfig->frameCount = patch.minimumStreamBufferSizeFrames;
298 }
299 *config = VALUE_OR_RETURN_STATUS(
300 ::aidl::android::aidl2legacy_AudioConfig_audio_config_t(*aidlConfig, isInput));
301 return OK;
302}
303
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800304namespace {
305
306class StreamCallbackBase {
307 protected:
308 explicit StreamCallbackBase(const sp<CallbackBroker>& broker) : mBroker(broker) {}
309 public:
310 void* getCookie() const { return mCookie; }
311 void setCookie(void* cookie) { mCookie = cookie; }
312 sp<CallbackBroker> getBroker() const {
313 if (void* cookie = mCookie; cookie != nullptr) return mBroker.promote();
314 return nullptr;
315 }
316 private:
317 const wp<CallbackBroker> mBroker;
318 std::atomic<void*> mCookie;
319};
320
321template<class C>
322class StreamCallbackBaseHelper {
323 protected:
324 explicit StreamCallbackBaseHelper(const StreamCallbackBase& base) : mBase(base) {}
325 sp<C> getCb(const sp<CallbackBroker>& broker, void* cookie);
326 using CbRef = const sp<C>&;
327 ndk::ScopedAStatus runCb(const std::function<void(CbRef cb)>& f) {
328 if (auto cb = getCb(mBase.getBroker(), mBase.getCookie()); cb != nullptr) f(cb);
329 return ndk::ScopedAStatus::ok();
330 }
331 private:
332 const StreamCallbackBase& mBase;
333};
334
335template<>
336sp<StreamOutHalInterfaceCallback> StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>::getCb(
337 const sp<CallbackBroker>& broker, void* cookie) {
338 if (broker != nullptr) return broker->getStreamOutCallback(cookie);
339 return nullptr;
340}
341
342template<>
343sp<StreamOutHalInterfaceEventCallback>
344StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>::getCb(
345 const sp<CallbackBroker>& broker, void* cookie) {
346 if (broker != nullptr) return broker->getStreamOutEventCallback(cookie);
347 return nullptr;
348}
349
350template<>
351sp<StreamOutHalInterfaceLatencyModeCallback>
352StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>::getCb(
353 const sp<CallbackBroker>& broker, void* cookie) {
354 if (broker != nullptr) return broker->getStreamOutLatencyModeCallback(cookie);
355 return nullptr;
356}
357
358/*
359Note on the callback ownership.
360
361In the Binder ownership model, the server implementation is kept alive
362as long as there is any client (proxy object) alive. This is done by
363incrementing the refcount of the server-side object by the Binder framework.
364When it detects that the last client is gone, it decrements the refcount back.
365
366Thus, it is not needed to keep any references to StreamCallback on our
367side (after we have sent an instance to the client), because we are
368the server-side. The callback object will be kept alive as long as the HAL server
369holds a strong ref to IStreamCallback proxy.
370*/
371
372class OutputStreamCallbackAidl : public StreamCallbackBase,
373 public StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>,
374 public ::aidl::android::hardware::audio::core::BnStreamCallback {
375 public:
376 explicit OutputStreamCallbackAidl(const sp<CallbackBroker>& broker)
377 : StreamCallbackBase(broker),
378 StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>(
379 *static_cast<StreamCallbackBase*>(this)) {}
380 ndk::ScopedAStatus onTransferReady() override {
381 return runCb([](CbRef cb) { cb->onWriteReady(); });
382 }
383 ndk::ScopedAStatus onError() override {
384 return runCb([](CbRef cb) { cb->onError(); });
385 }
386 ndk::ScopedAStatus onDrainReady() override {
387 return runCb([](CbRef cb) { cb->onDrainReady(); });
388 }
389};
390
391class OutputStreamEventCallbackAidl :
392 public StreamCallbackBase,
393 public StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>,
394 public StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>,
395 public ::aidl::android::hardware::audio::core::BnStreamOutEventCallback {
396 public:
397 explicit OutputStreamEventCallbackAidl(const sp<CallbackBroker>& broker)
398 : StreamCallbackBase(broker),
399 StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>(
400 *static_cast<StreamCallbackBase*>(this)),
401 StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>(
402 *static_cast<StreamCallbackBase*>(this)) {}
403 ndk::ScopedAStatus onCodecFormatChanged(const std::vector<uint8_t>& in_audioMetadata) override {
404 std::basic_string<uint8_t> halMetadata(in_audioMetadata.begin(), in_audioMetadata.end());
405 return StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>::runCb(
406 [&halMetadata](auto cb) { cb->onCodecFormatChanged(halMetadata); });
407 }
408 ndk::ScopedAStatus onRecommendedLatencyModeChanged(
409 const std::vector<AudioLatencyMode>& in_modes) override {
410 auto halModes = VALUE_OR_FATAL(
411 ::aidl::android::convertContainer<std::vector<audio_latency_mode_t>>(
412 in_modes,
413 ::aidl::android::aidl2legacy_AudioLatencyMode_audio_latency_mode_t));
414 return StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>::runCb(
415 [&halModes](auto cb) { cb->onRecommendedLatencyModeChanged(halModes); });
416 }
417};
418
419} // namespace
420
Mikhail Naganov31d46652023-01-10 18:29:25 +0000421status_t DeviceHalAidl::openOutputStream(
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800422 audio_io_handle_t handle, audio_devices_t devices,
423 audio_output_flags_t flags, struct audio_config* config,
424 const char* address,
Mikhail Naganov31d46652023-01-10 18:29:25 +0000425 sp<StreamOutHalInterface>* outStream) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800426 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000427 if (!outStream || !config) {
428 return BAD_VALUE;
429 }
430 TIME_CHECK();
431 if (!mModule) return NO_INIT;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800432 int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
433 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(handle));
434 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
435 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, false /*isInput*/));
436 AudioDevice aidlDevice = VALUE_OR_RETURN_STATUS(
437 ::aidl::android::legacy2aidl_audio_device_AudioDevice(devices, address));
438 int32_t aidlOutputFlags = VALUE_OR_RETURN_STATUS(
439 ::aidl::android::legacy2aidl_audio_output_flags_t_int32_t_mask(flags));
440 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::output>(aidlOutputFlags);
441 AudioPortConfig mixPortConfig;
442 Cleanups cleanups;
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800443 int32_t nominalLatency;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800444 RETURN_STATUS_IF_ERROR(prepareToOpenStream(aidlHandle, aidlDevice, aidlFlags, config,
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800445 &cleanups, &aidlConfig, &mixPortConfig, &nominalLatency));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800446 ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamArguments args;
447 args.portConfigId = mixPortConfig.id;
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800448 const bool isOffload = isBitPositionFlagSet(
449 aidlOutputFlags, AudioOutputFlags::COMPRESS_OFFLOAD);
450 std::shared_ptr<OutputStreamCallbackAidl> streamCb;
451 if (isOffload) {
452 streamCb = ndk::SharedRefBase::make<OutputStreamCallbackAidl>(this);
453 }
454 auto eventCb = ndk::SharedRefBase::make<OutputStreamEventCallbackAidl>(this);
455 if (isOffload) {
456 args.offloadInfo = aidlConfig.offloadInfo;
457 args.callback = streamCb;
458 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800459 args.bufferSizeFrames = aidlConfig.frameCount;
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800460 args.eventCallback = eventCb;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800461 ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamReturn ret;
462 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openOutputStream(args, &ret)));
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800463 StreamContextAidl context(ret.desc);
464 if (!context.isValid()) {
465 ALOGE("%s: Failed to created a valid stream context from the descriptor: %s",
466 __func__, ret.desc.toString().c_str());
467 return NO_INIT;
468 }
469 *outStream = sp<StreamOutHalAidl>::make(*config, std::move(context), nominalLatency,
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800470 std::move(ret.stream), this /*callbackBroker*/);
471 void* cbCookie = (*outStream).get();
472 {
473 std::lock_guard l(mLock);
474 mCallbacks.emplace(cbCookie, Callbacks{});
475 }
476 if (streamCb) streamCb->setCookie(cbCookie);
477 eventCb->setCookie(cbCookie);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800478 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000479 return OK;
480}
481
Mikhail Naganov31d46652023-01-10 18:29:25 +0000482status_t DeviceHalAidl::openInputStream(
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800483 audio_io_handle_t handle, audio_devices_t devices,
484 struct audio_config* config, audio_input_flags_t flags,
485 const char* address, audio_source_t source,
486 audio_devices_t outputDevice, const char* outputDeviceAddress,
Mikhail Naganov31d46652023-01-10 18:29:25 +0000487 sp<StreamInHalInterface>* inStream) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800488 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000489 if (!inStream || !config) {
490 return BAD_VALUE;
491 }
492 TIME_CHECK();
493 if (!mModule) return NO_INIT;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800494 int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
495 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(handle));
496 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
497 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, true /*isInput*/));
498 AudioDevice aidlDevice = VALUE_OR_RETURN_STATUS(
499 ::aidl::android::legacy2aidl_audio_device_AudioDevice(devices, address));
500 int32_t aidlInputFlags = VALUE_OR_RETURN_STATUS(
501 ::aidl::android::legacy2aidl_audio_input_flags_t_int32_t_mask(flags));
502 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::input>(aidlInputFlags);
503 AudioSource aidlSource = VALUE_OR_RETURN_STATUS(
504 ::aidl::android::legacy2aidl_audio_source_t_AudioSource(source));
505 AudioPortConfig mixPortConfig;
506 Cleanups cleanups;
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800507 int32_t nominalLatency;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800508 RETURN_STATUS_IF_ERROR(prepareToOpenStream(aidlHandle, aidlDevice, aidlFlags, config,
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800509 &cleanups, &aidlConfig, &mixPortConfig, &nominalLatency));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800510 ::aidl::android::hardware::audio::core::IModule::OpenInputStreamArguments args;
511 args.portConfigId = mixPortConfig.id;
512 RecordTrackMetadata aidlTrackMetadata{
513 .source = aidlSource, .gain = 1, .channelMask = aidlConfig.base.channelMask };
514 if (outputDevice != AUDIO_DEVICE_NONE) {
515 aidlTrackMetadata.destinationDevice = VALUE_OR_RETURN_STATUS(
516 ::aidl::android::legacy2aidl_audio_device_AudioDevice(
517 outputDevice, outputDeviceAddress));
518 }
519 args.sinkMetadata.tracks.push_back(std::move(aidlTrackMetadata));
520 args.bufferSizeFrames = aidlConfig.frameCount;
521 ::aidl::android::hardware::audio::core::IModule::OpenInputStreamReturn ret;
522 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openInputStream(args, &ret)));
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800523 StreamContextAidl context(ret.desc);
524 if (!context.isValid()) {
525 ALOGE("%s: Failed to created a valid stream context from the descriptor: %s",
526 __func__, ret.desc.toString().c_str());
527 return NO_INIT;
528 }
529 *inStream = sp<StreamInHalAidl>::make(*config, std::move(context), nominalLatency,
530 std::move(ret.stream));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800531 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000532 return OK;
533}
534
535status_t DeviceHalAidl::supportsAudioPatches(bool* supportsPatches) {
536 *supportsPatches = true;
537 return OK;
538}
539
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800540status_t DeviceHalAidl::createAudioPatch(unsigned int num_sources,
541 const struct audio_port_config* sources,
542 unsigned int num_sinks,
543 const struct audio_port_config* sinks,
544 audio_patch_handle_t* patch) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800545 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000546 TIME_CHECK();
547 if (!mModule) return NO_INIT;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800548 if (num_sinks > AUDIO_PATCH_PORTS_MAX || num_sources > AUDIO_PATCH_PORTS_MAX ||
549 sources == nullptr || sinks == nullptr || patch == nullptr) {
550 return BAD_VALUE;
551 }
552 // Note that the patch handle (*patch) is provided by the framework.
553 // In tests it's possible that its value is AUDIO_PATCH_HANDLE_NONE.
554
555 // Upon conversion, mix port configs contain audio configuration, while
556 // device port configs contain device address. This data is used to find
557 // or create HAL configs.
558 std::vector<AudioPortConfig> aidlSources, aidlSinks;
559 for (unsigned int i = 0; i < num_sources; ++i) {
560 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
561 sources[i].role, sources[i].type)) ==
562 ::aidl::android::AudioPortDirection::INPUT;
563 aidlSources.push_back(VALUE_OR_RETURN_STATUS(
564 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
565 sources[i], isInput, 0)));
566 }
567 for (unsigned int i = 0; i < num_sinks; ++i) {
568 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
569 sinks[i].role, sinks[i].type)) ==
570 ::aidl::android::AudioPortDirection::INPUT;
571 aidlSinks.push_back(VALUE_OR_RETURN_STATUS(
572 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
573 sinks[i], isInput, 0)));
574 }
575 Cleanups cleanups;
576 auto existingPatchIt = mPatches.end();
577 auto fwkHandlesIt = *patch != AUDIO_PATCH_HANDLE_NONE ?
578 mFwkHandles.find(*patch) : mFwkHandles.end();
579 AudioPatch aidlPatch;
580 if (fwkHandlesIt != mFwkHandles.end()) {
581 existingPatchIt = mPatches.find(fwkHandlesIt->second);
582 if (existingPatchIt != mPatches.end()) {
583 aidlPatch = existingPatchIt->second;
584 aidlPatch.sourcePortConfigIds.clear();
585 aidlPatch.sinkPortConfigIds.clear();
586 }
587 }
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800588 ALOGD("%s: sources: %s, sinks: %s",
589 __func__, ::android::internal::ToString(aidlSources).c_str(),
590 ::android::internal::ToString(aidlSinks).c_str());
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800591 auto fillPortConfigs = [&](
592 const std::vector<AudioPortConfig>& configs, std::vector<int32_t>* ids) -> status_t {
593 for (const auto& s : configs) {
594 AudioPortConfig portConfig;
595 bool created = false;
596 RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(s, &portConfig, &created));
597 if (created) {
598 cleanups.emplace_front(this, &DeviceHalAidl::resetPortConfig, portConfig.id);
599 }
600 ids->push_back(portConfig.id);
601 }
602 return OK;
603 };
604 RETURN_STATUS_IF_ERROR(fillPortConfigs(aidlSources, &aidlPatch.sourcePortConfigIds));
605 RETURN_STATUS_IF_ERROR(fillPortConfigs(aidlSinks, &aidlPatch.sinkPortConfigIds));
606 if (existingPatchIt != mPatches.end()) {
607 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
608 mModule->setAudioPatch(aidlPatch, &aidlPatch)));
609 existingPatchIt->second = aidlPatch;
610 } else {
611 bool created = false;
612 RETURN_STATUS_IF_ERROR(findOrCreatePatch(aidlPatch, &aidlPatch, &created));
613 // Since no cleanup of the patch is needed, 'created' is ignored.
614 if (fwkHandlesIt != mFwkHandles.end()) {
615 fwkHandlesIt->second = aidlPatch.id;
616 // Patch handle (*patch) stays the same.
617 } else {
618 if (*patch == AUDIO_PATCH_HANDLE_NONE) {
619 // This isn't good as the module can't provide a handle which is really unique.
620 // However, this situation should only happen in tests.
621 *patch = aidlPatch.id;
622 LOG_ALWAYS_FATAL_IF(mFwkHandles.count(*patch) > 0,
623 "%s: patch id %d clashes with another framework patch handle",
624 __func__, *patch);
625 }
626 mFwkHandles.emplace(*patch, aidlPatch.id);
627 }
628 }
629 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000630 return OK;
631}
632
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800633status_t DeviceHalAidl::releaseAudioPatch(audio_patch_handle_t patch) {
Mikhail Naganov89a9f742023-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 Naganov5b1eed12023-01-25 11:29:11 -0800637 auto idMapIt = mFwkHandles.find(patch);
638 if (idMapIt == mFwkHandles.end()) {
639 return BAD_VALUE;
640 }
641 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->resetAudioPatch(idMapIt->second)));
642 mFwkHandles.erase(idMapIt);
Shunkai Yao51202502022-12-12 06:11:46 +0000643 return OK;
644}
645
Mikhail Naganov31d46652023-01-10 18:29:25 +0000646status_t DeviceHalAidl::getAudioPort(struct audio_port* port __unused) {
647 TIME_CHECK();
648 ALOGE("%s not implemented yet", __func__);
649 return INVALID_OPERATION;
650}
651
652status_t DeviceHalAidl::getAudioPort(struct audio_port_v7 *port __unused) {
653 TIME_CHECK();
654 ALOGE("%s not implemented yet", __func__);
655 return INVALID_OPERATION;
656}
657
658status_t DeviceHalAidl::setAudioPortConfig(const struct audio_port_config* config __unused) {
659 TIME_CHECK();
660 if (!mModule) return NO_INIT;
661 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000662 return OK;
663}
664
665status_t DeviceHalAidl::getMicrophones(
Mikhail Naganov31d46652023-01-10 18:29:25 +0000666 std::vector<audio_microphone_characteristic_t>* microphones __unused) {
667 TIME_CHECK();
668 if (!mModule) return NO_INIT;
669 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000670 return OK;
671}
672
Mikhail Naganov31d46652023-01-10 18:29:25 +0000673status_t DeviceHalAidl::addDeviceEffect(audio_port_handle_t device __unused,
674 sp<EffectHalInterface> effect) {
Shunkai Yao51202502022-12-12 06:11:46 +0000675 if (!effect) {
676 return BAD_VALUE;
677 }
Mikhail Naganov31d46652023-01-10 18:29:25 +0000678 TIME_CHECK();
679 if (!mModule) return NO_INIT;
680 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000681 return OK;
682}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000683status_t DeviceHalAidl::removeDeviceEffect(audio_port_handle_t device __unused,
Shunkai Yao51202502022-12-12 06:11:46 +0000684 sp<EffectHalInterface> effect) {
685 if (!effect) {
686 return BAD_VALUE;
687 }
Mikhail Naganov31d46652023-01-10 18:29:25 +0000688 TIME_CHECK();
689 if (!mModule) return NO_INIT;
690 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000691 return OK;
692}
693
694status_t DeviceHalAidl::getMmapPolicyInfos(
695 media::audio::common::AudioMMapPolicyType policyType __unused,
696 std::vector<media::audio::common::AudioMMapPolicyInfo>* policyInfos __unused) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000697 TIME_CHECK();
Shunkai Yao51202502022-12-12 06:11:46 +0000698 ALOGE("%s not implemented yet", __func__);
699 return OK;
700}
701
702int32_t DeviceHalAidl::getAAudioMixerBurstCount() {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000703 TIME_CHECK();
Shunkai Yao51202502022-12-12 06:11:46 +0000704 ALOGE("%s not implemented yet", __func__);
705 return OK;
706}
707
708int32_t DeviceHalAidl::getAAudioHardwareBurstMinUsec() {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000709 TIME_CHECK();
Shunkai Yao51202502022-12-12 06:11:46 +0000710 ALOGE("%s not implemented yet", __func__);
711 return OK;
712}
713
714error::Result<audio_hw_sync_t> DeviceHalAidl::getHwAvSync() {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000715 TIME_CHECK();
Shunkai Yao51202502022-12-12 06:11:46 +0000716 ALOGE("%s not implemented yet", __func__);
717 return base::unexpected(INVALID_OPERATION);
718}
719
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000720status_t DeviceHalAidl::dump(int fd, const Vector<String16>& args) {
721 TIME_CHECK();
722 if (!mModule) return NO_INIT;
723 return mModule->dump(fd, Args(args).args(), args.size());
Shunkai Yao51202502022-12-12 06:11:46 +0000724};
725
Mikhail Naganov31d46652023-01-10 18:29:25 +0000726int32_t DeviceHalAidl::supportsBluetoothVariableLatency(bool* supports __unused) {
727 TIME_CHECK();
Shunkai Yao51202502022-12-12 06:11:46 +0000728 ALOGE("%s not implemented yet", __func__);
729 return INVALID_OPERATION;
730}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000731
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800732bool DeviceHalAidl::audioDeviceMatches(const AudioDevice& device, const AudioPort& p) {
733 if (p.ext.getTag() != AudioPortExt::Tag::device) return false;
734 return p.ext.get<AudioPortExt::Tag::device>().device == device;
735}
736
737bool DeviceHalAidl::audioDeviceMatches(const AudioDevice& device, const AudioPortConfig& p) {
738 if (p.ext.getTag() != AudioPortExt::Tag::device) return false;
739 if (device.type.type == AudioDeviceType::IN_DEFAULT) {
740 return p.portId == mDefaultInputPortId;
741 } else if (device.type.type == AudioDeviceType::OUT_DEFAULT) {
742 return p.portId == mDefaultOutputPortId;
743 }
744 return p.ext.get<AudioPortExt::Tag::device>().device == device;
745}
746
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800747status_t DeviceHalAidl::createPortConfig(const AudioPortConfig& requestedPortConfig,
748 AudioPortConfig* appliedPortConfig) {
749 TIME_CHECK();
750 bool applied = false;
751 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPortConfig(
752 requestedPortConfig, appliedPortConfig, &applied)));
753 if (!applied) {
754 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPortConfig(
755 *appliedPortConfig, appliedPortConfig, &applied)));
756 if (!applied) {
757 ALOGE("%s: module %s did not apply suggested config %s",
758 __func__, mInstance.c_str(), appliedPortConfig->toString().c_str());
759 return NO_INIT;
760 }
761 }
762 mPortConfigs.emplace(appliedPortConfig->id, *appliedPortConfig);
763 return OK;
764}
765
766status_t DeviceHalAidl::findOrCreatePatch(
767 const AudioPatch& requestedPatch, AudioPatch* patch, bool* created) {
768 std::set<int32_t> sourcePortConfigIds(requestedPatch.sourcePortConfigIds.begin(),
769 requestedPatch.sourcePortConfigIds.end());
770 std::set<int32_t> sinkPortConfigIds(requestedPatch.sinkPortConfigIds.begin(),
771 requestedPatch.sinkPortConfigIds.end());
772 return findOrCreatePatch(sourcePortConfigIds, sinkPortConfigIds, patch, created);
773}
774
775status_t DeviceHalAidl::findOrCreatePatch(
776 const std::set<int32_t>& sourcePortConfigIds, const std::set<int32_t>& sinkPortConfigIds,
777 AudioPatch* patch, bool* created) {
778 auto patchIt = findPatch(sourcePortConfigIds, sinkPortConfigIds);
779 if (patchIt == mPatches.end()) {
780 TIME_CHECK();
781 AudioPatch requestedPatch, appliedPatch;
782 requestedPatch.sourcePortConfigIds.insert(requestedPatch.sourcePortConfigIds.end(),
783 sourcePortConfigIds.begin(), sourcePortConfigIds.end());
784 requestedPatch.sinkPortConfigIds.insert(requestedPatch.sinkPortConfigIds.end(),
785 sinkPortConfigIds.begin(), sinkPortConfigIds.end());
786 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPatch(
787 requestedPatch, &appliedPatch)));
788 patchIt = mPatches.insert(mPatches.end(), std::make_pair(appliedPatch.id, appliedPatch));
789 *created = true;
790 } else {
791 *created = false;
792 }
793 *patch = patchIt->second;
794 return OK;
795}
796
797status_t DeviceHalAidl::findOrCreatePortConfig(const AudioDevice& device,
798 AudioPortConfig* portConfig, bool* created) {
799 auto portConfigIt = findPortConfig(device);
800 if (portConfigIt == mPortConfigs.end()) {
801 auto portsIt = findPort(device);
802 if (portsIt == mPorts.end()) {
803 ALOGE("%s: device port for device %s is not found in the module %s",
804 __func__, device.toString().c_str(), mInstance.c_str());
805 return BAD_VALUE;
806 }
807 AudioPortConfig requestedPortConfig;
808 requestedPortConfig.portId = portsIt->first;
809 AudioPortConfig appliedPortConfig;
810 RETURN_STATUS_IF_ERROR(createPortConfig(requestedPortConfig, &appliedPortConfig));
811 portConfigIt = mPortConfigs.insert(
812 mPortConfigs.end(), std::make_pair(appliedPortConfig.id, appliedPortConfig));
813 *created = true;
814 } else {
815 *created = false;
816 }
817 *portConfig = portConfigIt->second;
818 return OK;
819}
820
821status_t DeviceHalAidl::findOrCreatePortConfig(
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800822 const AudioConfig& config, const std::optional<AudioIoFlags>& flags, int32_t ioHandle,
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800823 AudioPortConfig* portConfig, bool* created) {
824 auto portConfigIt = findPortConfig(config, flags, ioHandle);
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800825 if (portConfigIt == mPortConfigs.end() && flags.has_value()) {
826 auto portsIt = findPort(config, flags.value());
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800827 if (portsIt == mPorts.end()) {
828 ALOGE("%s: mix port for config %s, flags %s is not found in the module %s",
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800829 __func__, config.toString().c_str(), flags.value().toString().c_str(),
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800830 mInstance.c_str());
831 return BAD_VALUE;
832 }
833 AudioPortConfig requestedPortConfig;
834 requestedPortConfig.portId = portsIt->first;
835 setPortConfigFromConfig(&requestedPortConfig, config);
836 AudioPortConfig appliedPortConfig;
837 RETURN_STATUS_IF_ERROR(createPortConfig(requestedPortConfig, &appliedPortConfig));
838 appliedPortConfig.ext.get<AudioPortExt::Tag::mix>().handle = ioHandle;
839 portConfigIt = mPortConfigs.insert(
840 mPortConfigs.end(), std::make_pair(appliedPortConfig.id, appliedPortConfig));
841 *created = true;
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800842 } else if (!flags.has_value()) {
843 ALOGW("%s: mix port config for %s, handle %d not found in the module %s, "
844 "and was not created as flags are not specified",
845 __func__, config.toString().c_str(), ioHandle, mInstance.c_str());
846 return BAD_VALUE;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800847 } else {
848 *created = false;
849 }
850 *portConfig = portConfigIt->second;
851 return OK;
852}
853
854status_t DeviceHalAidl::findOrCreatePortConfig(
855 const AudioPortConfig& requestedPortConfig, AudioPortConfig* portConfig, bool* created) {
856 using Tag = AudioPortExt::Tag;
857 if (requestedPortConfig.ext.getTag() == Tag::mix) {
858 if (const auto& p = requestedPortConfig;
859 !p.sampleRate.has_value() || !p.channelMask.has_value() ||
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800860 !p.format.has_value()) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800861 ALOGW("%s: provided mix port config is not fully specified: %s",
862 __func__, p.toString().c_str());
863 return BAD_VALUE;
864 }
865 AudioConfig config;
866 setConfigFromPortConfig(&config, requestedPortConfig);
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800867 return findOrCreatePortConfig(config, requestedPortConfig.flags,
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800868 requestedPortConfig.ext.get<Tag::mix>().handle, portConfig, created);
869 } else if (requestedPortConfig.ext.getTag() == Tag::device) {
870 return findOrCreatePortConfig(
871 requestedPortConfig.ext.get<Tag::device>().device, portConfig, created);
872 }
873 ALOGW("%s: unsupported audio port config: %s",
874 __func__, requestedPortConfig.toString().c_str());
875 return BAD_VALUE;
876}
877
878DeviceHalAidl::Patches::iterator DeviceHalAidl::findPatch(
879 const std::set<int32_t>& sourcePortConfigIds, const std::set<int32_t>& sinkPortConfigIds) {
880 return std::find_if(mPatches.begin(), mPatches.end(),
881 [&](const auto& pair) {
882 const auto& p = pair.second;
883 std::set<int32_t> patchSrcs(
884 p.sourcePortConfigIds.begin(), p.sourcePortConfigIds.end());
885 std::set<int32_t> patchSinks(
886 p.sinkPortConfigIds.begin(), p.sinkPortConfigIds.end());
887 return sourcePortConfigIds == patchSrcs && sinkPortConfigIds == patchSinks; });
888}
889
890DeviceHalAidl::Ports::iterator DeviceHalAidl::findPort(const AudioDevice& device) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800891 if (device.type.type == AudioDeviceType::IN_DEFAULT) {
892 return mPorts.find(mDefaultInputPortId);
893 } else if (device.type.type == AudioDeviceType::OUT_DEFAULT) {
894 return mPorts.find(mDefaultOutputPortId);
895 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800896 return std::find_if(mPorts.begin(), mPorts.end(),
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800897 [&](const auto& pair) { return audioDeviceMatches(device, pair.second); });
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800898}
899
900DeviceHalAidl::Ports::iterator DeviceHalAidl::findPort(
901 const AudioConfig& config, const AudioIoFlags& flags) {
902 using Tag = AudioPortExt::Tag;
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800903 AudioIoFlags matchFlags = flags;
904 auto matcher = [&](const auto& pair) {
905 const auto& p = pair.second;
906 return p.ext.getTag() == Tag::mix &&
907 p.flags == matchFlags &&
908 std::find_if(p.profiles.begin(), p.profiles.end(),
909 [&](const auto& prof) {
910 return prof.format == config.base.format &&
911 std::find(prof.channelMasks.begin(), prof.channelMasks.end(),
912 config.base.channelMask) != prof.channelMasks.end() &&
913 std::find(prof.sampleRates.begin(), prof.sampleRates.end(),
914 config.base.sampleRate) != prof.sampleRates.end();
915 }) != p.profiles.end(); };
916 auto it = std::find_if(mPorts.begin(), mPorts.end(), matcher);
917 if (it == mPorts.end() && flags.getTag() == AudioIoFlags::Tag::input &&
918 isBitPositionFlagSet(flags.get<AudioIoFlags::Tag::input>(), AudioInputFlags::FAST)) {
919 // "Fast" input is not a mandatory flag, try without it.
920 matchFlags.set<AudioIoFlags::Tag::input>(flags.get<AudioIoFlags::Tag::input>() &
921 ~makeBitPositionFlagMask(AudioInputFlags::FAST));
922 it = std::find_if(mPorts.begin(), mPorts.end(), matcher);
923 }
924 return it;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800925}
926
927DeviceHalAidl::PortConfigs::iterator DeviceHalAidl::findPortConfig(const AudioDevice& device) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800928 return std::find_if(mPortConfigs.begin(), mPortConfigs.end(),
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800929 [&](const auto& pair) { return audioDeviceMatches(device, pair.second); });
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800930}
931
932DeviceHalAidl::PortConfigs::iterator DeviceHalAidl::findPortConfig(
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800933 const AudioConfig& config, const std::optional<AudioIoFlags>& flags, int32_t ioHandle) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800934 using Tag = AudioPortExt::Tag;
935 return std::find_if(mPortConfigs.begin(), mPortConfigs.end(),
936 [&](const auto& pair) {
937 const auto& p = pair.second;
938 LOG_ALWAYS_FATAL_IF(p.ext.getTag() == Tag::mix &&
939 !p.sampleRate.has_value() || !p.channelMask.has_value() ||
940 !p.format.has_value() || !p.flags.has_value(),
941 "%s: stored mix port config is not fully specified: %s",
942 __func__, p.toString().c_str());
943 return p.ext.getTag() == Tag::mix &&
944 isConfigEqualToPortConfig(config, p) &&
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800945 (!flags.has_value() || p.flags.value() == flags.value()) &&
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800946 p.ext.template get<Tag::mix>().handle == ioHandle; });
947}
948/*
949DeviceHalAidl::PortConfigs::iterator DeviceHalAidl::findPortConfig(
950 const AudioPortConfig& portConfig) {
951 using Tag = AudioPortExt::Tag;
952 if (portConfig.ext.getTag() == Tag::mix) {
953 return std::find_if(mPortConfigs.begin(), mPortConfigs.end(),
954 [&](const auto& pair) {
955 const auto& p = pair.second;
956 LOG_ALWAYS_FATAL_IF(p.ext.getTag() == Tag::mix &&
957 !p.sampleRate.has_value() || !p.channelMask.has_value() ||
958 !p.format.has_value() || !p.flags.has_value(),
959 "%s: stored mix port config is not fully specified: %s",
960 __func__, p.toString().c_str());
961 return p.ext.getTag() == Tag::mix &&
962 (!portConfig.sampleRate.has_value() ||
963 p.sampleRate == portConfig.sampleRate) &&
964 (!portConfig.channelMask.has_value() ||
965 p.channelMask == portConfig.channelMask) &&
966 (!portConfig.format.has_value() || p.format == portConfig.format) &&
967 (!portConfig.flags.has_value() || p.flags == portConfig.flags) &&
968 p.ext.template get<Tag::mix>().handle ==
969 portConfig.ext.template get<Tag::mix>().handle; });
970 } else if (portConfig.ext.getTag() == Tag::device) {
971 return findPortConfig(portConfig.ext.get<Tag::device>().device);
972 }
973 return mPortConfigs.end();
974}
975*/
976void DeviceHalAidl::resetPatch(int32_t patchId) {
977 if (auto it = mPatches.find(patchId); it != mPatches.end()) {
978 mPatches.erase(it);
979 TIME_CHECK();
980 if (ndk::ScopedAStatus status = mModule->resetAudioPatch(patchId); !status.isOk()) {
981 ALOGE("%s: error while resetting patch %d: %s",
982 __func__, patchId, status.getDescription().c_str());
983 }
984 return;
985 }
986 ALOGE("%s: patch id %d not found", __func__, patchId);
987}
988
989void DeviceHalAidl::resetPortConfig(int32_t portConfigId) {
990 if (auto it = mPortConfigs.find(portConfigId); it != mPortConfigs.end()) {
991 mPortConfigs.erase(it);
992 TIME_CHECK();
993 if (ndk::ScopedAStatus status = mModule->resetAudioPortConfig(portConfigId);
994 !status.isOk()) {
995 ALOGE("%s: error while resetting port config %d: %s",
996 __func__, portConfigId, status.getDescription().c_str());
997 }
998 return;
999 }
1000 ALOGE("%s: port config id %d not found", __func__, portConfigId);
1001}
1002
Mikhail Naganovdfd594e2023-02-08 16:59:41 -08001003void DeviceHalAidl::clearCallbacks(void* cookie) {
1004 std::lock_guard l(mLock);
1005 mCallbacks.erase(cookie);
1006}
1007
1008sp<StreamOutHalInterfaceCallback> DeviceHalAidl::getStreamOutCallback(void* cookie) {
1009 return getCallbackImpl(cookie, &Callbacks::out);
1010}
1011
1012void DeviceHalAidl::setStreamOutCallback(
1013 void* cookie, const sp<StreamOutHalInterfaceCallback>& cb) {
1014 setCallbackImpl(cookie, &Callbacks::out, cb);
1015}
1016
1017sp<StreamOutHalInterfaceEventCallback> DeviceHalAidl::getStreamOutEventCallback(
1018 void* cookie) {
1019 return getCallbackImpl(cookie, &Callbacks::event);
1020}
1021
1022void DeviceHalAidl::setStreamOutEventCallback(
1023 void* cookie, const sp<StreamOutHalInterfaceEventCallback>& cb) {
1024 setCallbackImpl(cookie, &Callbacks::event, cb);
1025}
1026
1027sp<StreamOutHalInterfaceLatencyModeCallback> DeviceHalAidl::getStreamOutLatencyModeCallback(
1028 void* cookie) {
1029 return getCallbackImpl(cookie, &Callbacks::latency);
1030}
1031
1032void DeviceHalAidl::setStreamOutLatencyModeCallback(
1033 void* cookie, const sp<StreamOutHalInterfaceLatencyModeCallback>& cb) {
1034 setCallbackImpl(cookie, &Callbacks::latency, cb);
1035}
1036
1037template<class C>
1038sp<C> DeviceHalAidl::getCallbackImpl(void* cookie, wp<C> DeviceHalAidl::Callbacks::* field) {
1039 std::lock_guard l(mLock);
1040 if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
1041 return ((it->second).*field).promote();
1042 }
1043 return nullptr;
1044}
1045template<class C>
1046void DeviceHalAidl::setCallbackImpl(
1047 void* cookie, wp<C> DeviceHalAidl::Callbacks::* field, const sp<C>& cb) {
1048 std::lock_guard l(mLock);
1049 if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
1050 (it->second).*field = cb;
1051 }
1052}
1053
Mikhail Naganov31d46652023-01-10 18:29:25 +00001054} // namespace android