blob: cd17068ed520bafacea6a742ccd59f7fb0f76754 [file] [log] [blame]
Shunkai Yao51202502022-12-12 06:11:46 +00001/*
2 * Copyright (C) 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "DeviceHalAidl"
Vlad Popa03bd5bc2023-01-17 16:16:51 +010018// #define LOG_NDEBUG 0
Shunkai Yao51202502022-12-12 06:11:46 +000019
Mikhail Naganovf56ce782023-01-25 11:29:11 -080020#include <algorithm>
21#include <forward_list>
22
Mikhail Naganovb0c55252023-02-08 16:59:41 -080023#include <aidl/android/hardware/audio/core/BnStreamCallback.h>
24#include <aidl/android/hardware/audio/core/BnStreamOutEventCallback.h>
Mikhail Naganovfab697c2023-01-11 19:33:13 +000025#include <aidl/android/hardware/audio/core/StreamDescriptor.h>
26#include <error/expected_utils.h>
27#include <media/AidlConversionCppNdk.h>
Mikhail Naganovbfbb75b2023-04-21 18:48:16 -070028#include <media/AidlConversionNdkCpp.h>
Mikhail Naganovfab697c2023-01-11 19:33:13 +000029#include <media/AidlConversionUtil.h>
Mikhail Naganov31d46652023-01-10 18:29:25 +000030#include <mediautils/TimeCheck.h>
Mikhail Naganov8bd806e2023-01-30 12:33:18 -080031#include <Utils.h>
Mikhail Naganov31d46652023-01-10 18:29:25 +000032#include <utils/Log.h>
Shunkai Yao51202502022-12-12 06:11:46 +000033
Mikhail Naganov31d46652023-01-10 18:29:25 +000034#include "DeviceHalAidl.h"
35#include "StreamHalAidl.h"
36
Mikhail Naganovfab697c2023-01-11 19:33:13 +000037using aidl::android::aidl_utils::statusTFromBinderStatus;
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -070038using aidl::android::media::audio::common::AudioChannelLayout;
Mikhail Naganovf56ce782023-01-25 11:29:11 -080039using aidl::android::media::audio::common::AudioConfig;
40using aidl::android::media::audio::common::AudioDevice;
David Li9cf5e622023-03-21 00:51:10 +080041using aidl::android::media::audio::common::AudioDeviceAddress;
Mikhail Naganov8bd806e2023-01-30 12:33:18 -080042using aidl::android::media::audio::common::AudioDeviceType;
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -070043using aidl::android::media::audio::common::AudioFormatType;
Mikhail Naganov8bd806e2023-01-30 12:33:18 -080044using aidl::android::media::audio::common::AudioInputFlags;
Mikhail Naganovf56ce782023-01-25 11:29:11 -080045using aidl::android::media::audio::common::AudioIoFlags;
Mikhail Naganovb0c55252023-02-08 16:59:41 -080046using aidl::android::media::audio::common::AudioLatencyMode;
David Li9cf5e622023-03-21 00:51:10 +080047using aidl::android::media::audio::common::AudioMMapPolicy;
48using aidl::android::media::audio::common::AudioMMapPolicyInfo;
49using aidl::android::media::audio::common::AudioMMapPolicyType;
Mikhail Naganovfab697c2023-01-11 19:33:13 +000050using aidl::android::media::audio::common::AudioMode;
Mikhail Naganovf56ce782023-01-25 11:29:11 -080051using aidl::android::media::audio::common::AudioOutputFlags;
52using aidl::android::media::audio::common::AudioPort;
53using aidl::android::media::audio::common::AudioPortConfig;
Mikhail Naganov8bd806e2023-01-30 12:33:18 -080054using aidl::android::media::audio::common::AudioPortDeviceExt;
David Li9cf5e622023-03-21 00:51:10 +080055using aidl::android::media::audio::common::AudioPortExt;
Mikhail Naganov1a44bc62023-02-16 17:35:06 -080056using aidl::android::media::audio::common::AudioPortMixExt;
Mikhail Naganovd8d01f72023-03-09 16:24:40 -080057using aidl::android::media::audio::common::AudioPortMixExtUseCase;
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -070058using aidl::android::media::audio::common::AudioProfile;
Mikhail Naganovf56ce782023-01-25 11:29:11 -080059using aidl::android::media::audio::common::AudioSource;
Mikhail Naganovfab697c2023-01-11 19:33:13 +000060using aidl::android::media::audio::common::Float;
David Li9cf5e622023-03-21 00:51:10 +080061using aidl::android::media::audio::common::Int;
62using aidl::android::media::audio::common::MicrophoneDynamicInfo;
63using aidl::android::media::audio::common::MicrophoneInfo;
Mikhail Naganov6352e822023-03-09 18:22:36 -080064using aidl::android::hardware::audio::common::getFrameSizeInBytes;
65using aidl::android::hardware::audio::common::isBitPositionFlagSet;
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -070066using aidl::android::hardware::audio::common::isDefaultAudioFormat;
Mikhail Naganov6352e822023-03-09 18:22:36 -080067using aidl::android::hardware::audio::common::makeBitPositionFlagMask;
Mikhail Naganovf56ce782023-01-25 11:29:11 -080068using aidl::android::hardware::audio::common::RecordTrackMetadata;
69using aidl::android::hardware::audio::core::AudioPatch;
Mikhail Naganovecfafb72023-03-29 10:06:15 -070070using aidl::android::hardware::audio::core::AudioRoute;
Mikhail Naganovfab697c2023-01-11 19:33:13 +000071using aidl::android::hardware::audio::core::IModule;
72using aidl::android::hardware::audio::core::ITelephony;
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -070073using aidl::android::hardware::audio::core::ModuleDebug;
Mikhail Naganovfab697c2023-01-11 19:33:13 +000074using aidl::android::hardware::audio::core::StreamDescriptor;
Mikhail Naganov31d46652023-01-10 18:29:25 +000075
76namespace android {
77
Mikhail Naganovf56ce782023-01-25 11:29:11 -080078namespace {
79
80bool isConfigEqualToPortConfig(const AudioConfig& config, const AudioPortConfig& portConfig) {
81 return portConfig.sampleRate.value().value == config.base.sampleRate &&
82 portConfig.channelMask.value() == config.base.channelMask &&
83 portConfig.format.value() == config.base.format;
84}
85
86void setConfigFromPortConfig(AudioConfig* config, const AudioPortConfig& portConfig) {
87 config->base.sampleRate = portConfig.sampleRate.value().value;
88 config->base.channelMask = portConfig.channelMask.value();
89 config->base.format = portConfig.format.value();
90}
91
92void setPortConfigFromConfig(AudioPortConfig* portConfig, const AudioConfig& config) {
93 portConfig->sampleRate = Int{ .value = config.base.sampleRate };
94 portConfig->channelMask = config.base.channelMask;
95 portConfig->format = config.base.format;
96}
97
98} // namespace
99
Mikhail Naganov31d46652023-01-10 18:29:25 +0000100status_t DeviceHalAidl::getSupportedDevices(uint32_t*) {
101 // Obsolete.
102 return INVALID_OPERATION;
Shunkai Yao51202502022-12-12 06:11:46 +0000103}
104
105status_t DeviceHalAidl::initCheck() {
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800106 TIME_CHECK();
Mikhail Naganov31d46652023-01-10 18:29:25 +0000107 if (mModule == nullptr) return NO_INIT;
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800108 std::vector<AudioPort> ports;
109 RETURN_STATUS_IF_ERROR(
110 statusTFromBinderStatus(mModule->getAudioPorts(&ports)));
111 ALOGW_IF(ports.empty(), "%s: module %s returned an empty list of audio ports",
112 __func__, mInstance.c_str());
113 std::transform(ports.begin(), ports.end(), std::inserter(mPorts, mPorts.end()),
114 [](const auto& p) { return std::make_pair(p.id, p); });
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800115 mDefaultInputPortId = mDefaultOutputPortId = -1;
116 const int defaultDeviceFlag = 1 << AudioPortDeviceExt::FLAG_INDEX_DEFAULT_DEVICE;
117 for (const auto& pair : mPorts) {
118 const auto& p = pair.second;
119 if (p.ext.getTag() == AudioPortExt::Tag::device &&
120 (p.ext.get<AudioPortExt::Tag::device>().flags & defaultDeviceFlag) != 0) {
121 if (p.flags.getTag() == AudioIoFlags::Tag::input) {
122 mDefaultInputPortId = p.id;
123 } else if (p.flags.getTag() == AudioIoFlags::Tag::output) {
124 mDefaultOutputPortId = p.id;
125 }
126 }
127 }
128 ALOGI("%s: module %s default port ids: input %d, output %d",
129 __func__, mInstance.c_str(), mDefaultInputPortId, mDefaultOutputPortId);
Mikhail Naganovecfafb72023-03-29 10:06:15 -0700130 RETURN_STATUS_IF_ERROR(updateRoutes());
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800131 std::vector<AudioPortConfig> portConfigs;
132 RETURN_STATUS_IF_ERROR(
133 statusTFromBinderStatus(mModule->getAudioPortConfigs(&portConfigs))); // OK if empty
134 std::transform(portConfigs.begin(), portConfigs.end(),
135 std::inserter(mPortConfigs, mPortConfigs.end()),
136 [](const auto& p) { return std::make_pair(p.id, p); });
jiabin2248fa12023-04-27 22:04:16 +0000137 std::transform(mPortConfigs.begin(), mPortConfigs.end(),
138 std::inserter(mInitialPortConfigIds, mInitialPortConfigIds.end()),
139 [](const auto& pcPair) { return pcPair.first; });
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800140 std::vector<AudioPatch> patches;
141 RETURN_STATUS_IF_ERROR(
142 statusTFromBinderStatus(mModule->getAudioPatches(&patches))); // OK if empty
143 std::transform(patches.begin(), patches.end(),
144 std::inserter(mPatches, mPatches.end()),
145 [](const auto& p) { return std::make_pair(p.id, p); });
Shunkai Yao51202502022-12-12 06:11:46 +0000146 return OK;
147}
148
149status_t DeviceHalAidl::setVoiceVolume(float volume) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000150 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000151 if (!mModule) return NO_INIT;
152 std::shared_ptr<ITelephony> telephony;
153 if (ndk::ScopedAStatus status = mModule->getTelephony(&telephony);
154 status.isOk() && telephony != nullptr) {
155 ITelephony::TelecomConfig inConfig{ .voiceVolume = Float{volume} }, outConfig;
156 RETURN_STATUS_IF_ERROR(
157 statusTFromBinderStatus(telephony->setTelecomConfig(inConfig, &outConfig)));
158 ALOGW_IF(outConfig.voiceVolume.has_value() && volume != outConfig.voiceVolume.value().value,
159 "%s: the resulting voice volume %f is not the same as requested %f",
160 __func__, outConfig.voiceVolume.value().value, volume);
161 }
162 return INVALID_OPERATION;
Shunkai Yao51202502022-12-12 06:11:46 +0000163}
164
165status_t DeviceHalAidl::setMasterVolume(float volume) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000166 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000167 if (!mModule) return NO_INIT;
168 return statusTFromBinderStatus(mModule->setMasterVolume(volume));
Shunkai Yao51202502022-12-12 06:11:46 +0000169}
170
171status_t DeviceHalAidl::getMasterVolume(float *volume) {
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->getMasterVolume(volume));
Shunkai Yao51202502022-12-12 06:11:46 +0000175}
176
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000177status_t DeviceHalAidl::setMode(audio_mode_t mode) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000178 TIME_CHECK();
179 if (!mModule) return NO_INIT;
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000180 AudioMode audioMode = VALUE_OR_FATAL(::aidl::android::legacy2aidl_audio_mode_t_AudioMode(mode));
181 std::shared_ptr<ITelephony> telephony;
182 if (ndk::ScopedAStatus status = mModule->getTelephony(&telephony);
183 status.isOk() && telephony != nullptr) {
184 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(telephony->switchAudioMode(audioMode)));
185 }
186 return statusTFromBinderStatus(mModule->updateAudioMode(audioMode));
Shunkai Yao51202502022-12-12 06:11:46 +0000187}
188
189status_t DeviceHalAidl::setMicMute(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->setMicMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000193}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000194
Shunkai Yao51202502022-12-12 06:11:46 +0000195status_t DeviceHalAidl::getMicMute(bool *state) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000196 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000197 if (!mModule) return NO_INIT;
198 return statusTFromBinderStatus(mModule->getMicMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000199}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000200
Shunkai Yao51202502022-12-12 06:11:46 +0000201status_t DeviceHalAidl::setMasterMute(bool state) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000202 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000203 if (!mModule) return NO_INIT;
204 return statusTFromBinderStatus(mModule->setMasterMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000205}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000206
Shunkai Yao51202502022-12-12 06:11:46 +0000207status_t DeviceHalAidl::getMasterMute(bool *state) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000208 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000209 if (!mModule) return NO_INIT;
210 return statusTFromBinderStatus(mModule->getMasterMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000211}
212
Mikhail Naganov31d46652023-01-10 18:29:25 +0000213status_t DeviceHalAidl::setParameters(const String8& kvPairs __unused) {
214 TIME_CHECK();
215 if (!mModule) return NO_INIT;
216 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000217 return OK;
218}
219
Mikhail Naganov31d46652023-01-10 18:29:25 +0000220status_t DeviceHalAidl::getParameters(const String8& keys __unused, String8 *values) {
221 TIME_CHECK();
222 values->clear();
223 if (!mModule) return NO_INIT;
224 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000225 return OK;
226}
227
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800228namespace {
229
230class Cleanup {
231 public:
232 typedef void (DeviceHalAidl::*Cleaner)(int32_t);
233
234 Cleanup(DeviceHalAidl* device, Cleaner cleaner, int32_t id) :
235 mDevice(device), mCleaner(cleaner), mId(id) {}
236 ~Cleanup() { clean(); }
237 void clean() {
238 if (mDevice != nullptr) (mDevice->*mCleaner)(mId);
239 disarm();
240 }
241 void disarm() { mDevice = nullptr; }
242
243 private:
244 DeviceHalAidl* mDevice;
245 const Cleaner mCleaner;
246 const int32_t mId;
247};
248
249} // namespace
250
251// Since the order of container elements destruction is unspecified,
252// ensure that cleanups are performed from the most recent one and upwards.
253// This is the same as if there were individual Cleanup instances on the stack,
254// however the bonus is that we can disarm all of them with just one statement.
255class DeviceHalAidl::Cleanups : public std::forward_list<Cleanup> {
256 public:
257 ~Cleanups() { for (auto& c : *this) c.clean(); }
258 void disarmAll() { for (auto& c : *this) c.disarm(); }
259};
260
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800261status_t DeviceHalAidl::getInputBufferSize(const struct audio_config* config, size_t* size) {
262 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
263 if (size == nullptr) return BAD_VALUE;
264 TIME_CHECK();
265 if (!mModule) return NO_INIT;
266 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
267 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, true /*isInput*/));
268 AudioDevice aidlDevice;
269 aidlDevice.type.type = AudioDeviceType::IN_DEFAULT;
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800270 AudioSource aidlSource = AudioSource::DEFAULT;
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800271 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::input>(0);
272 AudioPortConfig mixPortConfig;
273 Cleanups cleanups;
274 audio_config writableConfig = *config;
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700275 AudioPatch aidlPatch;
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800276 RETURN_STATUS_IF_ERROR(prepareToOpenStream(0 /*handle*/, aidlDevice, aidlFlags, aidlSource,
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700277 &writableConfig, &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800278 *size = aidlConfig.frameCount *
279 getFrameSizeInBytes(aidlConfig.base.format, aidlConfig.base.channelMask);
280 // Do not disarm cleanups to release temporary port configs.
281 return OK;
282}
283
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800284status_t DeviceHalAidl::prepareToOpenStream(
285 int32_t aidlHandle, const AudioDevice& aidlDevice, const AudioIoFlags& aidlFlags,
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800286 AudioSource aidlSource, struct audio_config* config,
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800287 Cleanups* cleanups, AudioConfig* aidlConfig, AudioPortConfig* mixPortConfig,
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700288 AudioPatch* aidlPatch) {
289 ALOGD("%p %s::%s: handle %d, device %s, flags %s, source %s, config %s, mix port config %s",
290 this, getClassName().c_str(), __func__, aidlHandle, aidlDevice.toString().c_str(),
291 aidlFlags.toString().c_str(), toString(aidlSource).c_str(),
292 aidlConfig->toString().c_str(), mixPortConfig->toString().c_str());
jiabin2248fa12023-04-27 22:04:16 +0000293 resetUnusedPatchesAndPortConfigs();
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800294 const bool isInput = aidlFlags.getTag() == AudioIoFlags::Tag::input;
295 // Find / create AudioPortConfigs for the device port and the mix port,
296 // then find / create a patch between them, and open a stream on the mix port.
297 AudioPortConfig devicePortConfig;
298 bool created = false;
jiabin2248fa12023-04-27 22:04:16 +0000299 RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(aidlDevice, aidlConfig,
300 &devicePortConfig, &created));
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800301 if (created) {
302 cleanups->emplace_front(this, &DeviceHalAidl::resetPortConfig, devicePortConfig.id);
303 }
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800304 RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(*aidlConfig, aidlFlags, aidlHandle, aidlSource,
Mikhail Naganovecfafb72023-03-29 10:06:15 -0700305 std::set<int32_t>{devicePortConfig.portId}, mixPortConfig, &created));
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800306 if (created) {
307 cleanups->emplace_front(this, &DeviceHalAidl::resetPortConfig, mixPortConfig->id);
308 }
309 setConfigFromPortConfig(aidlConfig, *mixPortConfig);
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800310 if (isInput) {
311 RETURN_STATUS_IF_ERROR(findOrCreatePatch(
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700312 {devicePortConfig.id}, {mixPortConfig->id}, aidlPatch, &created));
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800313 } else {
314 RETURN_STATUS_IF_ERROR(findOrCreatePatch(
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700315 {mixPortConfig->id}, {devicePortConfig.id}, aidlPatch, &created));
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800316 }
317 if (created) {
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700318 cleanups->emplace_front(this, &DeviceHalAidl::resetPatch, aidlPatch->id);
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800319 }
320 if (aidlConfig->frameCount <= 0) {
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700321 aidlConfig->frameCount = aidlPatch->minimumStreamBufferSizeFrames;
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800322 }
323 *config = VALUE_OR_RETURN_STATUS(
324 ::aidl::android::aidl2legacy_AudioConfig_audio_config_t(*aidlConfig, isInput));
325 return OK;
326}
327
Mikhail Naganovb0c55252023-02-08 16:59:41 -0800328namespace {
329
330class StreamCallbackBase {
331 protected:
332 explicit StreamCallbackBase(const sp<CallbackBroker>& broker) : mBroker(broker) {}
333 public:
334 void* getCookie() const { return mCookie; }
335 void setCookie(void* cookie) { mCookie = cookie; }
336 sp<CallbackBroker> getBroker() const {
337 if (void* cookie = mCookie; cookie != nullptr) return mBroker.promote();
338 return nullptr;
339 }
340 private:
341 const wp<CallbackBroker> mBroker;
342 std::atomic<void*> mCookie;
343};
344
345template<class C>
346class StreamCallbackBaseHelper {
347 protected:
348 explicit StreamCallbackBaseHelper(const StreamCallbackBase& base) : mBase(base) {}
349 sp<C> getCb(const sp<CallbackBroker>& broker, void* cookie);
350 using CbRef = const sp<C>&;
351 ndk::ScopedAStatus runCb(const std::function<void(CbRef cb)>& f) {
352 if (auto cb = getCb(mBase.getBroker(), mBase.getCookie()); cb != nullptr) f(cb);
353 return ndk::ScopedAStatus::ok();
354 }
355 private:
356 const StreamCallbackBase& mBase;
357};
358
359template<>
360sp<StreamOutHalInterfaceCallback> StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>::getCb(
361 const sp<CallbackBroker>& broker, void* cookie) {
362 if (broker != nullptr) return broker->getStreamOutCallback(cookie);
363 return nullptr;
364}
365
366template<>
367sp<StreamOutHalInterfaceEventCallback>
368StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>::getCb(
369 const sp<CallbackBroker>& broker, void* cookie) {
370 if (broker != nullptr) return broker->getStreamOutEventCallback(cookie);
371 return nullptr;
372}
373
374template<>
375sp<StreamOutHalInterfaceLatencyModeCallback>
376StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>::getCb(
377 const sp<CallbackBroker>& broker, void* cookie) {
378 if (broker != nullptr) return broker->getStreamOutLatencyModeCallback(cookie);
379 return nullptr;
380}
381
382/*
383Note on the callback ownership.
384
385In the Binder ownership model, the server implementation is kept alive
386as long as there is any client (proxy object) alive. This is done by
387incrementing the refcount of the server-side object by the Binder framework.
388When it detects that the last client is gone, it decrements the refcount back.
389
390Thus, it is not needed to keep any references to StreamCallback on our
391side (after we have sent an instance to the client), because we are
392the server-side. The callback object will be kept alive as long as the HAL server
393holds a strong ref to IStreamCallback proxy.
394*/
395
396class OutputStreamCallbackAidl : public StreamCallbackBase,
397 public StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>,
398 public ::aidl::android::hardware::audio::core::BnStreamCallback {
399 public:
400 explicit OutputStreamCallbackAidl(const sp<CallbackBroker>& broker)
401 : StreamCallbackBase(broker),
402 StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>(
403 *static_cast<StreamCallbackBase*>(this)) {}
404 ndk::ScopedAStatus onTransferReady() override {
405 return runCb([](CbRef cb) { cb->onWriteReady(); });
406 }
407 ndk::ScopedAStatus onError() override {
408 return runCb([](CbRef cb) { cb->onError(); });
409 }
410 ndk::ScopedAStatus onDrainReady() override {
411 return runCb([](CbRef cb) { cb->onDrainReady(); });
412 }
413};
414
415class OutputStreamEventCallbackAidl :
416 public StreamCallbackBase,
417 public StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>,
418 public StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>,
419 public ::aidl::android::hardware::audio::core::BnStreamOutEventCallback {
420 public:
421 explicit OutputStreamEventCallbackAidl(const sp<CallbackBroker>& broker)
422 : StreamCallbackBase(broker),
423 StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>(
424 *static_cast<StreamCallbackBase*>(this)),
425 StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>(
426 *static_cast<StreamCallbackBase*>(this)) {}
427 ndk::ScopedAStatus onCodecFormatChanged(const std::vector<uint8_t>& in_audioMetadata) override {
428 std::basic_string<uint8_t> halMetadata(in_audioMetadata.begin(), in_audioMetadata.end());
429 return StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>::runCb(
430 [&halMetadata](auto cb) { cb->onCodecFormatChanged(halMetadata); });
431 }
432 ndk::ScopedAStatus onRecommendedLatencyModeChanged(
433 const std::vector<AudioLatencyMode>& in_modes) override {
434 auto halModes = VALUE_OR_FATAL(
435 ::aidl::android::convertContainer<std::vector<audio_latency_mode_t>>(
436 in_modes,
437 ::aidl::android::aidl2legacy_AudioLatencyMode_audio_latency_mode_t));
438 return StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>::runCb(
439 [&halModes](auto cb) { cb->onRecommendedLatencyModeChanged(halModes); });
440 }
441};
442
443} // namespace
444
Mikhail Naganov31d46652023-01-10 18:29:25 +0000445status_t DeviceHalAidl::openOutputStream(
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800446 audio_io_handle_t handle, audio_devices_t devices,
447 audio_output_flags_t flags, struct audio_config* config,
448 const char* address,
Mikhail Naganov31d46652023-01-10 18:29:25 +0000449 sp<StreamOutHalInterface>* outStream) {
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800450 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000451 if (!outStream || !config) {
452 return BAD_VALUE;
453 }
454 TIME_CHECK();
455 if (!mModule) return NO_INIT;
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800456 int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
457 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(handle));
458 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
459 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, false /*isInput*/));
460 AudioDevice aidlDevice = VALUE_OR_RETURN_STATUS(
461 ::aidl::android::legacy2aidl_audio_device_AudioDevice(devices, address));
462 int32_t aidlOutputFlags = VALUE_OR_RETURN_STATUS(
463 ::aidl::android::legacy2aidl_audio_output_flags_t_int32_t_mask(flags));
464 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::output>(aidlOutputFlags);
465 AudioPortConfig mixPortConfig;
466 Cleanups cleanups;
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700467 AudioPatch aidlPatch;
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800468 RETURN_STATUS_IF_ERROR(prepareToOpenStream(aidlHandle, aidlDevice, aidlFlags,
469 AudioSource::SYS_RESERVED_INVALID /*only needed for input*/,
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700470 config, &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800471 ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamArguments args;
472 args.portConfigId = mixPortConfig.id;
Mikhail Naganovb0c55252023-02-08 16:59:41 -0800473 const bool isOffload = isBitPositionFlagSet(
474 aidlOutputFlags, AudioOutputFlags::COMPRESS_OFFLOAD);
475 std::shared_ptr<OutputStreamCallbackAidl> streamCb;
476 if (isOffload) {
477 streamCb = ndk::SharedRefBase::make<OutputStreamCallbackAidl>(this);
478 }
479 auto eventCb = ndk::SharedRefBase::make<OutputStreamEventCallbackAidl>(this);
480 if (isOffload) {
481 args.offloadInfo = aidlConfig.offloadInfo;
482 args.callback = streamCb;
483 }
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800484 args.bufferSizeFrames = aidlConfig.frameCount;
Mikhail Naganovb0c55252023-02-08 16:59:41 -0800485 args.eventCallback = eventCb;
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800486 ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamReturn ret;
487 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openOutputStream(args, &ret)));
Mikhail Naganov712d71b2023-02-23 17:57:16 -0800488 StreamContextAidl context(ret.desc, isOffload);
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800489 if (!context.isValid()) {
490 ALOGE("%s: Failed to created a valid stream context from the descriptor: %s",
491 __func__, ret.desc.toString().c_str());
492 return NO_INIT;
493 }
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700494 *outStream = sp<StreamOutHalAidl>::make(*config, std::move(context), aidlPatch.latenciesMs[0],
Mikhail Naganovb0c55252023-02-08 16:59:41 -0800495 std::move(ret.stream), this /*callbackBroker*/);
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700496 mStreams.insert(std::pair(*outStream, aidlPatch.id));
Mikhail Naganovb0c55252023-02-08 16:59:41 -0800497 void* cbCookie = (*outStream).get();
498 {
499 std::lock_guard l(mLock);
500 mCallbacks.emplace(cbCookie, Callbacks{});
501 }
502 if (streamCb) streamCb->setCookie(cbCookie);
503 eventCb->setCookie(cbCookie);
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800504 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000505 return OK;
506}
507
Mikhail Naganov31d46652023-01-10 18:29:25 +0000508status_t DeviceHalAidl::openInputStream(
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800509 audio_io_handle_t handle, audio_devices_t devices,
510 struct audio_config* config, audio_input_flags_t flags,
511 const char* address, audio_source_t source,
512 audio_devices_t outputDevice, const char* outputDeviceAddress,
Mikhail Naganov31d46652023-01-10 18:29:25 +0000513 sp<StreamInHalInterface>* inStream) {
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800514 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000515 if (!inStream || !config) {
516 return BAD_VALUE;
517 }
518 TIME_CHECK();
519 if (!mModule) return NO_INIT;
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800520 int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
521 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(handle));
522 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
523 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, true /*isInput*/));
524 AudioDevice aidlDevice = VALUE_OR_RETURN_STATUS(
525 ::aidl::android::legacy2aidl_audio_device_AudioDevice(devices, address));
526 int32_t aidlInputFlags = VALUE_OR_RETURN_STATUS(
527 ::aidl::android::legacy2aidl_audio_input_flags_t_int32_t_mask(flags));
528 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::input>(aidlInputFlags);
529 AudioSource aidlSource = VALUE_OR_RETURN_STATUS(
530 ::aidl::android::legacy2aidl_audio_source_t_AudioSource(source));
531 AudioPortConfig mixPortConfig;
532 Cleanups cleanups;
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700533 AudioPatch aidlPatch;
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800534 RETURN_STATUS_IF_ERROR(prepareToOpenStream(aidlHandle, aidlDevice, aidlFlags, aidlSource,
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700535 config, &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800536 ::aidl::android::hardware::audio::core::IModule::OpenInputStreamArguments args;
537 args.portConfigId = mixPortConfig.id;
538 RecordTrackMetadata aidlTrackMetadata{
539 .source = aidlSource, .gain = 1, .channelMask = aidlConfig.base.channelMask };
540 if (outputDevice != AUDIO_DEVICE_NONE) {
541 aidlTrackMetadata.destinationDevice = VALUE_OR_RETURN_STATUS(
542 ::aidl::android::legacy2aidl_audio_device_AudioDevice(
543 outputDevice, outputDeviceAddress));
544 }
545 args.sinkMetadata.tracks.push_back(std::move(aidlTrackMetadata));
546 args.bufferSizeFrames = aidlConfig.frameCount;
547 ::aidl::android::hardware::audio::core::IModule::OpenInputStreamReturn ret;
548 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openInputStream(args, &ret)));
Mikhail Naganov712d71b2023-02-23 17:57:16 -0800549 StreamContextAidl context(ret.desc, false /*isAsynchronous*/);
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800550 if (!context.isValid()) {
551 ALOGE("%s: Failed to created a valid stream context from the descriptor: %s",
552 __func__, ret.desc.toString().c_str());
553 return NO_INIT;
554 }
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700555 *inStream = sp<StreamInHalAidl>::make(*config, std::move(context), aidlPatch.latenciesMs[0],
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800556 std::move(ret.stream), this /*micInfoProvider*/);
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700557 mStreams.insert(std::pair(*inStream, aidlPatch.id));
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800558 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000559 return OK;
560}
561
562status_t DeviceHalAidl::supportsAudioPatches(bool* supportsPatches) {
563 *supportsPatches = true;
564 return OK;
565}
566
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800567status_t DeviceHalAidl::createAudioPatch(unsigned int num_sources,
568 const struct audio_port_config* sources,
569 unsigned int num_sinks,
570 const struct audio_port_config* sinks,
571 audio_patch_handle_t* patch) {
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800572 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000573 TIME_CHECK();
574 if (!mModule) return NO_INIT;
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800575 if (num_sinks > AUDIO_PATCH_PORTS_MAX || num_sources > AUDIO_PATCH_PORTS_MAX ||
576 sources == nullptr || sinks == nullptr || patch == nullptr) {
577 return BAD_VALUE;
578 }
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800579 // When the patch handle (*patch) is AUDIO_PATCH_HANDLE_NONE, it means
580 // the framework wants to create a new patch. The handle has to be generated
581 // by the HAL. Since handles generated this way can only be unique within
582 // a HAL module, the framework generates a globally unique handle, and maps
583 // it on the <HAL module, patch handle> pair.
584 // When the patch handle is set, it meant the framework intends to update
585 // an existing patch.
586 //
587 // This behavior corresponds to HAL module behavior, with the only difference
588 // that the HAL module uses `int32_t` for patch IDs. The following assert ensures
589 // that both the framework and the HAL use the same value for "no ID":
590 static_assert(AUDIO_PATCH_HANDLE_NONE == 0);
591 int32_t halPatchId = static_cast<int32_t>(*patch);
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800592
593 // Upon conversion, mix port configs contain audio configuration, while
594 // device port configs contain device address. This data is used to find
595 // or create HAL configs.
596 std::vector<AudioPortConfig> aidlSources, aidlSinks;
597 for (unsigned int i = 0; i < num_sources; ++i) {
598 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
599 sources[i].role, sources[i].type)) ==
600 ::aidl::android::AudioPortDirection::INPUT;
601 aidlSources.push_back(VALUE_OR_RETURN_STATUS(
602 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
603 sources[i], isInput, 0)));
604 }
605 for (unsigned int i = 0; i < num_sinks; ++i) {
606 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
607 sinks[i].role, sinks[i].type)) ==
608 ::aidl::android::AudioPortDirection::INPUT;
609 aidlSinks.push_back(VALUE_OR_RETURN_STATUS(
610 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
611 sinks[i], isInput, 0)));
612 }
613 Cleanups cleanups;
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800614 auto existingPatchIt = halPatchId != 0 ? mPatches.find(halPatchId): mPatches.end();
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800615 AudioPatch aidlPatch;
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800616 if (existingPatchIt != mPatches.end()) {
617 aidlPatch = existingPatchIt->second;
618 aidlPatch.sourcePortConfigIds.clear();
619 aidlPatch.sinkPortConfigIds.clear();
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800620 }
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800621 ALOGD("%s: sources: %s, sinks: %s",
622 __func__, ::android::internal::ToString(aidlSources).c_str(),
623 ::android::internal::ToString(aidlSinks).c_str());
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800624 auto fillPortConfigs = [&](
Mikhail Naganovecfafb72023-03-29 10:06:15 -0700625 const std::vector<AudioPortConfig>& configs,
626 const std::set<int32_t>& destinationPortIds,
627 std::vector<int32_t>* ids, std::set<int32_t>* portIds) -> status_t {
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800628 for (const auto& s : configs) {
629 AudioPortConfig portConfig;
630 bool created = false;
Mikhail Naganovecfafb72023-03-29 10:06:15 -0700631 RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(
632 s, destinationPortIds, &portConfig, &created));
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800633 if (created) {
634 cleanups.emplace_front(this, &DeviceHalAidl::resetPortConfig, portConfig.id);
635 }
636 ids->push_back(portConfig.id);
Mikhail Naganovecfafb72023-03-29 10:06:15 -0700637 if (portIds != nullptr) {
638 portIds->insert(portConfig.portId);
639 }
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800640 }
641 return OK;
642 };
Mikhail Naganovecfafb72023-03-29 10:06:15 -0700643 // When looking up port configs, the destinationPortId is only used for mix ports.
644 // Thus, we process device port configs first, and look up the destination port ID from them.
645 bool sourceIsDevice = std::any_of(aidlSources.begin(), aidlSources.end(),
646 [](const auto& config) { return config.ext.getTag() == AudioPortExt::device; });
647 const std::vector<AudioPortConfig>& devicePortConfigs =
648 sourceIsDevice ? aidlSources : aidlSinks;
649 std::vector<int32_t>* devicePortConfigIds =
650 sourceIsDevice ? &aidlPatch.sourcePortConfigIds : &aidlPatch.sinkPortConfigIds;
651 const std::vector<AudioPortConfig>& mixPortConfigs =
652 sourceIsDevice ? aidlSinks : aidlSources;
653 std::vector<int32_t>* mixPortConfigIds =
654 sourceIsDevice ? &aidlPatch.sinkPortConfigIds : &aidlPatch.sourcePortConfigIds;
655 std::set<int32_t> devicePortIds;
656 RETURN_STATUS_IF_ERROR(fillPortConfigs(
657 devicePortConfigs, std::set<int32_t>(), devicePortConfigIds, &devicePortIds));
658 RETURN_STATUS_IF_ERROR(fillPortConfigs(
659 mixPortConfigs, devicePortIds, mixPortConfigIds, nullptr));
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800660 if (existingPatchIt != mPatches.end()) {
661 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
662 mModule->setAudioPatch(aidlPatch, &aidlPatch)));
663 existingPatchIt->second = aidlPatch;
664 } else {
665 bool created = false;
666 RETURN_STATUS_IF_ERROR(findOrCreatePatch(aidlPatch, &aidlPatch, &created));
667 // Since no cleanup of the patch is needed, 'created' is ignored.
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800668 halPatchId = aidlPatch.id;
669 *patch = static_cast<audio_patch_handle_t>(halPatchId);
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800670 }
671 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000672 return OK;
673}
674
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800675status_t DeviceHalAidl::releaseAudioPatch(audio_patch_handle_t patch) {
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800676 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000677 TIME_CHECK();
678 if (!mModule) return NO_INIT;
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800679 static_assert(AUDIO_PATCH_HANDLE_NONE == 0);
680 if (patch == AUDIO_PATCH_HANDLE_NONE) {
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800681 return BAD_VALUE;
682 }
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800683 int32_t halPatchId = static_cast<int32_t>(patch);
684 auto patchIt = mPatches.find(halPatchId);
685 if (patchIt == mPatches.end()) {
686 ALOGE("%s: patch with id %d not found", __func__, halPatchId);
687 return BAD_VALUE;
688 }
689 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->resetAudioPatch(halPatchId)));
690 mPatches.erase(patchIt);
Shunkai Yao51202502022-12-12 06:11:46 +0000691 return OK;
692}
693
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700694status_t DeviceHalAidl::getAudioPort(struct audio_port* port) {
695 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000696 TIME_CHECK();
697 if (!mModule) return NO_INIT;
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700698 if (port == nullptr) {
699 return BAD_VALUE;
700 }
701 audio_port_v7 portV7;
702 audio_populate_audio_port_v7(port, &portV7);
703 RETURN_STATUS_IF_ERROR(getAudioPort(&portV7));
704 return audio_populate_audio_port(&portV7, port) ? OK : BAD_VALUE;
705}
706
707status_t DeviceHalAidl::getAudioPort(struct audio_port_v7 *port) {
708 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
709 TIME_CHECK();
710 if (!mModule) return NO_INIT;
711 if (port == nullptr) {
712 return BAD_VALUE;
713 }
714 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(port->role, port->type)) ==
715 ::aidl::android::AudioPortDirection::INPUT;
716 auto aidlPort = VALUE_OR_RETURN_STATUS(
717 ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
718 if (aidlPort.ext.getTag() != AudioPortExt::device) {
719 ALOGE("%s: provided port is not a device port (module %s): %s",
720 __func__, mInstance.c_str(), aidlPort.toString().c_str());
721 return BAD_VALUE;
722 }
723 const auto& matchDevice = aidlPort.ext.get<AudioPortExt::device>().device;
724 // It seems that we don't have to call HAL since all valid ports have been added either
725 // during initialization, or while handling connection of an external device.
726 auto portsIt = findPort(matchDevice);
727 if (portsIt == mPorts.end()) {
728 ALOGE("%s: device port for device %s is not found in the module %s",
729 __func__, matchDevice.toString().c_str(), mInstance.c_str());
730 return BAD_VALUE;
731 }
732 const int32_t fwkId = aidlPort.id;
733 aidlPort = portsIt->second;
734 aidlPort.id = fwkId;
735 *port = VALUE_OR_RETURN_STATUS(::aidl::android::aidl2legacy_AudioPort_audio_port_v7(
736 aidlPort, isInput));
737 return OK;
738}
739
740status_t DeviceHalAidl::setAudioPortConfig(const struct audio_port_config* config) {
741 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
742 TIME_CHECK();
743 if (!mModule) return NO_INIT;
744 if (config == nullptr) {
745 return BAD_VALUE;
746 }
747 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
748 config->role, config->type)) == ::aidl::android::AudioPortDirection::INPUT;
749 AudioPortConfig requestedPortConfig = VALUE_OR_RETURN_STATUS(
750 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
751 *config, isInput, 0 /*portId*/));
752 AudioPortConfig portConfig;
753 bool created = false;
Mikhail Naganovecfafb72023-03-29 10:06:15 -0700754 RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(
755 requestedPortConfig, std::set<int32_t>(), &portConfig, &created));
Shunkai Yao51202502022-12-12 06:11:46 +0000756 return OK;
757}
758
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800759MicrophoneInfoProvider::Info const* DeviceHalAidl::getMicrophoneInfo() {
760 if (mMicrophones.status == Microphones::Status::UNKNOWN) {
761 TIME_CHECK();
762 std::vector<MicrophoneInfo> aidlInfo;
763 status_t status = statusTFromBinderStatus(mModule->getMicrophones(&aidlInfo));
764 if (status == OK) {
765 mMicrophones.status = Microphones::Status::QUERIED;
766 mMicrophones.info = std::move(aidlInfo);
767 } else if (status == INVALID_OPERATION) {
768 mMicrophones.status = Microphones::Status::NOT_SUPPORTED;
769 } else {
770 ALOGE("%s: Unexpected status from 'IModule.getMicrophones': %d", __func__, status);
771 return {};
772 }
773 }
774 if (mMicrophones.status == Microphones::Status::QUERIED) {
775 return &mMicrophones.info;
776 }
777 return {}; // NOT_SUPPORTED
778}
779
Shunkai Yao51202502022-12-12 06:11:46 +0000780status_t DeviceHalAidl::getMicrophones(
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800781 std::vector<audio_microphone_characteristic_t>* microphones) {
782 if (!microphones) {
783 return BAD_VALUE;
784 }
Mikhail Naganov31d46652023-01-10 18:29:25 +0000785 TIME_CHECK();
786 if (!mModule) return NO_INIT;
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800787 auto staticInfo = getMicrophoneInfo();
788 if (!staticInfo) return INVALID_OPERATION;
789 std::vector<MicrophoneDynamicInfo> emptyDynamicInfo;
790 emptyDynamicInfo.reserve(staticInfo->size());
791 std::transform(staticInfo->begin(), staticInfo->end(), std::back_inserter(emptyDynamicInfo),
792 [](const auto& info) { return MicrophoneDynamicInfo{ .id = info.id }; });
793 *microphones = VALUE_OR_RETURN_STATUS(
794 ::aidl::android::convertContainers<std::vector<audio_microphone_characteristic_t>>(
795 *staticInfo, emptyDynamicInfo,
796 ::aidl::android::aidl2legacy_MicrophoneInfos_audio_microphone_characteristic_t)
797 );
Shunkai Yao51202502022-12-12 06:11:46 +0000798 return OK;
799}
800
Mikhail Naganov31d46652023-01-10 18:29:25 +0000801status_t DeviceHalAidl::addDeviceEffect(audio_port_handle_t device __unused,
802 sp<EffectHalInterface> effect) {
Shunkai Yao51202502022-12-12 06:11:46 +0000803 if (!effect) {
804 return BAD_VALUE;
805 }
Mikhail Naganov31d46652023-01-10 18:29:25 +0000806 TIME_CHECK();
807 if (!mModule) return NO_INIT;
808 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000809 return OK;
810}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000811status_t DeviceHalAidl::removeDeviceEffect(audio_port_handle_t device __unused,
Shunkai Yao51202502022-12-12 06:11:46 +0000812 sp<EffectHalInterface> effect) {
813 if (!effect) {
814 return BAD_VALUE;
815 }
Mikhail Naganov31d46652023-01-10 18:29:25 +0000816 TIME_CHECK();
817 if (!mModule) return NO_INIT;
818 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000819 return OK;
820}
821
822status_t DeviceHalAidl::getMmapPolicyInfos(
David Li9cf5e622023-03-21 00:51:10 +0800823 media::audio::common::AudioMMapPolicyType policyType,
824 std::vector<media::audio::common::AudioMMapPolicyInfo>* policyInfos) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000825 TIME_CHECK();
Mikhail Naganovbfbb75b2023-04-21 18:48:16 -0700826 AudioMMapPolicyType mmapPolicyType = VALUE_OR_RETURN_STATUS(
827 cpp2ndk_AudioMMapPolicyType(policyType));
David Li9cf5e622023-03-21 00:51:10 +0800828
829 std::vector<AudioMMapPolicyInfo> mmapPolicyInfos;
830
831 if (status_t status = statusTFromBinderStatus(
832 mModule->getMmapPolicyInfos(mmapPolicyType, &mmapPolicyInfos)); status != OK) {
833 return status;
834 }
835
836 *policyInfos = VALUE_OR_RETURN_STATUS(
837 convertContainer<std::vector<media::audio::common::AudioMMapPolicyInfo>>(
838 mmapPolicyInfos, ndk2cpp_AudioMMapPolicyInfo));
Shunkai Yao51202502022-12-12 06:11:46 +0000839 return OK;
840}
841
842int32_t DeviceHalAidl::getAAudioMixerBurstCount() {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000843 TIME_CHECK();
David Li9cf5e622023-03-21 00:51:10 +0800844 int32_t mixerBurstCount = 0;
845 if (mModule->getAAudioMixerBurstCount(&mixerBurstCount).isOk()) {
846 return mixerBurstCount;
847 }
848 return 0;
Shunkai Yao51202502022-12-12 06:11:46 +0000849}
850
851int32_t DeviceHalAidl::getAAudioHardwareBurstMinUsec() {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000852 TIME_CHECK();
David Li9cf5e622023-03-21 00:51:10 +0800853 int32_t hardwareBurstMinUsec = 0;
854 if (mModule->getAAudioHardwareBurstMinUsec(&hardwareBurstMinUsec).isOk()) {
855 return hardwareBurstMinUsec;
856 }
857 return 0;
Shunkai Yao51202502022-12-12 06:11:46 +0000858}
859
860error::Result<audio_hw_sync_t> DeviceHalAidl::getHwAvSync() {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000861 TIME_CHECK();
Mikhail Naganov08a62ab2023-03-14 17:11:51 -0700862 if (!mModule) return NO_INIT;
863 int32_t aidlHwAvSync;
864 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->generateHwAvSyncId(&aidlHwAvSync)));
865 return VALUE_OR_RETURN_STATUS(
866 ::aidl::android::aidl2legacy_int32_t_audio_hw_sync_t(aidlHwAvSync));
Shunkai Yao51202502022-12-12 06:11:46 +0000867}
868
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000869status_t DeviceHalAidl::dump(int fd, const Vector<String16>& args) {
870 TIME_CHECK();
871 if (!mModule) return NO_INIT;
872 return mModule->dump(fd, Args(args).args(), args.size());
David Li9cf5e622023-03-21 00:51:10 +0800873}
Shunkai Yao51202502022-12-12 06:11:46 +0000874
Mikhail Naganov3ac95c92023-04-12 13:14:30 -0700875int32_t DeviceHalAidl::supportsBluetoothVariableLatency(bool* supports) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000876 TIME_CHECK();
Mikhail Naganov3ac95c92023-04-12 13:14:30 -0700877 if (!mModule) return NO_INIT;
878 if (supports == nullptr) {
879 return BAD_VALUE;
880 }
881 return statusTFromBinderStatus(mModule->supportsVariableLatency(supports));
Shunkai Yao51202502022-12-12 06:11:46 +0000882}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000883
Vlad Popa03bd5bc2023-01-17 16:16:51 +0100884status_t DeviceHalAidl::getSoundDoseInterface(const std::string& module,
885 ::ndk::SpAIBinder* soundDoseBinder) {
886 TIME_CHECK();
887 if (!mModule) return NO_INIT;
888 if (mSoundDose == nullptr) {
889 ndk::ScopedAStatus status = mModule->getSoundDose(&mSoundDose);
890 if (!status.isOk()) {
891 ALOGE("%s failed to return the sound dose interface for module %s: %s",
892 __func__,
893 module.c_str(),
894 status.getDescription().c_str());
895 return BAD_VALUE;
896 }
897 }
898 *soundDoseBinder = mSoundDose->asBinder();
899 ALOGI("%s using audio AIDL HAL sound dose interface", __func__);
900
901 return OK;
902}
903
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700904status_t DeviceHalAidl::setConnectedState(const struct audio_port_v7 *port, bool connected) {
905 TIME_CHECK();
906 if (!mModule) return NO_INIT;
907 if (port == nullptr) {
908 return BAD_VALUE;
909 }
910 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(port->role, port->type)) ==
911 ::aidl::android::AudioPortDirection::INPUT;
912 AudioPort aidlPort = VALUE_OR_RETURN_STATUS(
913 ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
914 if (aidlPort.ext.getTag() != AudioPortExt::device) {
915 ALOGE("%s: provided port is not a device port (module %s): %s",
916 __func__, mInstance.c_str(), aidlPort.toString().c_str());
917 return BAD_VALUE;
918 }
919 if (connected) {
920 AudioDevice matchDevice = aidlPort.ext.get<AudioPortExt::device>().device;
921 // Reset the device address to find the "template" port.
922 matchDevice.address = AudioDeviceAddress::make<AudioDeviceAddress::id>();
923 auto portsIt = findPort(matchDevice);
924 if (portsIt == mPorts.end()) {
925 ALOGW("%s: device port for device %s is not found in the module %s",
926 __func__, matchDevice.toString().c_str(), mInstance.c_str());
927 return BAD_VALUE;
928 }
929 // Use the ID of the "template" port, use all the information from the provided port.
930 aidlPort.id = portsIt->first;
931 AudioPort connectedPort;
932 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->connectExternalDevice(
933 aidlPort, &connectedPort)));
934 const auto [it, inserted] = mPorts.insert(std::make_pair(connectedPort.id, connectedPort));
935 LOG_ALWAYS_FATAL_IF(!inserted,
936 "%s: module %s, duplicate port ID received from HAL: %s, existing port: %s",
937 __func__, mInstance.c_str(), connectedPort.toString().c_str(),
938 it->second.toString().c_str());
939 } else { // !connected
940 AudioDevice matchDevice = aidlPort.ext.get<AudioPortExt::device>().device;
941 auto portsIt = findPort(matchDevice);
942 if (portsIt == mPorts.end()) {
943 ALOGW("%s: device port for device %s is not found in the module %s",
944 __func__, matchDevice.toString().c_str(), mInstance.c_str());
945 return BAD_VALUE;
946 }
947 // Any streams opened on the external device must be closed by this time,
948 // thus we can clean up patches and port configs that were created for them.
949 resetUnusedPatchesAndPortConfigs();
950 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->disconnectExternalDevice(
951 portsIt->second.id)));
952 mPorts.erase(portsIt);
953 }
Mikhail Naganovecfafb72023-03-29 10:06:15 -0700954 return updateRoutes();
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700955}
956
957status_t DeviceHalAidl::setSimulateDeviceConnections(bool enabled) {
958 TIME_CHECK();
959 if (!mModule) return NO_INIT;
960 ModuleDebug debug{ .simulateDeviceConnections = enabled };
961 status_t status = statusTFromBinderStatus(mModule->setModuleDebug(debug));
962 // This is important to log as it affects HAL behavior.
963 if (status == OK) {
964 ALOGI("%s: set enabled: %d", __func__, enabled);
965 } else {
966 ALOGW("%s: set enabled to %d failed: %d", __func__, enabled, status);
967 }
968 return status;
969}
970
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800971bool DeviceHalAidl::audioDeviceMatches(const AudioDevice& device, const AudioPort& p) {
972 if (p.ext.getTag() != AudioPortExt::Tag::device) return false;
973 return p.ext.get<AudioPortExt::Tag::device>().device == device;
974}
975
976bool DeviceHalAidl::audioDeviceMatches(const AudioDevice& device, const AudioPortConfig& p) {
977 if (p.ext.getTag() != AudioPortExt::Tag::device) return false;
978 if (device.type.type == AudioDeviceType::IN_DEFAULT) {
979 return p.portId == mDefaultInputPortId;
980 } else if (device.type.type == AudioDeviceType::OUT_DEFAULT) {
981 return p.portId == mDefaultOutputPortId;
982 }
983 return p.ext.get<AudioPortExt::Tag::device>().device == device;
984}
985
David Lia8f1e582023-03-30 21:08:06 +0800986status_t DeviceHalAidl::createOrUpdatePortConfig(
987 const AudioPortConfig& requestedPortConfig, PortConfigs::iterator* result, bool* created) {
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800988 TIME_CHECK();
Mikhail Naganov1a44bc62023-02-16 17:35:06 -0800989 AudioPortConfig appliedPortConfig;
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800990 bool applied = false;
991 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPortConfig(
Mikhail Naganov1a44bc62023-02-16 17:35:06 -0800992 requestedPortConfig, &appliedPortConfig, &applied)));
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800993 if (!applied) {
994 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPortConfig(
Mikhail Naganov1a44bc62023-02-16 17:35:06 -0800995 appliedPortConfig, &appliedPortConfig, &applied)));
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800996 if (!applied) {
997 ALOGE("%s: module %s did not apply suggested config %s",
Mikhail Naganov1a44bc62023-02-16 17:35:06 -0800998 __func__, mInstance.c_str(), appliedPortConfig.toString().c_str());
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800999 return NO_INIT;
1000 }
1001 }
David Lia8f1e582023-03-30 21:08:06 +08001002
1003 int32_t id = appliedPortConfig.id;
1004 if (requestedPortConfig.id != 0 && requestedPortConfig.id != id) {
1005 LOG_ALWAYS_FATAL("%s: requested port config id %d changed to %d", __func__,
1006 requestedPortConfig.id, id);
1007 }
1008
1009 auto [it, inserted] = mPortConfigs.insert_or_assign(std::move(id),
1010 std::move(appliedPortConfig));
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001011 *result = it;
David Lia8f1e582023-03-30 21:08:06 +08001012 *created = inserted;
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001013 return OK;
1014}
1015
1016status_t DeviceHalAidl::findOrCreatePatch(
1017 const AudioPatch& requestedPatch, AudioPatch* patch, bool* created) {
1018 std::set<int32_t> sourcePortConfigIds(requestedPatch.sourcePortConfigIds.begin(),
1019 requestedPatch.sourcePortConfigIds.end());
1020 std::set<int32_t> sinkPortConfigIds(requestedPatch.sinkPortConfigIds.begin(),
1021 requestedPatch.sinkPortConfigIds.end());
1022 return findOrCreatePatch(sourcePortConfigIds, sinkPortConfigIds, patch, created);
1023}
1024
1025status_t DeviceHalAidl::findOrCreatePatch(
1026 const std::set<int32_t>& sourcePortConfigIds, const std::set<int32_t>& sinkPortConfigIds,
1027 AudioPatch* patch, bool* created) {
1028 auto patchIt = findPatch(sourcePortConfigIds, sinkPortConfigIds);
1029 if (patchIt == mPatches.end()) {
1030 TIME_CHECK();
1031 AudioPatch requestedPatch, appliedPatch;
1032 requestedPatch.sourcePortConfigIds.insert(requestedPatch.sourcePortConfigIds.end(),
1033 sourcePortConfigIds.begin(), sourcePortConfigIds.end());
1034 requestedPatch.sinkPortConfigIds.insert(requestedPatch.sinkPortConfigIds.end(),
1035 sinkPortConfigIds.begin(), sinkPortConfigIds.end());
1036 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPatch(
1037 requestedPatch, &appliedPatch)));
1038 patchIt = mPatches.insert(mPatches.end(), std::make_pair(appliedPatch.id, appliedPatch));
1039 *created = true;
1040 } else {
1041 *created = false;
1042 }
1043 *patch = patchIt->second;
1044 return OK;
1045}
1046
jiabin2248fa12023-04-27 22:04:16 +00001047status_t DeviceHalAidl::findOrCreatePortConfig(const AudioDevice& device, const AudioConfig* config,
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001048 AudioPortConfig* portConfig, bool* created) {
1049 auto portConfigIt = findPortConfig(device);
1050 if (portConfigIt == mPortConfigs.end()) {
1051 auto portsIt = findPort(device);
1052 if (portsIt == mPorts.end()) {
1053 ALOGE("%s: device port for device %s is not found in the module %s",
1054 __func__, device.toString().c_str(), mInstance.c_str());
1055 return BAD_VALUE;
1056 }
1057 AudioPortConfig requestedPortConfig;
1058 requestedPortConfig.portId = portsIt->first;
jiabin2248fa12023-04-27 22:04:16 +00001059 if (config != nullptr) {
1060 setPortConfigFromConfig(&requestedPortConfig, *config);
1061 }
David Lia8f1e582023-03-30 21:08:06 +08001062 RETURN_STATUS_IF_ERROR(createOrUpdatePortConfig(requestedPortConfig, &portConfigIt,
1063 created));
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001064 } else {
1065 *created = false;
1066 }
1067 *portConfig = portConfigIt->second;
1068 return OK;
1069}
1070
1071status_t DeviceHalAidl::findOrCreatePortConfig(
Mikhail Naganov8bd806e2023-01-30 12:33:18 -08001072 const AudioConfig& config, const std::optional<AudioIoFlags>& flags, int32_t ioHandle,
Mikhail Naganovecfafb72023-03-29 10:06:15 -07001073 AudioSource source, const std::set<int32_t>& destinationPortIds,
1074 AudioPortConfig* portConfig, bool* created) {
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001075 // These flags get removed one by one in this order when retrying port finding.
1076 static const std::vector<AudioInputFlags> kOptionalInputFlags{
1077 AudioInputFlags::FAST, AudioInputFlags::RAW };
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001078 auto portConfigIt = findPortConfig(config, flags, ioHandle);
Mikhail Naganov8bd806e2023-01-30 12:33:18 -08001079 if (portConfigIt == mPortConfigs.end() && flags.has_value()) {
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001080 auto optionalInputFlagsIt = kOptionalInputFlags.begin();
1081 AudioIoFlags matchFlags = flags.value();
Mikhail Naganovecfafb72023-03-29 10:06:15 -07001082 auto portsIt = findPort(config, matchFlags, destinationPortIds);
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001083 while (portsIt == mPorts.end() && matchFlags.getTag() == AudioIoFlags::Tag::input
1084 && optionalInputFlagsIt != kOptionalInputFlags.end()) {
1085 if (!isBitPositionFlagSet(
1086 matchFlags.get<AudioIoFlags::Tag::input>(), *optionalInputFlagsIt)) {
1087 ++optionalInputFlagsIt;
1088 continue;
1089 }
1090 matchFlags.set<AudioIoFlags::Tag::input>(matchFlags.get<AudioIoFlags::Tag::input>() &
1091 ~makeBitPositionFlagMask(*optionalInputFlagsIt++));
Mikhail Naganovecfafb72023-03-29 10:06:15 -07001092 portsIt = findPort(config, matchFlags, destinationPortIds);
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001093 ALOGI("%s: mix port for config %s, flags %s was not found in the module %s, "
1094 "retried with flags %s", __func__, config.toString().c_str(),
1095 flags.value().toString().c_str(), mInstance.c_str(),
1096 matchFlags.toString().c_str());
1097 }
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001098 if (portsIt == mPorts.end()) {
1099 ALOGE("%s: mix port for config %s, flags %s is not found in the module %s",
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001100 __func__, config.toString().c_str(), matchFlags.toString().c_str(),
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001101 mInstance.c_str());
1102 return BAD_VALUE;
1103 }
1104 AudioPortConfig requestedPortConfig;
1105 requestedPortConfig.portId = portsIt->first;
1106 setPortConfigFromConfig(&requestedPortConfig, config);
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001107 requestedPortConfig.ext = AudioPortMixExt{ .handle = ioHandle };
Mikhail Naganovd8d01f72023-03-09 16:24:40 -08001108 if (matchFlags.getTag() == AudioIoFlags::Tag::input
1109 && source != AudioSource::SYS_RESERVED_INVALID) {
1110 requestedPortConfig.ext.get<AudioPortExt::Tag::mix>().usecase =
1111 AudioPortMixExtUseCase::make<AudioPortMixExtUseCase::Tag::source>(source);
1112 }
David Lia8f1e582023-03-30 21:08:06 +08001113 RETURN_STATUS_IF_ERROR(createOrUpdatePortConfig(requestedPortConfig, &portConfigIt,
1114 created));
Mikhail Naganov8bd806e2023-01-30 12:33:18 -08001115 } else if (!flags.has_value()) {
1116 ALOGW("%s: mix port config for %s, handle %d not found in the module %s, "
1117 "and was not created as flags are not specified",
1118 __func__, config.toString().c_str(), ioHandle, mInstance.c_str());
1119 return BAD_VALUE;
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001120 } else {
David Lia8f1e582023-03-30 21:08:06 +08001121 AudioPortConfig requestedPortConfig = portConfigIt->second;
1122 if (requestedPortConfig.ext.getTag() == AudioPortExt::Tag::mix) {
1123 AudioPortMixExt& mixExt = requestedPortConfig.ext.get<AudioPortExt::Tag::mix>();
1124 if (mixExt.usecase.getTag() == AudioPortMixExtUseCase::Tag::source &&
1125 source != AudioSource::SYS_RESERVED_INVALID) {
1126 mixExt.usecase.get<AudioPortMixExtUseCase::Tag::source>() = source;
1127 }
1128 }
1129
1130 if (requestedPortConfig != portConfigIt->second) {
1131 RETURN_STATUS_IF_ERROR(createOrUpdatePortConfig(requestedPortConfig, &portConfigIt,
1132 created));
1133 } else {
1134 *created = false;
1135 }
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001136 }
1137 *portConfig = portConfigIt->second;
1138 return OK;
1139}
1140
1141status_t DeviceHalAidl::findOrCreatePortConfig(
Mikhail Naganovecfafb72023-03-29 10:06:15 -07001142 const AudioPortConfig& requestedPortConfig, const std::set<int32_t>& destinationPortIds,
1143 AudioPortConfig* portConfig, bool* created) {
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001144 using Tag = AudioPortExt::Tag;
1145 if (requestedPortConfig.ext.getTag() == Tag::mix) {
1146 if (const auto& p = requestedPortConfig;
1147 !p.sampleRate.has_value() || !p.channelMask.has_value() ||
Mikhail Naganov8bd806e2023-01-30 12:33:18 -08001148 !p.format.has_value()) {
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001149 ALOGW("%s: provided mix port config is not fully specified: %s",
1150 __func__, p.toString().c_str());
1151 return BAD_VALUE;
1152 }
1153 AudioConfig config;
1154 setConfigFromPortConfig(&config, requestedPortConfig);
Mikhail Naganovd8d01f72023-03-09 16:24:40 -08001155 AudioSource source = requestedPortConfig.ext.get<Tag::mix>().usecase.getTag() ==
1156 AudioPortMixExtUseCase::Tag::source ?
1157 requestedPortConfig.ext.get<Tag::mix>().usecase.
1158 get<AudioPortMixExtUseCase::Tag::source>() : AudioSource::SYS_RESERVED_INVALID;
Mikhail Naganov8bd806e2023-01-30 12:33:18 -08001159 return findOrCreatePortConfig(config, requestedPortConfig.flags,
Mikhail Naganovecfafb72023-03-29 10:06:15 -07001160 requestedPortConfig.ext.get<Tag::mix>().handle, source, destinationPortIds,
1161 portConfig, created);
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001162 } else if (requestedPortConfig.ext.getTag() == Tag::device) {
1163 return findOrCreatePortConfig(
jiabin2248fa12023-04-27 22:04:16 +00001164 requestedPortConfig.ext.get<Tag::device>().device, nullptr /*config*/,
1165 portConfig, created);
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001166 }
1167 ALOGW("%s: unsupported audio port config: %s",
1168 __func__, requestedPortConfig.toString().c_str());
1169 return BAD_VALUE;
1170}
1171
1172DeviceHalAidl::Patches::iterator DeviceHalAidl::findPatch(
1173 const std::set<int32_t>& sourcePortConfigIds, const std::set<int32_t>& sinkPortConfigIds) {
1174 return std::find_if(mPatches.begin(), mPatches.end(),
1175 [&](const auto& pair) {
1176 const auto& p = pair.second;
1177 std::set<int32_t> patchSrcs(
1178 p.sourcePortConfigIds.begin(), p.sourcePortConfigIds.end());
1179 std::set<int32_t> patchSinks(
1180 p.sinkPortConfigIds.begin(), p.sinkPortConfigIds.end());
1181 return sourcePortConfigIds == patchSrcs && sinkPortConfigIds == patchSinks; });
1182}
1183
1184DeviceHalAidl::Ports::iterator DeviceHalAidl::findPort(const AudioDevice& device) {
Mikhail Naganov8bd806e2023-01-30 12:33:18 -08001185 if (device.type.type == AudioDeviceType::IN_DEFAULT) {
1186 return mPorts.find(mDefaultInputPortId);
1187 } else if (device.type.type == AudioDeviceType::OUT_DEFAULT) {
1188 return mPorts.find(mDefaultOutputPortId);
1189 }
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001190 return std::find_if(mPorts.begin(), mPorts.end(),
Mikhail Naganov8bd806e2023-01-30 12:33:18 -08001191 [&](const auto& pair) { return audioDeviceMatches(device, pair.second); });
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001192}
1193
1194DeviceHalAidl::Ports::iterator DeviceHalAidl::findPort(
Mikhail Naganovecfafb72023-03-29 10:06:15 -07001195 const AudioConfig& config, const AudioIoFlags& flags,
1196 const std::set<int32_t>& destinationPortIds) {
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -07001197 auto belongsToProfile = [&config](const AudioProfile& prof) {
1198 return (isDefaultAudioFormat(config.base.format) || prof.format == config.base.format) &&
1199 (config.base.channelMask.getTag() == AudioChannelLayout::none ||
1200 std::find(prof.channelMasks.begin(), prof.channelMasks.end(),
1201 config.base.channelMask) != prof.channelMasks.end()) &&
1202 (config.base.sampleRate == 0 ||
1203 std::find(prof.sampleRates.begin(), prof.sampleRates.end(),
1204 config.base.sampleRate) != prof.sampleRates.end());
1205 };
jiabin2248fa12023-04-27 22:04:16 +00001206 static const std::vector<AudioOutputFlags> kOptionalOutputFlags{AudioOutputFlags::BIT_PERFECT};
1207 int optionalFlags = 0;
1208 auto flagMatches = [&flags, &optionalFlags](const AudioIoFlags& portFlags) {
1209 // Ports should be able to match if the optional flags are not requested.
1210 return portFlags == flags ||
1211 (portFlags.getTag() == AudioIoFlags::Tag::output &&
1212 AudioIoFlags::make<AudioIoFlags::Tag::output>(
1213 portFlags.get<AudioIoFlags::Tag::output>() &
1214 ~optionalFlags) == flags);
1215 };
Mikhail Naganov8bd806e2023-01-30 12:33:18 -08001216 auto matcher = [&](const auto& pair) {
1217 const auto& p = pair.second;
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001218 return p.ext.getTag() == AudioPortExt::Tag::mix &&
jiabin2248fa12023-04-27 22:04:16 +00001219 flagMatches(p.flags) &&
Mikhail Naganovecfafb72023-03-29 10:06:15 -07001220 (destinationPortIds.empty() ||
1221 std::any_of(destinationPortIds.begin(), destinationPortIds.end(),
1222 [&](const int32_t destId) { return mRoutingMatrix.count(
1223 std::make_pair(p.id, destId)) != 0; })) &&
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -07001224 (p.profiles.empty() ||
1225 std::find_if(p.profiles.begin(), p.profiles.end(), belongsToProfile) !=
1226 p.profiles.end()); };
jiabin2248fa12023-04-27 22:04:16 +00001227 auto result = std::find_if(mPorts.begin(), mPorts.end(), matcher);
1228 if (result == mPorts.end() && flags.getTag() == AudioIoFlags::Tag::output) {
1229 auto optionalOutputFlagsIt = kOptionalOutputFlags.begin();
1230 while (result == mPorts.end() && optionalOutputFlagsIt != kOptionalOutputFlags.end()) {
1231 if (isBitPositionFlagSet(
1232 flags.get<AudioIoFlags::Tag::output>(), *optionalOutputFlagsIt)) {
1233 // If the flag is set by the request, it must be matched.
1234 ++optionalOutputFlagsIt;
1235 continue;
1236 }
1237 optionalFlags |= makeBitPositionFlagMask(*optionalOutputFlagsIt++);
1238 result = std::find_if(mPorts.begin(), mPorts.end(), matcher);
1239 ALOGI("%s: port for config %s, flags %s was not found in the module %s, "
1240 "retried with excluding optional flags %#x", __func__, config.toString().c_str(),
1241 flags.toString().c_str(), mInstance.c_str(), optionalFlags);
1242 }
1243 }
1244 return result;
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001245}
1246
1247DeviceHalAidl::PortConfigs::iterator DeviceHalAidl::findPortConfig(const AudioDevice& device) {
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001248 return std::find_if(mPortConfigs.begin(), mPortConfigs.end(),
Mikhail Naganov8bd806e2023-01-30 12:33:18 -08001249 [&](const auto& pair) { return audioDeviceMatches(device, pair.second); });
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001250}
1251
1252DeviceHalAidl::PortConfigs::iterator DeviceHalAidl::findPortConfig(
Mikhail Naganov8bd806e2023-01-30 12:33:18 -08001253 const AudioConfig& config, const std::optional<AudioIoFlags>& flags, int32_t ioHandle) {
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001254 using Tag = AudioPortExt::Tag;
1255 return std::find_if(mPortConfigs.begin(), mPortConfigs.end(),
1256 [&](const auto& pair) {
1257 const auto& p = pair.second;
1258 LOG_ALWAYS_FATAL_IF(p.ext.getTag() == Tag::mix &&
1259 !p.sampleRate.has_value() || !p.channelMask.has_value() ||
1260 !p.format.has_value() || !p.flags.has_value(),
1261 "%s: stored mix port config is not fully specified: %s",
1262 __func__, p.toString().c_str());
1263 return p.ext.getTag() == Tag::mix &&
1264 isConfigEqualToPortConfig(config, p) &&
Mikhail Naganov8bd806e2023-01-30 12:33:18 -08001265 (!flags.has_value() || p.flags.value() == flags.value()) &&
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001266 p.ext.template get<Tag::mix>().handle == ioHandle; });
1267}
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -07001268
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001269void DeviceHalAidl::resetPatch(int32_t patchId) {
1270 if (auto it = mPatches.find(patchId); it != mPatches.end()) {
1271 mPatches.erase(it);
1272 TIME_CHECK();
1273 if (ndk::ScopedAStatus status = mModule->resetAudioPatch(patchId); !status.isOk()) {
1274 ALOGE("%s: error while resetting patch %d: %s",
1275 __func__, patchId, status.getDescription().c_str());
1276 }
1277 return;
1278 }
1279 ALOGE("%s: patch id %d not found", __func__, patchId);
1280}
1281
1282void DeviceHalAidl::resetPortConfig(int32_t portConfigId) {
1283 if (auto it = mPortConfigs.find(portConfigId); it != mPortConfigs.end()) {
1284 mPortConfigs.erase(it);
1285 TIME_CHECK();
1286 if (ndk::ScopedAStatus status = mModule->resetAudioPortConfig(portConfigId);
1287 !status.isOk()) {
1288 ALOGE("%s: error while resetting port config %d: %s",
1289 __func__, portConfigId, status.getDescription().c_str());
1290 }
1291 return;
1292 }
1293 ALOGE("%s: port config id %d not found", __func__, portConfigId);
1294}
1295
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -07001296void DeviceHalAidl::resetUnusedPatches() {
1297 // Since patches can be created independently of streams via 'createAudioPatch',
1298 // here we only clean up patches for released streams.
1299 for (auto it = mStreams.begin(); it != mStreams.end(); ) {
1300 if (auto streamSp = it->first.promote(); streamSp) {
1301 ++it;
1302 } else {
1303 resetPatch(it->second);
1304 it = mStreams.erase(it);
1305 }
1306 }
1307}
1308
1309void DeviceHalAidl::resetUnusedPatchesAndPortConfigs() {
1310 resetUnusedPatches();
1311 resetUnusedPortConfigs();
1312}
1313
1314void DeviceHalAidl::resetUnusedPortConfigs() {
1315 // The assumption is that port configs are used to create patches
1316 // (or to open streams, but that involves creation of patches, too). Thus,
1317 // orphaned port configs can and should be reset.
1318 std::set<int32_t> portConfigIds;
1319 std::transform(mPortConfigs.begin(), mPortConfigs.end(),
1320 std::inserter(portConfigIds, portConfigIds.end()),
1321 [](const auto& pcPair) { return pcPair.first; });
1322 for (const auto& p : mPatches) {
1323 for (int32_t id : p.second.sourcePortConfigIds) portConfigIds.erase(id);
1324 for (int32_t id : p.second.sinkPortConfigIds) portConfigIds.erase(id);
1325 }
jiabin2248fa12023-04-27 22:04:16 +00001326 for (int32_t id : mInitialPortConfigIds) {
1327 portConfigIds.erase(id);
1328 }
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -07001329 for (int32_t id : portConfigIds) resetPortConfig(id);
1330}
1331
Mikhail Naganovecfafb72023-03-29 10:06:15 -07001332status_t DeviceHalAidl::updateRoutes() {
1333 TIME_CHECK();
1334 std::vector<AudioRoute> routes;
1335 RETURN_STATUS_IF_ERROR(
1336 statusTFromBinderStatus(mModule->getAudioRoutes(&routes)));
1337 ALOGW_IF(routes.empty(), "%s: module %s returned an empty list of audio routes",
1338 __func__, mInstance.c_str());
1339 mRoutingMatrix.clear();
1340 for (const auto& r : routes) {
1341 for (auto portId : r.sourcePortIds) {
1342 mRoutingMatrix.emplace(r.sinkPortId, portId);
1343 mRoutingMatrix.emplace(portId, r.sinkPortId);
1344 }
1345 }
1346 return OK;
1347}
1348
Mikhail Naganovb0c55252023-02-08 16:59:41 -08001349void DeviceHalAidl::clearCallbacks(void* cookie) {
1350 std::lock_guard l(mLock);
1351 mCallbacks.erase(cookie);
1352}
1353
1354sp<StreamOutHalInterfaceCallback> DeviceHalAidl::getStreamOutCallback(void* cookie) {
1355 return getCallbackImpl(cookie, &Callbacks::out);
1356}
1357
1358void DeviceHalAidl::setStreamOutCallback(
1359 void* cookie, const sp<StreamOutHalInterfaceCallback>& cb) {
1360 setCallbackImpl(cookie, &Callbacks::out, cb);
1361}
1362
1363sp<StreamOutHalInterfaceEventCallback> DeviceHalAidl::getStreamOutEventCallback(
1364 void* cookie) {
1365 return getCallbackImpl(cookie, &Callbacks::event);
1366}
1367
1368void DeviceHalAidl::setStreamOutEventCallback(
1369 void* cookie, const sp<StreamOutHalInterfaceEventCallback>& cb) {
1370 setCallbackImpl(cookie, &Callbacks::event, cb);
1371}
1372
1373sp<StreamOutHalInterfaceLatencyModeCallback> DeviceHalAidl::getStreamOutLatencyModeCallback(
1374 void* cookie) {
1375 return getCallbackImpl(cookie, &Callbacks::latency);
1376}
1377
1378void DeviceHalAidl::setStreamOutLatencyModeCallback(
1379 void* cookie, const sp<StreamOutHalInterfaceLatencyModeCallback>& cb) {
1380 setCallbackImpl(cookie, &Callbacks::latency, cb);
1381}
1382
1383template<class C>
1384sp<C> DeviceHalAidl::getCallbackImpl(void* cookie, wp<C> DeviceHalAidl::Callbacks::* field) {
1385 std::lock_guard l(mLock);
1386 if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
1387 return ((it->second).*field).promote();
1388 }
1389 return nullptr;
1390}
1391template<class C>
1392void DeviceHalAidl::setCallbackImpl(
1393 void* cookie, wp<C> DeviceHalAidl::Callbacks::* field, const sp<C>& cb) {
1394 std::lock_guard l(mLock);
1395 if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
1396 (it->second).*field = cb;
1397 }
1398}
1399
Mikhail Naganov31d46652023-01-10 18:29:25 +00001400} // namespace android