blob: 8f764b527397470fe0a32c80f8db6bf68104699e [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>
Mikhail Naganov25bc9a22023-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 Naganov89a9f742023-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 Naganove93a0862023-03-15 17:06:59 -070038using aidl::android::media::audio::common::AudioChannelLayout;
Mikhail Naganov5b1eed12023-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 Naganov89a9f742023-01-30 12:33:18 -080042using aidl::android::media::audio::common::AudioDeviceType;
Mikhail Naganove93a0862023-03-15 17:06:59 -070043using aidl::android::media::audio::common::AudioFormatType;
Mikhail Naganov89a9f742023-01-30 12:33:18 -080044using aidl::android::media::audio::common::AudioInputFlags;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -080045using aidl::android::media::audio::common::AudioIoFlags;
Mikhail Naganovdfd594e2023-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 Naganov5b1eed12023-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 Naganov89a9f742023-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 Naganove93a0862023-03-15 17:06:59 -070058using aidl::android::media::audio::common::AudioProfile;
Mikhail Naganov5b1eed12023-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 Naganove93a0862023-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 Naganov5b1eed12023-01-25 11:29:11 -080068using aidl::android::hardware::audio::common::RecordTrackMetadata;
69using aidl::android::hardware::audio::core::AudioPatch;
Mikhail Naganov289468a2023-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 Naganove93a0862023-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 Naganov5b1eed12023-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
Mikhail Naganovf83b9742023-04-24 13:06:04 -070098// Note: these converters are for types defined in different AIDL files. Although these
99// AIDL files are copies of each other, however formally these are different types
100// thus we don't use a conversion via a parcelable.
101ConversionResult<media::AudioRoute> ndk2cpp_AudioRoute(const AudioRoute& ndk) {
102 media::AudioRoute cpp;
103 cpp.sourcePortIds.insert(
104 cpp.sourcePortIds.end(), ndk.sourcePortIds.begin(), ndk.sourcePortIds.end());
105 cpp.sinkPortId = ndk.sinkPortId;
106 cpp.isExclusive = ndk.isExclusive;
David Li9cf5e622023-03-21 00:51:10 +0800107 return cpp;
108}
109
Mikhail Naganov1fba38c2023-05-03 17:45:36 -0700110template<typename T>
111std::shared_ptr<T> retrieveSubInterface(const std::shared_ptr<IModule>& module,
112 ::ndk::ScopedAStatus (IModule::*getT)(std::shared_ptr<T>*)) {
113 if (module != nullptr) {
114 std::shared_ptr<T> instance;
115 if (auto status = (module.get()->*getT)(&instance); status.isOk()) {
116 return instance;
117 }
118 }
119 return nullptr;
120}
121
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800122} // namespace
123
Mikhail Naganov1fba38c2023-05-03 17:45:36 -0700124DeviceHalAidl::DeviceHalAidl(const std::string& instance, const std::shared_ptr<IModule>& module)
125 : ConversionHelperAidl("DeviceHalAidl"),
126 mInstance(instance), mModule(module),
127 mTelephony(retrieveSubInterface<ITelephony>(module, &IModule::getTelephony)) {
128}
129
Mikhail Naganovf83b9742023-04-24 13:06:04 -0700130status_t DeviceHalAidl::getAudioPorts(std::vector<media::audio::common::AudioPort> *ports) {
Mikhail Naganov9e459d72023-05-05 17:36:39 -0700131 return ::aidl::android::convertContainer(mPorts, ports,
132 [](const Ports::value_type& pair) { return ndk2cpp_AudioPort(pair.second); });
Mikhail Naganovf83b9742023-04-24 13:06:04 -0700133}
134
135status_t DeviceHalAidl::getAudioRoutes(std::vector<media::AudioRoute> *routes) {
136 *routes = VALUE_OR_RETURN_STATUS(
137 ::aidl::android::convertContainer<std::vector<media::AudioRoute>>(
138 mRoutes, ndk2cpp_AudioRoute));
139 return OK;
140}
141
Mikhail Naganov1fba38c2023-05-03 17:45:36 -0700142status_t DeviceHalAidl::getSupportedModes(std::vector<media::audio::common::AudioMode> *modes) {
143 TIME_CHECK();
144 if (modes == nullptr) {
145 return BAD_VALUE;
146 }
147 if (mModule == nullptr) return NO_INIT;
148 if (mTelephony == nullptr) return INVALID_OPERATION;
149 std::vector<AudioMode> aidlModes;
150 RETURN_STATUS_IF_ERROR(
151 statusTFromBinderStatus(mTelephony->getSupportedAudioModes(&aidlModes)));
152 *modes = VALUE_OR_RETURN_STATUS(
153 ::aidl::android::convertContainer<std::vector<media::audio::common::AudioMode>>(
154 aidlModes, ndk2cpp_AudioMode));
155 return OK;
156}
157
Mikhail Naganov31d46652023-01-10 18:29:25 +0000158status_t DeviceHalAidl::getSupportedDevices(uint32_t*) {
159 // Obsolete.
160 return INVALID_OPERATION;
Shunkai Yao51202502022-12-12 06:11:46 +0000161}
162
163status_t DeviceHalAidl::initCheck() {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800164 TIME_CHECK();
Mikhail Naganov31d46652023-01-10 18:29:25 +0000165 if (mModule == nullptr) return NO_INIT;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800166 std::vector<AudioPort> ports;
Mikhail Naganovf83b9742023-04-24 13:06:04 -0700167 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->getAudioPorts(&ports)));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800168 ALOGW_IF(ports.empty(), "%s: module %s returned an empty list of audio ports",
169 __func__, mInstance.c_str());
170 std::transform(ports.begin(), ports.end(), std::inserter(mPorts, mPorts.end()),
171 [](const auto& p) { return std::make_pair(p.id, p); });
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800172 mDefaultInputPortId = mDefaultOutputPortId = -1;
173 const int defaultDeviceFlag = 1 << AudioPortDeviceExt::FLAG_INDEX_DEFAULT_DEVICE;
174 for (const auto& pair : mPorts) {
175 const auto& p = pair.second;
176 if (p.ext.getTag() == AudioPortExt::Tag::device &&
177 (p.ext.get<AudioPortExt::Tag::device>().flags & defaultDeviceFlag) != 0) {
178 if (p.flags.getTag() == AudioIoFlags::Tag::input) {
179 mDefaultInputPortId = p.id;
180 } else if (p.flags.getTag() == AudioIoFlags::Tag::output) {
181 mDefaultOutputPortId = p.id;
182 }
183 }
184 }
185 ALOGI("%s: module %s default port ids: input %d, output %d",
186 __func__, mInstance.c_str(), mDefaultInputPortId, mDefaultOutputPortId);
Mikhail Naganov289468a2023-03-29 10:06:15 -0700187 RETURN_STATUS_IF_ERROR(updateRoutes());
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800188 std::vector<AudioPortConfig> portConfigs;
189 RETURN_STATUS_IF_ERROR(
190 statusTFromBinderStatus(mModule->getAudioPortConfigs(&portConfigs))); // OK if empty
191 std::transform(portConfigs.begin(), portConfigs.end(),
192 std::inserter(mPortConfigs, mPortConfigs.end()),
193 [](const auto& p) { return std::make_pair(p.id, p); });
jiabin9c07faf2023-04-26 22:00:44 +0000194 std::transform(mPortConfigs.begin(), mPortConfigs.end(),
195 std::inserter(mInitialPortConfigIds, mInitialPortConfigIds.end()),
196 [](const auto& pcPair) { return pcPair.first; });
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800197 std::vector<AudioPatch> patches;
198 RETURN_STATUS_IF_ERROR(
199 statusTFromBinderStatus(mModule->getAudioPatches(&patches))); // OK if empty
200 std::transform(patches.begin(), patches.end(),
201 std::inserter(mPatches, mPatches.end()),
202 [](const auto& p) { return std::make_pair(p.id, p); });
Shunkai Yao51202502022-12-12 06:11:46 +0000203 return OK;
204}
205
206status_t DeviceHalAidl::setVoiceVolume(float volume) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000207 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000208 if (!mModule) return NO_INIT;
Mikhail Naganov1fba38c2023-05-03 17:45:36 -0700209 if (mTelephony == nullptr) return INVALID_OPERATION;
210 ITelephony::TelecomConfig inConfig{ .voiceVolume = Float{volume} }, outConfig;
211 RETURN_STATUS_IF_ERROR(
212 statusTFromBinderStatus(mTelephony->setTelecomConfig(inConfig, &outConfig)));
213 ALOGW_IF(outConfig.voiceVolume.has_value() && volume != outConfig.voiceVolume.value().value,
214 "%s: the resulting voice volume %f is not the same as requested %f",
215 __func__, outConfig.voiceVolume.value().value, volume);
216 return OK;
Shunkai Yao51202502022-12-12 06:11:46 +0000217}
218
219status_t DeviceHalAidl::setMasterVolume(float volume) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000220 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000221 if (!mModule) return NO_INIT;
222 return statusTFromBinderStatus(mModule->setMasterVolume(volume));
Shunkai Yao51202502022-12-12 06:11:46 +0000223}
224
225status_t DeviceHalAidl::getMasterVolume(float *volume) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000226 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000227 if (!mModule) return NO_INIT;
228 return statusTFromBinderStatus(mModule->getMasterVolume(volume));
Shunkai Yao51202502022-12-12 06:11:46 +0000229}
230
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000231status_t DeviceHalAidl::setMode(audio_mode_t mode) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000232 TIME_CHECK();
233 if (!mModule) return NO_INIT;
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000234 AudioMode audioMode = VALUE_OR_FATAL(::aidl::android::legacy2aidl_audio_mode_t_AudioMode(mode));
Mikhail Naganov1fba38c2023-05-03 17:45:36 -0700235 if (mTelephony != nullptr) {
236 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mTelephony->switchAudioMode(audioMode)));
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000237 }
238 return statusTFromBinderStatus(mModule->updateAudioMode(audioMode));
Shunkai Yao51202502022-12-12 06:11:46 +0000239}
240
241status_t DeviceHalAidl::setMicMute(bool state) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000242 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000243 if (!mModule) return NO_INIT;
244 return statusTFromBinderStatus(mModule->setMicMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000245}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000246
Shunkai Yao51202502022-12-12 06:11:46 +0000247status_t DeviceHalAidl::getMicMute(bool *state) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000248 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000249 if (!mModule) return NO_INIT;
250 return statusTFromBinderStatus(mModule->getMicMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000251}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000252
Shunkai Yao51202502022-12-12 06:11:46 +0000253status_t DeviceHalAidl::setMasterMute(bool state) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000254 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000255 if (!mModule) return NO_INIT;
256 return statusTFromBinderStatus(mModule->setMasterMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000257}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000258
Shunkai Yao51202502022-12-12 06:11:46 +0000259status_t DeviceHalAidl::getMasterMute(bool *state) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000260 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000261 if (!mModule) return NO_INIT;
262 return statusTFromBinderStatus(mModule->getMasterMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000263}
264
Mikhail Naganov31d46652023-01-10 18:29:25 +0000265status_t DeviceHalAidl::setParameters(const String8& kvPairs __unused) {
266 TIME_CHECK();
267 if (!mModule) return NO_INIT;
268 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000269 return OK;
270}
271
Mikhail Naganov31d46652023-01-10 18:29:25 +0000272status_t DeviceHalAidl::getParameters(const String8& keys __unused, String8 *values) {
273 TIME_CHECK();
274 values->clear();
275 if (!mModule) return NO_INIT;
276 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000277 return OK;
278}
279
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800280namespace {
281
282class Cleanup {
283 public:
284 typedef void (DeviceHalAidl::*Cleaner)(int32_t);
285
286 Cleanup(DeviceHalAidl* device, Cleaner cleaner, int32_t id) :
287 mDevice(device), mCleaner(cleaner), mId(id) {}
288 ~Cleanup() { clean(); }
289 void clean() {
290 if (mDevice != nullptr) (mDevice->*mCleaner)(mId);
291 disarm();
292 }
293 void disarm() { mDevice = nullptr; }
294
295 private:
296 DeviceHalAidl* mDevice;
297 const Cleaner mCleaner;
298 const int32_t mId;
299};
300
301} // namespace
302
303// Since the order of container elements destruction is unspecified,
304// ensure that cleanups are performed from the most recent one and upwards.
305// This is the same as if there were individual Cleanup instances on the stack,
306// however the bonus is that we can disarm all of them with just one statement.
307class DeviceHalAidl::Cleanups : public std::forward_list<Cleanup> {
308 public:
309 ~Cleanups() { for (auto& c : *this) c.clean(); }
310 void disarmAll() { for (auto& c : *this) c.disarm(); }
311};
312
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800313status_t DeviceHalAidl::getInputBufferSize(const struct audio_config* config, size_t* size) {
314 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
315 if (size == nullptr) return BAD_VALUE;
316 TIME_CHECK();
317 if (!mModule) return NO_INIT;
318 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
319 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, true /*isInput*/));
320 AudioDevice aidlDevice;
321 aidlDevice.type.type = AudioDeviceType::IN_DEFAULT;
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800322 AudioSource aidlSource = AudioSource::DEFAULT;
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800323 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::input>(0);
324 AudioPortConfig mixPortConfig;
325 Cleanups cleanups;
326 audio_config writableConfig = *config;
Mikhail Naganove93a0862023-03-15 17:06:59 -0700327 AudioPatch aidlPatch;
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800328 RETURN_STATUS_IF_ERROR(prepareToOpenStream(0 /*handle*/, aidlDevice, aidlFlags, aidlSource,
Mikhail Naganove93a0862023-03-15 17:06:59 -0700329 &writableConfig, &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800330 *size = aidlConfig.frameCount *
331 getFrameSizeInBytes(aidlConfig.base.format, aidlConfig.base.channelMask);
332 // Do not disarm cleanups to release temporary port configs.
333 return OK;
334}
335
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800336status_t DeviceHalAidl::prepareToOpenStream(
337 int32_t aidlHandle, const AudioDevice& aidlDevice, const AudioIoFlags& aidlFlags,
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800338 AudioSource aidlSource, struct audio_config* config,
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800339 Cleanups* cleanups, AudioConfig* aidlConfig, AudioPortConfig* mixPortConfig,
Mikhail Naganove93a0862023-03-15 17:06:59 -0700340 AudioPatch* aidlPatch) {
341 ALOGD("%p %s::%s: handle %d, device %s, flags %s, source %s, config %s, mix port config %s",
342 this, getClassName().c_str(), __func__, aidlHandle, aidlDevice.toString().c_str(),
343 aidlFlags.toString().c_str(), toString(aidlSource).c_str(),
344 aidlConfig->toString().c_str(), mixPortConfig->toString().c_str());
jiabin9c07faf2023-04-26 22:00:44 +0000345 resetUnusedPatchesAndPortConfigs();
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800346 const bool isInput = aidlFlags.getTag() == AudioIoFlags::Tag::input;
347 // Find / create AudioPortConfigs for the device port and the mix port,
348 // then find / create a patch between them, and open a stream on the mix port.
349 AudioPortConfig devicePortConfig;
350 bool created = false;
jiabin9c07faf2023-04-26 22:00:44 +0000351 RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(aidlDevice, aidlConfig,
352 &devicePortConfig, &created));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800353 if (created) {
354 cleanups->emplace_front(this, &DeviceHalAidl::resetPortConfig, devicePortConfig.id);
355 }
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800356 RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(*aidlConfig, aidlFlags, aidlHandle, aidlSource,
Mikhail Naganov289468a2023-03-29 10:06:15 -0700357 std::set<int32_t>{devicePortConfig.portId}, mixPortConfig, &created));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800358 if (created) {
359 cleanups->emplace_front(this, &DeviceHalAidl::resetPortConfig, mixPortConfig->id);
360 }
361 setConfigFromPortConfig(aidlConfig, *mixPortConfig);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800362 if (isInput) {
363 RETURN_STATUS_IF_ERROR(findOrCreatePatch(
Mikhail Naganove93a0862023-03-15 17:06:59 -0700364 {devicePortConfig.id}, {mixPortConfig->id}, aidlPatch, &created));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800365 } else {
366 RETURN_STATUS_IF_ERROR(findOrCreatePatch(
Mikhail Naganove93a0862023-03-15 17:06:59 -0700367 {mixPortConfig->id}, {devicePortConfig.id}, aidlPatch, &created));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800368 }
369 if (created) {
Mikhail Naganove93a0862023-03-15 17:06:59 -0700370 cleanups->emplace_front(this, &DeviceHalAidl::resetPatch, aidlPatch->id);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800371 }
372 if (aidlConfig->frameCount <= 0) {
Mikhail Naganove93a0862023-03-15 17:06:59 -0700373 aidlConfig->frameCount = aidlPatch->minimumStreamBufferSizeFrames;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800374 }
375 *config = VALUE_OR_RETURN_STATUS(
376 ::aidl::android::aidl2legacy_AudioConfig_audio_config_t(*aidlConfig, isInput));
377 return OK;
378}
379
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800380namespace {
381
382class StreamCallbackBase {
383 protected:
384 explicit StreamCallbackBase(const sp<CallbackBroker>& broker) : mBroker(broker) {}
385 public:
386 void* getCookie() const { return mCookie; }
387 void setCookie(void* cookie) { mCookie = cookie; }
388 sp<CallbackBroker> getBroker() const {
389 if (void* cookie = mCookie; cookie != nullptr) return mBroker.promote();
390 return nullptr;
391 }
392 private:
393 const wp<CallbackBroker> mBroker;
394 std::atomic<void*> mCookie;
395};
396
397template<class C>
398class StreamCallbackBaseHelper {
399 protected:
400 explicit StreamCallbackBaseHelper(const StreamCallbackBase& base) : mBase(base) {}
401 sp<C> getCb(const sp<CallbackBroker>& broker, void* cookie);
402 using CbRef = const sp<C>&;
403 ndk::ScopedAStatus runCb(const std::function<void(CbRef cb)>& f) {
404 if (auto cb = getCb(mBase.getBroker(), mBase.getCookie()); cb != nullptr) f(cb);
405 return ndk::ScopedAStatus::ok();
406 }
407 private:
408 const StreamCallbackBase& mBase;
409};
410
411template<>
412sp<StreamOutHalInterfaceCallback> StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>::getCb(
413 const sp<CallbackBroker>& broker, void* cookie) {
414 if (broker != nullptr) return broker->getStreamOutCallback(cookie);
415 return nullptr;
416}
417
418template<>
419sp<StreamOutHalInterfaceEventCallback>
420StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>::getCb(
421 const sp<CallbackBroker>& broker, void* cookie) {
422 if (broker != nullptr) return broker->getStreamOutEventCallback(cookie);
423 return nullptr;
424}
425
426template<>
427sp<StreamOutHalInterfaceLatencyModeCallback>
428StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>::getCb(
429 const sp<CallbackBroker>& broker, void* cookie) {
430 if (broker != nullptr) return broker->getStreamOutLatencyModeCallback(cookie);
431 return nullptr;
432}
433
434/*
435Note on the callback ownership.
436
437In the Binder ownership model, the server implementation is kept alive
438as long as there is any client (proxy object) alive. This is done by
439incrementing the refcount of the server-side object by the Binder framework.
440When it detects that the last client is gone, it decrements the refcount back.
441
442Thus, it is not needed to keep any references to StreamCallback on our
443side (after we have sent an instance to the client), because we are
444the server-side. The callback object will be kept alive as long as the HAL server
445holds a strong ref to IStreamCallback proxy.
446*/
447
448class OutputStreamCallbackAidl : public StreamCallbackBase,
449 public StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>,
450 public ::aidl::android::hardware::audio::core::BnStreamCallback {
451 public:
452 explicit OutputStreamCallbackAidl(const sp<CallbackBroker>& broker)
453 : StreamCallbackBase(broker),
454 StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>(
455 *static_cast<StreamCallbackBase*>(this)) {}
456 ndk::ScopedAStatus onTransferReady() override {
457 return runCb([](CbRef cb) { cb->onWriteReady(); });
458 }
459 ndk::ScopedAStatus onError() override {
460 return runCb([](CbRef cb) { cb->onError(); });
461 }
462 ndk::ScopedAStatus onDrainReady() override {
463 return runCb([](CbRef cb) { cb->onDrainReady(); });
464 }
465};
466
467class OutputStreamEventCallbackAidl :
468 public StreamCallbackBase,
469 public StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>,
470 public StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>,
471 public ::aidl::android::hardware::audio::core::BnStreamOutEventCallback {
472 public:
473 explicit OutputStreamEventCallbackAidl(const sp<CallbackBroker>& broker)
474 : StreamCallbackBase(broker),
475 StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>(
476 *static_cast<StreamCallbackBase*>(this)),
477 StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>(
478 *static_cast<StreamCallbackBase*>(this)) {}
479 ndk::ScopedAStatus onCodecFormatChanged(const std::vector<uint8_t>& in_audioMetadata) override {
480 std::basic_string<uint8_t> halMetadata(in_audioMetadata.begin(), in_audioMetadata.end());
481 return StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>::runCb(
482 [&halMetadata](auto cb) { cb->onCodecFormatChanged(halMetadata); });
483 }
484 ndk::ScopedAStatus onRecommendedLatencyModeChanged(
485 const std::vector<AudioLatencyMode>& in_modes) override {
486 auto halModes = VALUE_OR_FATAL(
487 ::aidl::android::convertContainer<std::vector<audio_latency_mode_t>>(
488 in_modes,
489 ::aidl::android::aidl2legacy_AudioLatencyMode_audio_latency_mode_t));
490 return StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>::runCb(
491 [&halModes](auto cb) { cb->onRecommendedLatencyModeChanged(halModes); });
492 }
493};
494
495} // namespace
496
Mikhail Naganov31d46652023-01-10 18:29:25 +0000497status_t DeviceHalAidl::openOutputStream(
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800498 audio_io_handle_t handle, audio_devices_t devices,
499 audio_output_flags_t flags, struct audio_config* config,
500 const char* address,
Mikhail Naganov31d46652023-01-10 18:29:25 +0000501 sp<StreamOutHalInterface>* outStream) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800502 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000503 if (!outStream || !config) {
504 return BAD_VALUE;
505 }
506 TIME_CHECK();
507 if (!mModule) return NO_INIT;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800508 int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
509 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(handle));
510 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
511 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, false /*isInput*/));
512 AudioDevice aidlDevice = VALUE_OR_RETURN_STATUS(
513 ::aidl::android::legacy2aidl_audio_device_AudioDevice(devices, address));
514 int32_t aidlOutputFlags = VALUE_OR_RETURN_STATUS(
515 ::aidl::android::legacy2aidl_audio_output_flags_t_int32_t_mask(flags));
516 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::output>(aidlOutputFlags);
517 AudioPortConfig mixPortConfig;
518 Cleanups cleanups;
Mikhail Naganove93a0862023-03-15 17:06:59 -0700519 AudioPatch aidlPatch;
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800520 RETURN_STATUS_IF_ERROR(prepareToOpenStream(aidlHandle, aidlDevice, aidlFlags,
521 AudioSource::SYS_RESERVED_INVALID /*only needed for input*/,
Mikhail Naganove93a0862023-03-15 17:06:59 -0700522 config, &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800523 ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamArguments args;
524 args.portConfigId = mixPortConfig.id;
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800525 const bool isOffload = isBitPositionFlagSet(
526 aidlOutputFlags, AudioOutputFlags::COMPRESS_OFFLOAD);
527 std::shared_ptr<OutputStreamCallbackAidl> streamCb;
528 if (isOffload) {
529 streamCb = ndk::SharedRefBase::make<OutputStreamCallbackAidl>(this);
530 }
531 auto eventCb = ndk::SharedRefBase::make<OutputStreamEventCallbackAidl>(this);
532 if (isOffload) {
533 args.offloadInfo = aidlConfig.offloadInfo;
534 args.callback = streamCb;
535 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800536 args.bufferSizeFrames = aidlConfig.frameCount;
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800537 args.eventCallback = eventCb;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800538 ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamReturn ret;
539 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openOutputStream(args, &ret)));
Mikhail Naganov712d71b2023-02-23 17:57:16 -0800540 StreamContextAidl context(ret.desc, isOffload);
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800541 if (!context.isValid()) {
542 ALOGE("%s: Failed to created a valid stream context from the descriptor: %s",
543 __func__, ret.desc.toString().c_str());
544 return NO_INIT;
545 }
Mikhail Naganove93a0862023-03-15 17:06:59 -0700546 *outStream = sp<StreamOutHalAidl>::make(*config, std::move(context), aidlPatch.latenciesMs[0],
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800547 std::move(ret.stream), this /*callbackBroker*/);
Mikhail Naganove93a0862023-03-15 17:06:59 -0700548 mStreams.insert(std::pair(*outStream, aidlPatch.id));
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800549 void* cbCookie = (*outStream).get();
550 {
551 std::lock_guard l(mLock);
552 mCallbacks.emplace(cbCookie, Callbacks{});
553 }
554 if (streamCb) streamCb->setCookie(cbCookie);
555 eventCb->setCookie(cbCookie);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800556 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000557 return OK;
558}
559
Mikhail Naganov31d46652023-01-10 18:29:25 +0000560status_t DeviceHalAidl::openInputStream(
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800561 audio_io_handle_t handle, audio_devices_t devices,
562 struct audio_config* config, audio_input_flags_t flags,
563 const char* address, audio_source_t source,
564 audio_devices_t outputDevice, const char* outputDeviceAddress,
Mikhail Naganov31d46652023-01-10 18:29:25 +0000565 sp<StreamInHalInterface>* inStream) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800566 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000567 if (!inStream || !config) {
568 return BAD_VALUE;
569 }
570 TIME_CHECK();
571 if (!mModule) return NO_INIT;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800572 int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
573 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(handle));
574 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
575 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, true /*isInput*/));
576 AudioDevice aidlDevice = VALUE_OR_RETURN_STATUS(
577 ::aidl::android::legacy2aidl_audio_device_AudioDevice(devices, address));
578 int32_t aidlInputFlags = VALUE_OR_RETURN_STATUS(
579 ::aidl::android::legacy2aidl_audio_input_flags_t_int32_t_mask(flags));
580 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::input>(aidlInputFlags);
581 AudioSource aidlSource = VALUE_OR_RETURN_STATUS(
582 ::aidl::android::legacy2aidl_audio_source_t_AudioSource(source));
583 AudioPortConfig mixPortConfig;
584 Cleanups cleanups;
Mikhail Naganove93a0862023-03-15 17:06:59 -0700585 AudioPatch aidlPatch;
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800586 RETURN_STATUS_IF_ERROR(prepareToOpenStream(aidlHandle, aidlDevice, aidlFlags, aidlSource,
Mikhail Naganove93a0862023-03-15 17:06:59 -0700587 config, &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800588 ::aidl::android::hardware::audio::core::IModule::OpenInputStreamArguments args;
589 args.portConfigId = mixPortConfig.id;
590 RecordTrackMetadata aidlTrackMetadata{
591 .source = aidlSource, .gain = 1, .channelMask = aidlConfig.base.channelMask };
592 if (outputDevice != AUDIO_DEVICE_NONE) {
593 aidlTrackMetadata.destinationDevice = VALUE_OR_RETURN_STATUS(
594 ::aidl::android::legacy2aidl_audio_device_AudioDevice(
595 outputDevice, outputDeviceAddress));
596 }
597 args.sinkMetadata.tracks.push_back(std::move(aidlTrackMetadata));
598 args.bufferSizeFrames = aidlConfig.frameCount;
599 ::aidl::android::hardware::audio::core::IModule::OpenInputStreamReturn ret;
600 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openInputStream(args, &ret)));
Mikhail Naganov712d71b2023-02-23 17:57:16 -0800601 StreamContextAidl context(ret.desc, false /*isAsynchronous*/);
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800602 if (!context.isValid()) {
603 ALOGE("%s: Failed to created a valid stream context from the descriptor: %s",
604 __func__, ret.desc.toString().c_str());
605 return NO_INIT;
606 }
Mikhail Naganove93a0862023-03-15 17:06:59 -0700607 *inStream = sp<StreamInHalAidl>::make(*config, std::move(context), aidlPatch.latenciesMs[0],
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800608 std::move(ret.stream), this /*micInfoProvider*/);
Mikhail Naganove93a0862023-03-15 17:06:59 -0700609 mStreams.insert(std::pair(*inStream, aidlPatch.id));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800610 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000611 return OK;
612}
613
614status_t DeviceHalAidl::supportsAudioPatches(bool* supportsPatches) {
615 *supportsPatches = true;
616 return OK;
617}
618
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800619status_t DeviceHalAidl::createAudioPatch(unsigned int num_sources,
620 const struct audio_port_config* sources,
621 unsigned int num_sinks,
622 const struct audio_port_config* sinks,
623 audio_patch_handle_t* patch) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800624 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000625 TIME_CHECK();
626 if (!mModule) return NO_INIT;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800627 if (num_sinks > AUDIO_PATCH_PORTS_MAX || num_sources > AUDIO_PATCH_PORTS_MAX ||
628 sources == nullptr || sinks == nullptr || patch == nullptr) {
629 return BAD_VALUE;
630 }
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800631 // When the patch handle (*patch) is AUDIO_PATCH_HANDLE_NONE, it means
632 // the framework wants to create a new patch. The handle has to be generated
633 // by the HAL. Since handles generated this way can only be unique within
634 // a HAL module, the framework generates a globally unique handle, and maps
635 // it on the <HAL module, patch handle> pair.
636 // When the patch handle is set, it meant the framework intends to update
637 // an existing patch.
638 //
639 // This behavior corresponds to HAL module behavior, with the only difference
640 // that the HAL module uses `int32_t` for patch IDs. The following assert ensures
641 // that both the framework and the HAL use the same value for "no ID":
642 static_assert(AUDIO_PATCH_HANDLE_NONE == 0);
643 int32_t halPatchId = static_cast<int32_t>(*patch);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800644
645 // Upon conversion, mix port configs contain audio configuration, while
646 // device port configs contain device address. This data is used to find
647 // or create HAL configs.
648 std::vector<AudioPortConfig> aidlSources, aidlSinks;
649 for (unsigned int i = 0; i < num_sources; ++i) {
650 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
651 sources[i].role, sources[i].type)) ==
652 ::aidl::android::AudioPortDirection::INPUT;
653 aidlSources.push_back(VALUE_OR_RETURN_STATUS(
654 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
655 sources[i], isInput, 0)));
656 }
657 for (unsigned int i = 0; i < num_sinks; ++i) {
658 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
659 sinks[i].role, sinks[i].type)) ==
660 ::aidl::android::AudioPortDirection::INPUT;
661 aidlSinks.push_back(VALUE_OR_RETURN_STATUS(
662 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
663 sinks[i], isInput, 0)));
664 }
665 Cleanups cleanups;
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800666 auto existingPatchIt = halPatchId != 0 ? mPatches.find(halPatchId): mPatches.end();
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800667 AudioPatch aidlPatch;
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800668 if (existingPatchIt != mPatches.end()) {
669 aidlPatch = existingPatchIt->second;
670 aidlPatch.sourcePortConfigIds.clear();
671 aidlPatch.sinkPortConfigIds.clear();
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800672 }
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800673 ALOGD("%s: sources: %s, sinks: %s",
674 __func__, ::android::internal::ToString(aidlSources).c_str(),
675 ::android::internal::ToString(aidlSinks).c_str());
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800676 auto fillPortConfigs = [&](
Mikhail Naganov289468a2023-03-29 10:06:15 -0700677 const std::vector<AudioPortConfig>& configs,
678 const std::set<int32_t>& destinationPortIds,
679 std::vector<int32_t>* ids, std::set<int32_t>* portIds) -> status_t {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800680 for (const auto& s : configs) {
681 AudioPortConfig portConfig;
682 bool created = false;
Mikhail Naganov289468a2023-03-29 10:06:15 -0700683 RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(
684 s, destinationPortIds, &portConfig, &created));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800685 if (created) {
686 cleanups.emplace_front(this, &DeviceHalAidl::resetPortConfig, portConfig.id);
687 }
688 ids->push_back(portConfig.id);
Mikhail Naganov289468a2023-03-29 10:06:15 -0700689 if (portIds != nullptr) {
690 portIds->insert(portConfig.portId);
691 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800692 }
693 return OK;
694 };
Mikhail Naganov289468a2023-03-29 10:06:15 -0700695 // When looking up port configs, the destinationPortId is only used for mix ports.
696 // Thus, we process device port configs first, and look up the destination port ID from them.
697 bool sourceIsDevice = std::any_of(aidlSources.begin(), aidlSources.end(),
698 [](const auto& config) { return config.ext.getTag() == AudioPortExt::device; });
699 const std::vector<AudioPortConfig>& devicePortConfigs =
700 sourceIsDevice ? aidlSources : aidlSinks;
701 std::vector<int32_t>* devicePortConfigIds =
702 sourceIsDevice ? &aidlPatch.sourcePortConfigIds : &aidlPatch.sinkPortConfigIds;
703 const std::vector<AudioPortConfig>& mixPortConfigs =
704 sourceIsDevice ? aidlSinks : aidlSources;
705 std::vector<int32_t>* mixPortConfigIds =
706 sourceIsDevice ? &aidlPatch.sinkPortConfigIds : &aidlPatch.sourcePortConfigIds;
707 std::set<int32_t> devicePortIds;
708 RETURN_STATUS_IF_ERROR(fillPortConfigs(
709 devicePortConfigs, std::set<int32_t>(), devicePortConfigIds, &devicePortIds));
710 RETURN_STATUS_IF_ERROR(fillPortConfigs(
711 mixPortConfigs, devicePortIds, mixPortConfigIds, nullptr));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800712 if (existingPatchIt != mPatches.end()) {
713 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
714 mModule->setAudioPatch(aidlPatch, &aidlPatch)));
715 existingPatchIt->second = aidlPatch;
716 } else {
717 bool created = false;
718 RETURN_STATUS_IF_ERROR(findOrCreatePatch(aidlPatch, &aidlPatch, &created));
719 // Since no cleanup of the patch is needed, 'created' is ignored.
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800720 halPatchId = aidlPatch.id;
721 *patch = static_cast<audio_patch_handle_t>(halPatchId);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800722 }
723 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000724 return OK;
725}
726
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800727status_t DeviceHalAidl::releaseAudioPatch(audio_patch_handle_t patch) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800728 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000729 TIME_CHECK();
730 if (!mModule) return NO_INIT;
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800731 static_assert(AUDIO_PATCH_HANDLE_NONE == 0);
732 if (patch == AUDIO_PATCH_HANDLE_NONE) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800733 return BAD_VALUE;
734 }
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800735 int32_t halPatchId = static_cast<int32_t>(patch);
736 auto patchIt = mPatches.find(halPatchId);
737 if (patchIt == mPatches.end()) {
738 ALOGE("%s: patch with id %d not found", __func__, halPatchId);
739 return BAD_VALUE;
740 }
741 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->resetAudioPatch(halPatchId)));
742 mPatches.erase(patchIt);
Shunkai Yao51202502022-12-12 06:11:46 +0000743 return OK;
744}
745
Mikhail Naganove93a0862023-03-15 17:06:59 -0700746status_t DeviceHalAidl::getAudioPort(struct audio_port* port) {
747 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000748 TIME_CHECK();
749 if (!mModule) return NO_INIT;
Mikhail Naganove93a0862023-03-15 17:06:59 -0700750 if (port == nullptr) {
751 return BAD_VALUE;
752 }
753 audio_port_v7 portV7;
754 audio_populate_audio_port_v7(port, &portV7);
755 RETURN_STATUS_IF_ERROR(getAudioPort(&portV7));
756 return audio_populate_audio_port(&portV7, port) ? OK : BAD_VALUE;
757}
758
759status_t DeviceHalAidl::getAudioPort(struct audio_port_v7 *port) {
760 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
761 TIME_CHECK();
762 if (!mModule) return NO_INIT;
763 if (port == nullptr) {
764 return BAD_VALUE;
765 }
766 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(port->role, port->type)) ==
767 ::aidl::android::AudioPortDirection::INPUT;
768 auto aidlPort = VALUE_OR_RETURN_STATUS(
769 ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
770 if (aidlPort.ext.getTag() != AudioPortExt::device) {
771 ALOGE("%s: provided port is not a device port (module %s): %s",
772 __func__, mInstance.c_str(), aidlPort.toString().c_str());
773 return BAD_VALUE;
774 }
775 const auto& matchDevice = aidlPort.ext.get<AudioPortExt::device>().device;
776 // It seems that we don't have to call HAL since all valid ports have been added either
777 // during initialization, or while handling connection of an external device.
778 auto portsIt = findPort(matchDevice);
779 if (portsIt == mPorts.end()) {
780 ALOGE("%s: device port for device %s is not found in the module %s",
781 __func__, matchDevice.toString().c_str(), mInstance.c_str());
782 return BAD_VALUE;
783 }
784 const int32_t fwkId = aidlPort.id;
785 aidlPort = portsIt->second;
786 aidlPort.id = fwkId;
787 *port = VALUE_OR_RETURN_STATUS(::aidl::android::aidl2legacy_AudioPort_audio_port_v7(
788 aidlPort, isInput));
789 return OK;
790}
791
792status_t DeviceHalAidl::setAudioPortConfig(const struct audio_port_config* config) {
793 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
794 TIME_CHECK();
795 if (!mModule) return NO_INIT;
796 if (config == nullptr) {
797 return BAD_VALUE;
798 }
799 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
800 config->role, config->type)) == ::aidl::android::AudioPortDirection::INPUT;
801 AudioPortConfig requestedPortConfig = VALUE_OR_RETURN_STATUS(
802 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
803 *config, isInput, 0 /*portId*/));
804 AudioPortConfig portConfig;
805 bool created = false;
Mikhail Naganov289468a2023-03-29 10:06:15 -0700806 RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(
807 requestedPortConfig, std::set<int32_t>(), &portConfig, &created));
Shunkai Yao51202502022-12-12 06:11:46 +0000808 return OK;
809}
810
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800811MicrophoneInfoProvider::Info const* DeviceHalAidl::getMicrophoneInfo() {
812 if (mMicrophones.status == Microphones::Status::UNKNOWN) {
813 TIME_CHECK();
814 std::vector<MicrophoneInfo> aidlInfo;
815 status_t status = statusTFromBinderStatus(mModule->getMicrophones(&aidlInfo));
816 if (status == OK) {
817 mMicrophones.status = Microphones::Status::QUERIED;
818 mMicrophones.info = std::move(aidlInfo);
819 } else if (status == INVALID_OPERATION) {
820 mMicrophones.status = Microphones::Status::NOT_SUPPORTED;
821 } else {
822 ALOGE("%s: Unexpected status from 'IModule.getMicrophones': %d", __func__, status);
823 return {};
824 }
825 }
826 if (mMicrophones.status == Microphones::Status::QUERIED) {
827 return &mMicrophones.info;
828 }
829 return {}; // NOT_SUPPORTED
830}
831
Shunkai Yao51202502022-12-12 06:11:46 +0000832status_t DeviceHalAidl::getMicrophones(
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800833 std::vector<audio_microphone_characteristic_t>* microphones) {
834 if (!microphones) {
835 return BAD_VALUE;
836 }
Mikhail Naganov31d46652023-01-10 18:29:25 +0000837 TIME_CHECK();
838 if (!mModule) return NO_INIT;
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800839 auto staticInfo = getMicrophoneInfo();
840 if (!staticInfo) return INVALID_OPERATION;
841 std::vector<MicrophoneDynamicInfo> emptyDynamicInfo;
842 emptyDynamicInfo.reserve(staticInfo->size());
843 std::transform(staticInfo->begin(), staticInfo->end(), std::back_inserter(emptyDynamicInfo),
844 [](const auto& info) { return MicrophoneDynamicInfo{ .id = info.id }; });
845 *microphones = VALUE_OR_RETURN_STATUS(
846 ::aidl::android::convertContainers<std::vector<audio_microphone_characteristic_t>>(
847 *staticInfo, emptyDynamicInfo,
848 ::aidl::android::aidl2legacy_MicrophoneInfos_audio_microphone_characteristic_t)
849 );
Shunkai Yao51202502022-12-12 06:11:46 +0000850 return OK;
851}
852
Mikhail Naganov31d46652023-01-10 18:29:25 +0000853status_t DeviceHalAidl::addDeviceEffect(audio_port_handle_t device __unused,
854 sp<EffectHalInterface> effect) {
Shunkai Yao51202502022-12-12 06:11:46 +0000855 if (!effect) {
856 return BAD_VALUE;
857 }
Mikhail Naganov31d46652023-01-10 18:29:25 +0000858 TIME_CHECK();
859 if (!mModule) return NO_INIT;
860 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000861 return OK;
862}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000863status_t DeviceHalAidl::removeDeviceEffect(audio_port_handle_t device __unused,
Shunkai Yao51202502022-12-12 06:11:46 +0000864 sp<EffectHalInterface> effect) {
865 if (!effect) {
866 return BAD_VALUE;
867 }
Mikhail Naganov31d46652023-01-10 18:29:25 +0000868 TIME_CHECK();
869 if (!mModule) return NO_INIT;
870 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000871 return OK;
872}
873
874status_t DeviceHalAidl::getMmapPolicyInfos(
David Li9cf5e622023-03-21 00:51:10 +0800875 media::audio::common::AudioMMapPolicyType policyType,
876 std::vector<media::audio::common::AudioMMapPolicyInfo>* policyInfos) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000877 TIME_CHECK();
Mikhail Naganov25bc9a22023-04-21 18:48:16 -0700878 AudioMMapPolicyType mmapPolicyType = VALUE_OR_RETURN_STATUS(
879 cpp2ndk_AudioMMapPolicyType(policyType));
David Li9cf5e622023-03-21 00:51:10 +0800880
881 std::vector<AudioMMapPolicyInfo> mmapPolicyInfos;
882
883 if (status_t status = statusTFromBinderStatus(
884 mModule->getMmapPolicyInfos(mmapPolicyType, &mmapPolicyInfos)); status != OK) {
885 return status;
886 }
887
888 *policyInfos = VALUE_OR_RETURN_STATUS(
889 convertContainer<std::vector<media::audio::common::AudioMMapPolicyInfo>>(
890 mmapPolicyInfos, ndk2cpp_AudioMMapPolicyInfo));
Shunkai Yao51202502022-12-12 06:11:46 +0000891 return OK;
892}
893
894int32_t DeviceHalAidl::getAAudioMixerBurstCount() {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000895 TIME_CHECK();
David Li9cf5e622023-03-21 00:51:10 +0800896 int32_t mixerBurstCount = 0;
897 if (mModule->getAAudioMixerBurstCount(&mixerBurstCount).isOk()) {
898 return mixerBurstCount;
899 }
900 return 0;
Shunkai Yao51202502022-12-12 06:11:46 +0000901}
902
903int32_t DeviceHalAidl::getAAudioHardwareBurstMinUsec() {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000904 TIME_CHECK();
David Li9cf5e622023-03-21 00:51:10 +0800905 int32_t hardwareBurstMinUsec = 0;
906 if (mModule->getAAudioHardwareBurstMinUsec(&hardwareBurstMinUsec).isOk()) {
907 return hardwareBurstMinUsec;
908 }
909 return 0;
Shunkai Yao51202502022-12-12 06:11:46 +0000910}
911
912error::Result<audio_hw_sync_t> DeviceHalAidl::getHwAvSync() {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000913 TIME_CHECK();
Mikhail Naganov08a62ab2023-03-14 17:11:51 -0700914 if (!mModule) return NO_INIT;
915 int32_t aidlHwAvSync;
916 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->generateHwAvSyncId(&aidlHwAvSync)));
917 return VALUE_OR_RETURN_STATUS(
918 ::aidl::android::aidl2legacy_int32_t_audio_hw_sync_t(aidlHwAvSync));
Shunkai Yao51202502022-12-12 06:11:46 +0000919}
920
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000921status_t DeviceHalAidl::dump(int fd, const Vector<String16>& args) {
922 TIME_CHECK();
923 if (!mModule) return NO_INIT;
924 return mModule->dump(fd, Args(args).args(), args.size());
David Li9cf5e622023-03-21 00:51:10 +0800925}
Shunkai Yao51202502022-12-12 06:11:46 +0000926
Mikhail Naganov3ac95c92023-04-12 13:14:30 -0700927int32_t DeviceHalAidl::supportsBluetoothVariableLatency(bool* supports) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000928 TIME_CHECK();
Mikhail Naganov3ac95c92023-04-12 13:14:30 -0700929 if (!mModule) return NO_INIT;
930 if (supports == nullptr) {
931 return BAD_VALUE;
932 }
933 return statusTFromBinderStatus(mModule->supportsVariableLatency(supports));
Shunkai Yao51202502022-12-12 06:11:46 +0000934}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000935
jiabin872de702023-04-27 22:04:31 +0000936
937status_t DeviceHalAidl::prepareToDisconnectExternalDevice(const struct audio_port_v7* port) {
938 // There is not AIDL API defined for `prepareToDisconnectExternalDevice`.
939 // Call `setConnectedState` instead.
940 // TODO(b/279824103): call prepareToDisconnectExternalDevice when it is added.
941 const status_t status = setConnectedState(port, false /*connected*/);
942 if (status == NO_ERROR) {
943 mDeviceDisconnectionNotified.insert(port->id);
944 }
945 return status;
946}
947
Mikhail Naganove93a0862023-03-15 17:06:59 -0700948status_t DeviceHalAidl::setConnectedState(const struct audio_port_v7 *port, bool connected) {
949 TIME_CHECK();
950 if (!mModule) return NO_INIT;
951 if (port == nullptr) {
952 return BAD_VALUE;
953 }
jiabin872de702023-04-27 22:04:31 +0000954 if (!connected && mDeviceDisconnectionNotified.erase(port->id) > 0) {
955 // For device disconnection, APM will first call `prepareToDisconnectExternalDevice`
956 // and then call `setConnectedState`. However, there is no API for
957 // `prepareToDisconnectExternalDevice` yet. In that case, `setConnectedState` will be
958 // called when calling `prepareToDisconnectExternalDevice`. Do not call to the HAL if
959 // previous call is successful. Also remove the cache here to avoid a large cache after
960 // a long run.
961 return NO_ERROR;
962 }
Mikhail Naganove93a0862023-03-15 17:06:59 -0700963 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(port->role, port->type)) ==
964 ::aidl::android::AudioPortDirection::INPUT;
965 AudioPort aidlPort = VALUE_OR_RETURN_STATUS(
966 ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
967 if (aidlPort.ext.getTag() != AudioPortExt::device) {
968 ALOGE("%s: provided port is not a device port (module %s): %s",
969 __func__, mInstance.c_str(), aidlPort.toString().c_str());
970 return BAD_VALUE;
971 }
972 if (connected) {
973 AudioDevice matchDevice = aidlPort.ext.get<AudioPortExt::device>().device;
974 // Reset the device address to find the "template" port.
975 matchDevice.address = AudioDeviceAddress::make<AudioDeviceAddress::id>();
976 auto portsIt = findPort(matchDevice);
977 if (portsIt == mPorts.end()) {
978 ALOGW("%s: device port for device %s is not found in the module %s",
979 __func__, matchDevice.toString().c_str(), mInstance.c_str());
980 return BAD_VALUE;
981 }
982 // Use the ID of the "template" port, use all the information from the provided port.
983 aidlPort.id = portsIt->first;
984 AudioPort connectedPort;
985 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->connectExternalDevice(
986 aidlPort, &connectedPort)));
987 const auto [it, inserted] = mPorts.insert(std::make_pair(connectedPort.id, connectedPort));
988 LOG_ALWAYS_FATAL_IF(!inserted,
989 "%s: module %s, duplicate port ID received from HAL: %s, existing port: %s",
990 __func__, mInstance.c_str(), connectedPort.toString().c_str(),
991 it->second.toString().c_str());
992 } else { // !connected
993 AudioDevice matchDevice = aidlPort.ext.get<AudioPortExt::device>().device;
994 auto portsIt = findPort(matchDevice);
995 if (portsIt == mPorts.end()) {
996 ALOGW("%s: device port for device %s is not found in the module %s",
997 __func__, matchDevice.toString().c_str(), mInstance.c_str());
998 return BAD_VALUE;
999 }
1000 // Any streams opened on the external device must be closed by this time,
1001 // thus we can clean up patches and port configs that were created for them.
1002 resetUnusedPatchesAndPortConfigs();
1003 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->disconnectExternalDevice(
1004 portsIt->second.id)));
1005 mPorts.erase(portsIt);
1006 }
Mikhail Naganov289468a2023-03-29 10:06:15 -07001007 return updateRoutes();
Mikhail Naganove93a0862023-03-15 17:06:59 -07001008}
1009
1010status_t DeviceHalAidl::setSimulateDeviceConnections(bool enabled) {
1011 TIME_CHECK();
1012 if (!mModule) return NO_INIT;
1013 ModuleDebug debug{ .simulateDeviceConnections = enabled };
1014 status_t status = statusTFromBinderStatus(mModule->setModuleDebug(debug));
1015 // This is important to log as it affects HAL behavior.
1016 if (status == OK) {
1017 ALOGI("%s: set enabled: %d", __func__, enabled);
1018 } else {
1019 ALOGW("%s: set enabled to %d failed: %d", __func__, enabled, status);
1020 }
1021 return status;
1022}
1023
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001024bool DeviceHalAidl::audioDeviceMatches(const AudioDevice& device, const AudioPort& p) {
1025 if (p.ext.getTag() != AudioPortExt::Tag::device) return false;
1026 return p.ext.get<AudioPortExt::Tag::device>().device == device;
1027}
1028
1029bool DeviceHalAidl::audioDeviceMatches(const AudioDevice& device, const AudioPortConfig& p) {
1030 if (p.ext.getTag() != AudioPortExt::Tag::device) return false;
1031 if (device.type.type == AudioDeviceType::IN_DEFAULT) {
1032 return p.portId == mDefaultInputPortId;
1033 } else if (device.type.type == AudioDeviceType::OUT_DEFAULT) {
1034 return p.portId == mDefaultOutputPortId;
1035 }
1036 return p.ext.get<AudioPortExt::Tag::device>().device == device;
1037}
1038
David Lia8675d42023-03-30 21:08:06 +08001039status_t DeviceHalAidl::createOrUpdatePortConfig(
1040 const AudioPortConfig& requestedPortConfig, PortConfigs::iterator* result, bool* created) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001041 TIME_CHECK();
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001042 AudioPortConfig appliedPortConfig;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001043 bool applied = false;
1044 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPortConfig(
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001045 requestedPortConfig, &appliedPortConfig, &applied)));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001046 if (!applied) {
1047 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPortConfig(
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001048 appliedPortConfig, &appliedPortConfig, &applied)));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001049 if (!applied) {
1050 ALOGE("%s: module %s did not apply suggested config %s",
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001051 __func__, mInstance.c_str(), appliedPortConfig.toString().c_str());
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001052 return NO_INIT;
1053 }
1054 }
David Lia8675d42023-03-30 21:08:06 +08001055
1056 int32_t id = appliedPortConfig.id;
1057 if (requestedPortConfig.id != 0 && requestedPortConfig.id != id) {
1058 LOG_ALWAYS_FATAL("%s: requested port config id %d changed to %d", __func__,
1059 requestedPortConfig.id, id);
1060 }
1061
1062 auto [it, inserted] = mPortConfigs.insert_or_assign(std::move(id),
1063 std::move(appliedPortConfig));
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001064 *result = it;
David Lia8675d42023-03-30 21:08:06 +08001065 *created = inserted;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001066 return OK;
1067}
1068
1069status_t DeviceHalAidl::findOrCreatePatch(
1070 const AudioPatch& requestedPatch, AudioPatch* patch, bool* created) {
1071 std::set<int32_t> sourcePortConfigIds(requestedPatch.sourcePortConfigIds.begin(),
1072 requestedPatch.sourcePortConfigIds.end());
1073 std::set<int32_t> sinkPortConfigIds(requestedPatch.sinkPortConfigIds.begin(),
1074 requestedPatch.sinkPortConfigIds.end());
1075 return findOrCreatePatch(sourcePortConfigIds, sinkPortConfigIds, patch, created);
1076}
1077
1078status_t DeviceHalAidl::findOrCreatePatch(
1079 const std::set<int32_t>& sourcePortConfigIds, const std::set<int32_t>& sinkPortConfigIds,
1080 AudioPatch* patch, bool* created) {
1081 auto patchIt = findPatch(sourcePortConfigIds, sinkPortConfigIds);
1082 if (patchIt == mPatches.end()) {
1083 TIME_CHECK();
1084 AudioPatch requestedPatch, appliedPatch;
1085 requestedPatch.sourcePortConfigIds.insert(requestedPatch.sourcePortConfigIds.end(),
1086 sourcePortConfigIds.begin(), sourcePortConfigIds.end());
1087 requestedPatch.sinkPortConfigIds.insert(requestedPatch.sinkPortConfigIds.end(),
1088 sinkPortConfigIds.begin(), sinkPortConfigIds.end());
1089 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPatch(
1090 requestedPatch, &appliedPatch)));
1091 patchIt = mPatches.insert(mPatches.end(), std::make_pair(appliedPatch.id, appliedPatch));
1092 *created = true;
1093 } else {
1094 *created = false;
1095 }
1096 *patch = patchIt->second;
1097 return OK;
1098}
1099
jiabin9c07faf2023-04-26 22:00:44 +00001100status_t DeviceHalAidl::findOrCreatePortConfig(const AudioDevice& device, const AudioConfig* config,
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001101 AudioPortConfig* portConfig, bool* created) {
1102 auto portConfigIt = findPortConfig(device);
1103 if (portConfigIt == mPortConfigs.end()) {
1104 auto portsIt = findPort(device);
1105 if (portsIt == mPorts.end()) {
1106 ALOGE("%s: device port for device %s is not found in the module %s",
1107 __func__, device.toString().c_str(), mInstance.c_str());
1108 return BAD_VALUE;
1109 }
1110 AudioPortConfig requestedPortConfig;
1111 requestedPortConfig.portId = portsIt->first;
jiabin9c07faf2023-04-26 22:00:44 +00001112 if (config != nullptr) {
1113 setPortConfigFromConfig(&requestedPortConfig, *config);
1114 }
David Lia8675d42023-03-30 21:08:06 +08001115 RETURN_STATUS_IF_ERROR(createOrUpdatePortConfig(requestedPortConfig, &portConfigIt,
1116 created));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001117 } else {
1118 *created = false;
1119 }
1120 *portConfig = portConfigIt->second;
1121 return OK;
1122}
1123
1124status_t DeviceHalAidl::findOrCreatePortConfig(
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001125 const AudioConfig& config, const std::optional<AudioIoFlags>& flags, int32_t ioHandle,
Mikhail Naganov289468a2023-03-29 10:06:15 -07001126 AudioSource source, const std::set<int32_t>& destinationPortIds,
1127 AudioPortConfig* portConfig, bool* created) {
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001128 // These flags get removed one by one in this order when retrying port finding.
1129 static const std::vector<AudioInputFlags> kOptionalInputFlags{
1130 AudioInputFlags::FAST, AudioInputFlags::RAW };
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001131 auto portConfigIt = findPortConfig(config, flags, ioHandle);
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001132 if (portConfigIt == mPortConfigs.end() && flags.has_value()) {
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001133 auto optionalInputFlagsIt = kOptionalInputFlags.begin();
1134 AudioIoFlags matchFlags = flags.value();
Mikhail Naganov289468a2023-03-29 10:06:15 -07001135 auto portsIt = findPort(config, matchFlags, destinationPortIds);
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001136 while (portsIt == mPorts.end() && matchFlags.getTag() == AudioIoFlags::Tag::input
1137 && optionalInputFlagsIt != kOptionalInputFlags.end()) {
1138 if (!isBitPositionFlagSet(
1139 matchFlags.get<AudioIoFlags::Tag::input>(), *optionalInputFlagsIt)) {
1140 ++optionalInputFlagsIt;
1141 continue;
1142 }
1143 matchFlags.set<AudioIoFlags::Tag::input>(matchFlags.get<AudioIoFlags::Tag::input>() &
1144 ~makeBitPositionFlagMask(*optionalInputFlagsIt++));
Mikhail Naganov289468a2023-03-29 10:06:15 -07001145 portsIt = findPort(config, matchFlags, destinationPortIds);
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001146 ALOGI("%s: mix port for config %s, flags %s was not found in the module %s, "
1147 "retried with flags %s", __func__, config.toString().c_str(),
1148 flags.value().toString().c_str(), mInstance.c_str(),
1149 matchFlags.toString().c_str());
1150 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001151 if (portsIt == mPorts.end()) {
1152 ALOGE("%s: mix port for config %s, flags %s is not found in the module %s",
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001153 __func__, config.toString().c_str(), matchFlags.toString().c_str(),
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001154 mInstance.c_str());
1155 return BAD_VALUE;
1156 }
1157 AudioPortConfig requestedPortConfig;
1158 requestedPortConfig.portId = portsIt->first;
1159 setPortConfigFromConfig(&requestedPortConfig, config);
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001160 requestedPortConfig.ext = AudioPortMixExt{ .handle = ioHandle };
Mikhail Naganovd8d01f72023-03-09 16:24:40 -08001161 if (matchFlags.getTag() == AudioIoFlags::Tag::input
1162 && source != AudioSource::SYS_RESERVED_INVALID) {
1163 requestedPortConfig.ext.get<AudioPortExt::Tag::mix>().usecase =
1164 AudioPortMixExtUseCase::make<AudioPortMixExtUseCase::Tag::source>(source);
1165 }
David Lia8675d42023-03-30 21:08:06 +08001166 RETURN_STATUS_IF_ERROR(createOrUpdatePortConfig(requestedPortConfig, &portConfigIt,
1167 created));
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001168 } else if (!flags.has_value()) {
1169 ALOGW("%s: mix port config for %s, handle %d not found in the module %s, "
1170 "and was not created as flags are not specified",
1171 __func__, config.toString().c_str(), ioHandle, mInstance.c_str());
1172 return BAD_VALUE;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001173 } else {
David Lia8675d42023-03-30 21:08:06 +08001174 AudioPortConfig requestedPortConfig = portConfigIt->second;
1175 if (requestedPortConfig.ext.getTag() == AudioPortExt::Tag::mix) {
1176 AudioPortMixExt& mixExt = requestedPortConfig.ext.get<AudioPortExt::Tag::mix>();
1177 if (mixExt.usecase.getTag() == AudioPortMixExtUseCase::Tag::source &&
1178 source != AudioSource::SYS_RESERVED_INVALID) {
1179 mixExt.usecase.get<AudioPortMixExtUseCase::Tag::source>() = source;
1180 }
1181 }
1182
1183 if (requestedPortConfig != portConfigIt->second) {
1184 RETURN_STATUS_IF_ERROR(createOrUpdatePortConfig(requestedPortConfig, &portConfigIt,
1185 created));
1186 } else {
1187 *created = false;
1188 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001189 }
1190 *portConfig = portConfigIt->second;
1191 return OK;
1192}
1193
1194status_t DeviceHalAidl::findOrCreatePortConfig(
Mikhail Naganov289468a2023-03-29 10:06:15 -07001195 const AudioPortConfig& requestedPortConfig, const std::set<int32_t>& destinationPortIds,
1196 AudioPortConfig* portConfig, bool* created) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001197 using Tag = AudioPortExt::Tag;
1198 if (requestedPortConfig.ext.getTag() == Tag::mix) {
1199 if (const auto& p = requestedPortConfig;
1200 !p.sampleRate.has_value() || !p.channelMask.has_value() ||
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001201 !p.format.has_value()) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001202 ALOGW("%s: provided mix port config is not fully specified: %s",
1203 __func__, p.toString().c_str());
1204 return BAD_VALUE;
1205 }
1206 AudioConfig config;
1207 setConfigFromPortConfig(&config, requestedPortConfig);
Mikhail Naganovd8d01f72023-03-09 16:24:40 -08001208 AudioSource source = requestedPortConfig.ext.get<Tag::mix>().usecase.getTag() ==
1209 AudioPortMixExtUseCase::Tag::source ?
1210 requestedPortConfig.ext.get<Tag::mix>().usecase.
1211 get<AudioPortMixExtUseCase::Tag::source>() : AudioSource::SYS_RESERVED_INVALID;
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001212 return findOrCreatePortConfig(config, requestedPortConfig.flags,
Mikhail Naganov289468a2023-03-29 10:06:15 -07001213 requestedPortConfig.ext.get<Tag::mix>().handle, source, destinationPortIds,
1214 portConfig, created);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001215 } else if (requestedPortConfig.ext.getTag() == Tag::device) {
1216 return findOrCreatePortConfig(
jiabin9c07faf2023-04-26 22:00:44 +00001217 requestedPortConfig.ext.get<Tag::device>().device, nullptr /*config*/,
1218 portConfig, created);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001219 }
1220 ALOGW("%s: unsupported audio port config: %s",
1221 __func__, requestedPortConfig.toString().c_str());
1222 return BAD_VALUE;
1223}
1224
1225DeviceHalAidl::Patches::iterator DeviceHalAidl::findPatch(
1226 const std::set<int32_t>& sourcePortConfigIds, const std::set<int32_t>& sinkPortConfigIds) {
1227 return std::find_if(mPatches.begin(), mPatches.end(),
1228 [&](const auto& pair) {
1229 const auto& p = pair.second;
1230 std::set<int32_t> patchSrcs(
1231 p.sourcePortConfigIds.begin(), p.sourcePortConfigIds.end());
1232 std::set<int32_t> patchSinks(
1233 p.sinkPortConfigIds.begin(), p.sinkPortConfigIds.end());
1234 return sourcePortConfigIds == patchSrcs && sinkPortConfigIds == patchSinks; });
1235}
1236
1237DeviceHalAidl::Ports::iterator DeviceHalAidl::findPort(const AudioDevice& device) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001238 if (device.type.type == AudioDeviceType::IN_DEFAULT) {
1239 return mPorts.find(mDefaultInputPortId);
1240 } else if (device.type.type == AudioDeviceType::OUT_DEFAULT) {
1241 return mPorts.find(mDefaultOutputPortId);
1242 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001243 return std::find_if(mPorts.begin(), mPorts.end(),
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001244 [&](const auto& pair) { return audioDeviceMatches(device, pair.second); });
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001245}
1246
1247DeviceHalAidl::Ports::iterator DeviceHalAidl::findPort(
Mikhail Naganov289468a2023-03-29 10:06:15 -07001248 const AudioConfig& config, const AudioIoFlags& flags,
1249 const std::set<int32_t>& destinationPortIds) {
Mikhail Naganove93a0862023-03-15 17:06:59 -07001250 auto belongsToProfile = [&config](const AudioProfile& prof) {
1251 return (isDefaultAudioFormat(config.base.format) || prof.format == config.base.format) &&
1252 (config.base.channelMask.getTag() == AudioChannelLayout::none ||
1253 std::find(prof.channelMasks.begin(), prof.channelMasks.end(),
1254 config.base.channelMask) != prof.channelMasks.end()) &&
1255 (config.base.sampleRate == 0 ||
1256 std::find(prof.sampleRates.begin(), prof.sampleRates.end(),
1257 config.base.sampleRate) != prof.sampleRates.end());
1258 };
jiabin9c07faf2023-04-26 22:00:44 +00001259 static const std::vector<AudioOutputFlags> kOptionalOutputFlags{AudioOutputFlags::BIT_PERFECT};
1260 int optionalFlags = 0;
1261 auto flagMatches = [&flags, &optionalFlags](const AudioIoFlags& portFlags) {
1262 // Ports should be able to match if the optional flags are not requested.
1263 return portFlags == flags ||
1264 (portFlags.getTag() == AudioIoFlags::Tag::output &&
1265 AudioIoFlags::make<AudioIoFlags::Tag::output>(
1266 portFlags.get<AudioIoFlags::Tag::output>() &
1267 ~optionalFlags) == flags);
1268 };
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001269 auto matcher = [&](const auto& pair) {
1270 const auto& p = pair.second;
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001271 return p.ext.getTag() == AudioPortExt::Tag::mix &&
jiabin9c07faf2023-04-26 22:00:44 +00001272 flagMatches(p.flags) &&
Mikhail Naganov289468a2023-03-29 10:06:15 -07001273 (destinationPortIds.empty() ||
1274 std::any_of(destinationPortIds.begin(), destinationPortIds.end(),
1275 [&](const int32_t destId) { return mRoutingMatrix.count(
1276 std::make_pair(p.id, destId)) != 0; })) &&
Mikhail Naganove93a0862023-03-15 17:06:59 -07001277 (p.profiles.empty() ||
1278 std::find_if(p.profiles.begin(), p.profiles.end(), belongsToProfile) !=
1279 p.profiles.end()); };
jiabin9c07faf2023-04-26 22:00:44 +00001280 auto result = std::find_if(mPorts.begin(), mPorts.end(), matcher);
1281 if (result == mPorts.end() && flags.getTag() == AudioIoFlags::Tag::output) {
1282 auto optionalOutputFlagsIt = kOptionalOutputFlags.begin();
1283 while (result == mPorts.end() && optionalOutputFlagsIt != kOptionalOutputFlags.end()) {
1284 if (isBitPositionFlagSet(
1285 flags.get<AudioIoFlags::Tag::output>(), *optionalOutputFlagsIt)) {
1286 // If the flag is set by the request, it must be matched.
1287 ++optionalOutputFlagsIt;
1288 continue;
1289 }
1290 optionalFlags |= makeBitPositionFlagMask(*optionalOutputFlagsIt++);
1291 result = std::find_if(mPorts.begin(), mPorts.end(), matcher);
1292 ALOGI("%s: port for config %s, flags %s was not found in the module %s, "
1293 "retried with excluding optional flags %#x", __func__, config.toString().c_str(),
1294 flags.toString().c_str(), mInstance.c_str(), optionalFlags);
1295 }
1296 }
1297 return result;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001298}
1299
1300DeviceHalAidl::PortConfigs::iterator DeviceHalAidl::findPortConfig(const AudioDevice& device) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001301 return std::find_if(mPortConfigs.begin(), mPortConfigs.end(),
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001302 [&](const auto& pair) { return audioDeviceMatches(device, pair.second); });
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001303}
1304
1305DeviceHalAidl::PortConfigs::iterator DeviceHalAidl::findPortConfig(
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001306 const AudioConfig& config, const std::optional<AudioIoFlags>& flags, int32_t ioHandle) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001307 using Tag = AudioPortExt::Tag;
1308 return std::find_if(mPortConfigs.begin(), mPortConfigs.end(),
1309 [&](const auto& pair) {
1310 const auto& p = pair.second;
1311 LOG_ALWAYS_FATAL_IF(p.ext.getTag() == Tag::mix &&
1312 !p.sampleRate.has_value() || !p.channelMask.has_value() ||
1313 !p.format.has_value() || !p.flags.has_value(),
1314 "%s: stored mix port config is not fully specified: %s",
1315 __func__, p.toString().c_str());
1316 return p.ext.getTag() == Tag::mix &&
1317 isConfigEqualToPortConfig(config, p) &&
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001318 (!flags.has_value() || p.flags.value() == flags.value()) &&
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001319 p.ext.template get<Tag::mix>().handle == ioHandle; });
1320}
Mikhail Naganove93a0862023-03-15 17:06:59 -07001321
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001322void DeviceHalAidl::resetPatch(int32_t patchId) {
1323 if (auto it = mPatches.find(patchId); it != mPatches.end()) {
1324 mPatches.erase(it);
1325 TIME_CHECK();
1326 if (ndk::ScopedAStatus status = mModule->resetAudioPatch(patchId); !status.isOk()) {
1327 ALOGE("%s: error while resetting patch %d: %s",
1328 __func__, patchId, status.getDescription().c_str());
1329 }
1330 return;
1331 }
1332 ALOGE("%s: patch id %d not found", __func__, patchId);
1333}
1334
1335void DeviceHalAidl::resetPortConfig(int32_t portConfigId) {
1336 if (auto it = mPortConfigs.find(portConfigId); it != mPortConfigs.end()) {
1337 mPortConfigs.erase(it);
1338 TIME_CHECK();
1339 if (ndk::ScopedAStatus status = mModule->resetAudioPortConfig(portConfigId);
1340 !status.isOk()) {
1341 ALOGE("%s: error while resetting port config %d: %s",
1342 __func__, portConfigId, status.getDescription().c_str());
1343 }
1344 return;
1345 }
1346 ALOGE("%s: port config id %d not found", __func__, portConfigId);
1347}
1348
Mikhail Naganove93a0862023-03-15 17:06:59 -07001349void DeviceHalAidl::resetUnusedPatches() {
1350 // Since patches can be created independently of streams via 'createAudioPatch',
1351 // here we only clean up patches for released streams.
1352 for (auto it = mStreams.begin(); it != mStreams.end(); ) {
1353 if (auto streamSp = it->first.promote(); streamSp) {
1354 ++it;
1355 } else {
1356 resetPatch(it->second);
1357 it = mStreams.erase(it);
1358 }
1359 }
1360}
1361
1362void DeviceHalAidl::resetUnusedPatchesAndPortConfigs() {
1363 resetUnusedPatches();
1364 resetUnusedPortConfigs();
1365}
1366
1367void DeviceHalAidl::resetUnusedPortConfigs() {
1368 // The assumption is that port configs are used to create patches
1369 // (or to open streams, but that involves creation of patches, too). Thus,
1370 // orphaned port configs can and should be reset.
1371 std::set<int32_t> portConfigIds;
1372 std::transform(mPortConfigs.begin(), mPortConfigs.end(),
1373 std::inserter(portConfigIds, portConfigIds.end()),
1374 [](const auto& pcPair) { return pcPair.first; });
1375 for (const auto& p : mPatches) {
1376 for (int32_t id : p.second.sourcePortConfigIds) portConfigIds.erase(id);
1377 for (int32_t id : p.second.sinkPortConfigIds) portConfigIds.erase(id);
1378 }
jiabin9c07faf2023-04-26 22:00:44 +00001379 for (int32_t id : mInitialPortConfigIds) {
1380 portConfigIds.erase(id);
1381 }
Mikhail Naganove93a0862023-03-15 17:06:59 -07001382 for (int32_t id : portConfigIds) resetPortConfig(id);
1383}
1384
Mikhail Naganov289468a2023-03-29 10:06:15 -07001385status_t DeviceHalAidl::updateRoutes() {
1386 TIME_CHECK();
Mikhail Naganov289468a2023-03-29 10:06:15 -07001387 RETURN_STATUS_IF_ERROR(
Mikhail Naganovf83b9742023-04-24 13:06:04 -07001388 statusTFromBinderStatus(mModule->getAudioRoutes(&mRoutes)));
1389 ALOGW_IF(mRoutes.empty(), "%s: module %s returned an empty list of audio routes",
Mikhail Naganov289468a2023-03-29 10:06:15 -07001390 __func__, mInstance.c_str());
1391 mRoutingMatrix.clear();
Mikhail Naganovf83b9742023-04-24 13:06:04 -07001392 for (const auto& r : mRoutes) {
Mikhail Naganov289468a2023-03-29 10:06:15 -07001393 for (auto portId : r.sourcePortIds) {
1394 mRoutingMatrix.emplace(r.sinkPortId, portId);
1395 mRoutingMatrix.emplace(portId, r.sinkPortId);
1396 }
1397 }
1398 return OK;
1399}
1400
Mikhail Naganovdfd594e2023-02-08 16:59:41 -08001401void DeviceHalAidl::clearCallbacks(void* cookie) {
1402 std::lock_guard l(mLock);
1403 mCallbacks.erase(cookie);
1404}
1405
1406sp<StreamOutHalInterfaceCallback> DeviceHalAidl::getStreamOutCallback(void* cookie) {
1407 return getCallbackImpl(cookie, &Callbacks::out);
1408}
1409
1410void DeviceHalAidl::setStreamOutCallback(
1411 void* cookie, const sp<StreamOutHalInterfaceCallback>& cb) {
1412 setCallbackImpl(cookie, &Callbacks::out, cb);
1413}
1414
1415sp<StreamOutHalInterfaceEventCallback> DeviceHalAidl::getStreamOutEventCallback(
1416 void* cookie) {
1417 return getCallbackImpl(cookie, &Callbacks::event);
1418}
1419
1420void DeviceHalAidl::setStreamOutEventCallback(
1421 void* cookie, const sp<StreamOutHalInterfaceEventCallback>& cb) {
1422 setCallbackImpl(cookie, &Callbacks::event, cb);
1423}
1424
1425sp<StreamOutHalInterfaceLatencyModeCallback> DeviceHalAidl::getStreamOutLatencyModeCallback(
1426 void* cookie) {
1427 return getCallbackImpl(cookie, &Callbacks::latency);
1428}
1429
1430void DeviceHalAidl::setStreamOutLatencyModeCallback(
1431 void* cookie, const sp<StreamOutHalInterfaceLatencyModeCallback>& cb) {
1432 setCallbackImpl(cookie, &Callbacks::latency, cb);
1433}
1434
1435template<class C>
1436sp<C> DeviceHalAidl::getCallbackImpl(void* cookie, wp<C> DeviceHalAidl::Callbacks::* field) {
1437 std::lock_guard l(mLock);
1438 if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
1439 return ((it->second).*field).promote();
1440 }
1441 return nullptr;
1442}
1443template<class C>
1444void DeviceHalAidl::setCallbackImpl(
1445 void* cookie, wp<C> DeviceHalAidl::Callbacks::* field, const sp<C>& cb) {
1446 std::lock_guard l(mLock);
1447 if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
1448 (it->second).*field = cb;
1449 }
1450}
1451
Mikhail Naganov31d46652023-01-10 18:29:25 +00001452} // namespace android