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