blob: e452a35210d381f7c5493a76f576c82f407f0d72 [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 Naganov5b1eed12023-01-25 11:29:11 -0800110} // namespace
111
Mikhail Naganovf83b9742023-04-24 13:06:04 -0700112status_t DeviceHalAidl::getAudioPorts(std::vector<media::audio::common::AudioPort> *ports) {
113 auto convertAudioPortFromMap = [](const Ports::value_type& pair) {
114 return ndk2cpp_AudioPort(pair.second);
115 };
116 return ::aidl::android::convertRange(mPorts.begin(), mPorts.end(), ports->begin(),
117 convertAudioPortFromMap);
118}
119
120status_t DeviceHalAidl::getAudioRoutes(std::vector<media::AudioRoute> *routes) {
121 *routes = VALUE_OR_RETURN_STATUS(
122 ::aidl::android::convertContainer<std::vector<media::AudioRoute>>(
123 mRoutes, ndk2cpp_AudioRoute));
124 return OK;
125}
126
Mikhail Naganov31d46652023-01-10 18:29:25 +0000127status_t DeviceHalAidl::getSupportedDevices(uint32_t*) {
128 // Obsolete.
129 return INVALID_OPERATION;
Shunkai Yao51202502022-12-12 06:11:46 +0000130}
131
132status_t DeviceHalAidl::initCheck() {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800133 TIME_CHECK();
Mikhail Naganov31d46652023-01-10 18:29:25 +0000134 if (mModule == nullptr) return NO_INIT;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800135 std::vector<AudioPort> ports;
Mikhail Naganovf83b9742023-04-24 13:06:04 -0700136 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->getAudioPorts(&ports)));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800137 ALOGW_IF(ports.empty(), "%s: module %s returned an empty list of audio ports",
138 __func__, mInstance.c_str());
139 std::transform(ports.begin(), ports.end(), std::inserter(mPorts, mPorts.end()),
140 [](const auto& p) { return std::make_pair(p.id, p); });
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800141 mDefaultInputPortId = mDefaultOutputPortId = -1;
142 const int defaultDeviceFlag = 1 << AudioPortDeviceExt::FLAG_INDEX_DEFAULT_DEVICE;
143 for (const auto& pair : mPorts) {
144 const auto& p = pair.second;
145 if (p.ext.getTag() == AudioPortExt::Tag::device &&
146 (p.ext.get<AudioPortExt::Tag::device>().flags & defaultDeviceFlag) != 0) {
147 if (p.flags.getTag() == AudioIoFlags::Tag::input) {
148 mDefaultInputPortId = p.id;
149 } else if (p.flags.getTag() == AudioIoFlags::Tag::output) {
150 mDefaultOutputPortId = p.id;
151 }
152 }
153 }
154 ALOGI("%s: module %s default port ids: input %d, output %d",
155 __func__, mInstance.c_str(), mDefaultInputPortId, mDefaultOutputPortId);
Mikhail Naganov289468a2023-03-29 10:06:15 -0700156 RETURN_STATUS_IF_ERROR(updateRoutes());
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800157 std::vector<AudioPortConfig> portConfigs;
158 RETURN_STATUS_IF_ERROR(
159 statusTFromBinderStatus(mModule->getAudioPortConfigs(&portConfigs))); // OK if empty
160 std::transform(portConfigs.begin(), portConfigs.end(),
161 std::inserter(mPortConfigs, mPortConfigs.end()),
162 [](const auto& p) { return std::make_pair(p.id, p); });
jiabin9c07faf2023-04-26 22:00:44 +0000163 std::transform(mPortConfigs.begin(), mPortConfigs.end(),
164 std::inserter(mInitialPortConfigIds, mInitialPortConfigIds.end()),
165 [](const auto& pcPair) { return pcPair.first; });
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800166 std::vector<AudioPatch> patches;
167 RETURN_STATUS_IF_ERROR(
168 statusTFromBinderStatus(mModule->getAudioPatches(&patches))); // OK if empty
169 std::transform(patches.begin(), patches.end(),
170 std::inserter(mPatches, mPatches.end()),
171 [](const auto& p) { return std::make_pair(p.id, p); });
Shunkai Yao51202502022-12-12 06:11:46 +0000172 return OK;
173}
174
175status_t DeviceHalAidl::setVoiceVolume(float volume) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000176 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000177 if (!mModule) return NO_INIT;
178 std::shared_ptr<ITelephony> telephony;
179 if (ndk::ScopedAStatus status = mModule->getTelephony(&telephony);
180 status.isOk() && telephony != nullptr) {
181 ITelephony::TelecomConfig inConfig{ .voiceVolume = Float{volume} }, outConfig;
182 RETURN_STATUS_IF_ERROR(
183 statusTFromBinderStatus(telephony->setTelecomConfig(inConfig, &outConfig)));
184 ALOGW_IF(outConfig.voiceVolume.has_value() && volume != outConfig.voiceVolume.value().value,
185 "%s: the resulting voice volume %f is not the same as requested %f",
186 __func__, outConfig.voiceVolume.value().value, volume);
187 }
188 return INVALID_OPERATION;
Shunkai Yao51202502022-12-12 06:11:46 +0000189}
190
191status_t DeviceHalAidl::setMasterVolume(float volume) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000192 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000193 if (!mModule) return NO_INIT;
194 return statusTFromBinderStatus(mModule->setMasterVolume(volume));
Shunkai Yao51202502022-12-12 06:11:46 +0000195}
196
197status_t DeviceHalAidl::getMasterVolume(float *volume) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000198 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000199 if (!mModule) return NO_INIT;
200 return statusTFromBinderStatus(mModule->getMasterVolume(volume));
Shunkai Yao51202502022-12-12 06:11:46 +0000201}
202
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000203status_t DeviceHalAidl::setMode(audio_mode_t mode) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000204 TIME_CHECK();
205 if (!mModule) return NO_INIT;
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000206 AudioMode audioMode = VALUE_OR_FATAL(::aidl::android::legacy2aidl_audio_mode_t_AudioMode(mode));
207 std::shared_ptr<ITelephony> telephony;
208 if (ndk::ScopedAStatus status = mModule->getTelephony(&telephony);
209 status.isOk() && telephony != nullptr) {
210 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(telephony->switchAudioMode(audioMode)));
211 }
212 return statusTFromBinderStatus(mModule->updateAudioMode(audioMode));
Shunkai Yao51202502022-12-12 06:11:46 +0000213}
214
215status_t DeviceHalAidl::setMicMute(bool state) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000216 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000217 if (!mModule) return NO_INIT;
218 return statusTFromBinderStatus(mModule->setMicMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000219}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000220
Shunkai Yao51202502022-12-12 06:11:46 +0000221status_t DeviceHalAidl::getMicMute(bool *state) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000222 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000223 if (!mModule) return NO_INIT;
224 return statusTFromBinderStatus(mModule->getMicMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000225}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000226
Shunkai Yao51202502022-12-12 06:11:46 +0000227status_t DeviceHalAidl::setMasterMute(bool state) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000228 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000229 if (!mModule) return NO_INIT;
230 return statusTFromBinderStatus(mModule->setMasterMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000231}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000232
Shunkai Yao51202502022-12-12 06:11:46 +0000233status_t DeviceHalAidl::getMasterMute(bool *state) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000234 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000235 if (!mModule) return NO_INIT;
236 return statusTFromBinderStatus(mModule->getMasterMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000237}
238
Mikhail Naganov31d46652023-01-10 18:29:25 +0000239status_t DeviceHalAidl::setParameters(const String8& kvPairs __unused) {
240 TIME_CHECK();
241 if (!mModule) return NO_INIT;
242 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000243 return OK;
244}
245
Mikhail Naganov31d46652023-01-10 18:29:25 +0000246status_t DeviceHalAidl::getParameters(const String8& keys __unused, String8 *values) {
247 TIME_CHECK();
248 values->clear();
249 if (!mModule) return NO_INIT;
250 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000251 return OK;
252}
253
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800254namespace {
255
256class Cleanup {
257 public:
258 typedef void (DeviceHalAidl::*Cleaner)(int32_t);
259
260 Cleanup(DeviceHalAidl* device, Cleaner cleaner, int32_t id) :
261 mDevice(device), mCleaner(cleaner), mId(id) {}
262 ~Cleanup() { clean(); }
263 void clean() {
264 if (mDevice != nullptr) (mDevice->*mCleaner)(mId);
265 disarm();
266 }
267 void disarm() { mDevice = nullptr; }
268
269 private:
270 DeviceHalAidl* mDevice;
271 const Cleaner mCleaner;
272 const int32_t mId;
273};
274
275} // namespace
276
277// Since the order of container elements destruction is unspecified,
278// ensure that cleanups are performed from the most recent one and upwards.
279// This is the same as if there were individual Cleanup instances on the stack,
280// however the bonus is that we can disarm all of them with just one statement.
281class DeviceHalAidl::Cleanups : public std::forward_list<Cleanup> {
282 public:
283 ~Cleanups() { for (auto& c : *this) c.clean(); }
284 void disarmAll() { for (auto& c : *this) c.disarm(); }
285};
286
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800287status_t DeviceHalAidl::getInputBufferSize(const struct audio_config* config, size_t* size) {
288 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
289 if (size == nullptr) return BAD_VALUE;
290 TIME_CHECK();
291 if (!mModule) return NO_INIT;
292 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
293 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, true /*isInput*/));
294 AudioDevice aidlDevice;
295 aidlDevice.type.type = AudioDeviceType::IN_DEFAULT;
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800296 AudioSource aidlSource = AudioSource::DEFAULT;
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800297 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::input>(0);
298 AudioPortConfig mixPortConfig;
299 Cleanups cleanups;
300 audio_config writableConfig = *config;
Mikhail Naganove93a0862023-03-15 17:06:59 -0700301 AudioPatch aidlPatch;
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800302 RETURN_STATUS_IF_ERROR(prepareToOpenStream(0 /*handle*/, aidlDevice, aidlFlags, aidlSource,
Mikhail Naganove93a0862023-03-15 17:06:59 -0700303 &writableConfig, &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800304 *size = aidlConfig.frameCount *
305 getFrameSizeInBytes(aidlConfig.base.format, aidlConfig.base.channelMask);
306 // Do not disarm cleanups to release temporary port configs.
307 return OK;
308}
309
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800310status_t DeviceHalAidl::prepareToOpenStream(
311 int32_t aidlHandle, const AudioDevice& aidlDevice, const AudioIoFlags& aidlFlags,
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800312 AudioSource aidlSource, struct audio_config* config,
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800313 Cleanups* cleanups, AudioConfig* aidlConfig, AudioPortConfig* mixPortConfig,
Mikhail Naganove93a0862023-03-15 17:06:59 -0700314 AudioPatch* aidlPatch) {
315 ALOGD("%p %s::%s: handle %d, device %s, flags %s, source %s, config %s, mix port config %s",
316 this, getClassName().c_str(), __func__, aidlHandle, aidlDevice.toString().c_str(),
317 aidlFlags.toString().c_str(), toString(aidlSource).c_str(),
318 aidlConfig->toString().c_str(), mixPortConfig->toString().c_str());
jiabin9c07faf2023-04-26 22:00:44 +0000319 resetUnusedPatchesAndPortConfigs();
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800320 const bool isInput = aidlFlags.getTag() == AudioIoFlags::Tag::input;
321 // Find / create AudioPortConfigs for the device port and the mix port,
322 // then find / create a patch between them, and open a stream on the mix port.
323 AudioPortConfig devicePortConfig;
324 bool created = false;
jiabin9c07faf2023-04-26 22:00:44 +0000325 RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(aidlDevice, aidlConfig,
326 &devicePortConfig, &created));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800327 if (created) {
328 cleanups->emplace_front(this, &DeviceHalAidl::resetPortConfig, devicePortConfig.id);
329 }
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800330 RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(*aidlConfig, aidlFlags, aidlHandle, aidlSource,
Mikhail Naganov289468a2023-03-29 10:06:15 -0700331 std::set<int32_t>{devicePortConfig.portId}, mixPortConfig, &created));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800332 if (created) {
333 cleanups->emplace_front(this, &DeviceHalAidl::resetPortConfig, mixPortConfig->id);
334 }
335 setConfigFromPortConfig(aidlConfig, *mixPortConfig);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800336 if (isInput) {
337 RETURN_STATUS_IF_ERROR(findOrCreatePatch(
Mikhail Naganove93a0862023-03-15 17:06:59 -0700338 {devicePortConfig.id}, {mixPortConfig->id}, aidlPatch, &created));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800339 } else {
340 RETURN_STATUS_IF_ERROR(findOrCreatePatch(
Mikhail Naganove93a0862023-03-15 17:06:59 -0700341 {mixPortConfig->id}, {devicePortConfig.id}, aidlPatch, &created));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800342 }
343 if (created) {
Mikhail Naganove93a0862023-03-15 17:06:59 -0700344 cleanups->emplace_front(this, &DeviceHalAidl::resetPatch, aidlPatch->id);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800345 }
346 if (aidlConfig->frameCount <= 0) {
Mikhail Naganove93a0862023-03-15 17:06:59 -0700347 aidlConfig->frameCount = aidlPatch->minimumStreamBufferSizeFrames;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800348 }
349 *config = VALUE_OR_RETURN_STATUS(
350 ::aidl::android::aidl2legacy_AudioConfig_audio_config_t(*aidlConfig, isInput));
351 return OK;
352}
353
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800354namespace {
355
356class StreamCallbackBase {
357 protected:
358 explicit StreamCallbackBase(const sp<CallbackBroker>& broker) : mBroker(broker) {}
359 public:
360 void* getCookie() const { return mCookie; }
361 void setCookie(void* cookie) { mCookie = cookie; }
362 sp<CallbackBroker> getBroker() const {
363 if (void* cookie = mCookie; cookie != nullptr) return mBroker.promote();
364 return nullptr;
365 }
366 private:
367 const wp<CallbackBroker> mBroker;
368 std::atomic<void*> mCookie;
369};
370
371template<class C>
372class StreamCallbackBaseHelper {
373 protected:
374 explicit StreamCallbackBaseHelper(const StreamCallbackBase& base) : mBase(base) {}
375 sp<C> getCb(const sp<CallbackBroker>& broker, void* cookie);
376 using CbRef = const sp<C>&;
377 ndk::ScopedAStatus runCb(const std::function<void(CbRef cb)>& f) {
378 if (auto cb = getCb(mBase.getBroker(), mBase.getCookie()); cb != nullptr) f(cb);
379 return ndk::ScopedAStatus::ok();
380 }
381 private:
382 const StreamCallbackBase& mBase;
383};
384
385template<>
386sp<StreamOutHalInterfaceCallback> StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>::getCb(
387 const sp<CallbackBroker>& broker, void* cookie) {
388 if (broker != nullptr) return broker->getStreamOutCallback(cookie);
389 return nullptr;
390}
391
392template<>
393sp<StreamOutHalInterfaceEventCallback>
394StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>::getCb(
395 const sp<CallbackBroker>& broker, void* cookie) {
396 if (broker != nullptr) return broker->getStreamOutEventCallback(cookie);
397 return nullptr;
398}
399
400template<>
401sp<StreamOutHalInterfaceLatencyModeCallback>
402StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>::getCb(
403 const sp<CallbackBroker>& broker, void* cookie) {
404 if (broker != nullptr) return broker->getStreamOutLatencyModeCallback(cookie);
405 return nullptr;
406}
407
408/*
409Note on the callback ownership.
410
411In the Binder ownership model, the server implementation is kept alive
412as long as there is any client (proxy object) alive. This is done by
413incrementing the refcount of the server-side object by the Binder framework.
414When it detects that the last client is gone, it decrements the refcount back.
415
416Thus, it is not needed to keep any references to StreamCallback on our
417side (after we have sent an instance to the client), because we are
418the server-side. The callback object will be kept alive as long as the HAL server
419holds a strong ref to IStreamCallback proxy.
420*/
421
422class OutputStreamCallbackAidl : public StreamCallbackBase,
423 public StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>,
424 public ::aidl::android::hardware::audio::core::BnStreamCallback {
425 public:
426 explicit OutputStreamCallbackAidl(const sp<CallbackBroker>& broker)
427 : StreamCallbackBase(broker),
428 StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>(
429 *static_cast<StreamCallbackBase*>(this)) {}
430 ndk::ScopedAStatus onTransferReady() override {
431 return runCb([](CbRef cb) { cb->onWriteReady(); });
432 }
433 ndk::ScopedAStatus onError() override {
434 return runCb([](CbRef cb) { cb->onError(); });
435 }
436 ndk::ScopedAStatus onDrainReady() override {
437 return runCb([](CbRef cb) { cb->onDrainReady(); });
438 }
439};
440
441class OutputStreamEventCallbackAidl :
442 public StreamCallbackBase,
443 public StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>,
444 public StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>,
445 public ::aidl::android::hardware::audio::core::BnStreamOutEventCallback {
446 public:
447 explicit OutputStreamEventCallbackAidl(const sp<CallbackBroker>& broker)
448 : StreamCallbackBase(broker),
449 StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>(
450 *static_cast<StreamCallbackBase*>(this)),
451 StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>(
452 *static_cast<StreamCallbackBase*>(this)) {}
453 ndk::ScopedAStatus onCodecFormatChanged(const std::vector<uint8_t>& in_audioMetadata) override {
454 std::basic_string<uint8_t> halMetadata(in_audioMetadata.begin(), in_audioMetadata.end());
455 return StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>::runCb(
456 [&halMetadata](auto cb) { cb->onCodecFormatChanged(halMetadata); });
457 }
458 ndk::ScopedAStatus onRecommendedLatencyModeChanged(
459 const std::vector<AudioLatencyMode>& in_modes) override {
460 auto halModes = VALUE_OR_FATAL(
461 ::aidl::android::convertContainer<std::vector<audio_latency_mode_t>>(
462 in_modes,
463 ::aidl::android::aidl2legacy_AudioLatencyMode_audio_latency_mode_t));
464 return StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>::runCb(
465 [&halModes](auto cb) { cb->onRecommendedLatencyModeChanged(halModes); });
466 }
467};
468
469} // namespace
470
Mikhail Naganov31d46652023-01-10 18:29:25 +0000471status_t DeviceHalAidl::openOutputStream(
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800472 audio_io_handle_t handle, audio_devices_t devices,
473 audio_output_flags_t flags, struct audio_config* config,
474 const char* address,
Mikhail Naganov31d46652023-01-10 18:29:25 +0000475 sp<StreamOutHalInterface>* outStream) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800476 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000477 if (!outStream || !config) {
478 return BAD_VALUE;
479 }
480 TIME_CHECK();
481 if (!mModule) return NO_INIT;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800482 int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
483 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(handle));
484 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
485 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, false /*isInput*/));
486 AudioDevice aidlDevice = VALUE_OR_RETURN_STATUS(
487 ::aidl::android::legacy2aidl_audio_device_AudioDevice(devices, address));
488 int32_t aidlOutputFlags = VALUE_OR_RETURN_STATUS(
489 ::aidl::android::legacy2aidl_audio_output_flags_t_int32_t_mask(flags));
490 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::output>(aidlOutputFlags);
491 AudioPortConfig mixPortConfig;
492 Cleanups cleanups;
Mikhail Naganove93a0862023-03-15 17:06:59 -0700493 AudioPatch aidlPatch;
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800494 RETURN_STATUS_IF_ERROR(prepareToOpenStream(aidlHandle, aidlDevice, aidlFlags,
495 AudioSource::SYS_RESERVED_INVALID /*only needed for input*/,
Mikhail Naganove93a0862023-03-15 17:06:59 -0700496 config, &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800497 ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamArguments args;
498 args.portConfigId = mixPortConfig.id;
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800499 const bool isOffload = isBitPositionFlagSet(
500 aidlOutputFlags, AudioOutputFlags::COMPRESS_OFFLOAD);
501 std::shared_ptr<OutputStreamCallbackAidl> streamCb;
502 if (isOffload) {
503 streamCb = ndk::SharedRefBase::make<OutputStreamCallbackAidl>(this);
504 }
505 auto eventCb = ndk::SharedRefBase::make<OutputStreamEventCallbackAidl>(this);
506 if (isOffload) {
507 args.offloadInfo = aidlConfig.offloadInfo;
508 args.callback = streamCb;
509 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800510 args.bufferSizeFrames = aidlConfig.frameCount;
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800511 args.eventCallback = eventCb;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800512 ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamReturn ret;
513 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openOutputStream(args, &ret)));
Mikhail Naganov712d71b2023-02-23 17:57:16 -0800514 StreamContextAidl context(ret.desc, isOffload);
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800515 if (!context.isValid()) {
516 ALOGE("%s: Failed to created a valid stream context from the descriptor: %s",
517 __func__, ret.desc.toString().c_str());
518 return NO_INIT;
519 }
Mikhail Naganove93a0862023-03-15 17:06:59 -0700520 *outStream = sp<StreamOutHalAidl>::make(*config, std::move(context), aidlPatch.latenciesMs[0],
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800521 std::move(ret.stream), this /*callbackBroker*/);
Mikhail Naganove93a0862023-03-15 17:06:59 -0700522 mStreams.insert(std::pair(*outStream, aidlPatch.id));
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800523 void* cbCookie = (*outStream).get();
524 {
525 std::lock_guard l(mLock);
526 mCallbacks.emplace(cbCookie, Callbacks{});
527 }
528 if (streamCb) streamCb->setCookie(cbCookie);
529 eventCb->setCookie(cbCookie);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800530 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000531 return OK;
532}
533
Mikhail Naganov31d46652023-01-10 18:29:25 +0000534status_t DeviceHalAidl::openInputStream(
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800535 audio_io_handle_t handle, audio_devices_t devices,
536 struct audio_config* config, audio_input_flags_t flags,
537 const char* address, audio_source_t source,
538 audio_devices_t outputDevice, const char* outputDeviceAddress,
Mikhail Naganov31d46652023-01-10 18:29:25 +0000539 sp<StreamInHalInterface>* inStream) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800540 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000541 if (!inStream || !config) {
542 return BAD_VALUE;
543 }
544 TIME_CHECK();
545 if (!mModule) return NO_INIT;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800546 int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
547 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(handle));
548 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
549 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, true /*isInput*/));
550 AudioDevice aidlDevice = VALUE_OR_RETURN_STATUS(
551 ::aidl::android::legacy2aidl_audio_device_AudioDevice(devices, address));
552 int32_t aidlInputFlags = VALUE_OR_RETURN_STATUS(
553 ::aidl::android::legacy2aidl_audio_input_flags_t_int32_t_mask(flags));
554 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::input>(aidlInputFlags);
555 AudioSource aidlSource = VALUE_OR_RETURN_STATUS(
556 ::aidl::android::legacy2aidl_audio_source_t_AudioSource(source));
557 AudioPortConfig mixPortConfig;
558 Cleanups cleanups;
Mikhail Naganove93a0862023-03-15 17:06:59 -0700559 AudioPatch aidlPatch;
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800560 RETURN_STATUS_IF_ERROR(prepareToOpenStream(aidlHandle, aidlDevice, aidlFlags, aidlSource,
Mikhail Naganove93a0862023-03-15 17:06:59 -0700561 config, &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800562 ::aidl::android::hardware::audio::core::IModule::OpenInputStreamArguments args;
563 args.portConfigId = mixPortConfig.id;
564 RecordTrackMetadata aidlTrackMetadata{
565 .source = aidlSource, .gain = 1, .channelMask = aidlConfig.base.channelMask };
566 if (outputDevice != AUDIO_DEVICE_NONE) {
567 aidlTrackMetadata.destinationDevice = VALUE_OR_RETURN_STATUS(
568 ::aidl::android::legacy2aidl_audio_device_AudioDevice(
569 outputDevice, outputDeviceAddress));
570 }
571 args.sinkMetadata.tracks.push_back(std::move(aidlTrackMetadata));
572 args.bufferSizeFrames = aidlConfig.frameCount;
573 ::aidl::android::hardware::audio::core::IModule::OpenInputStreamReturn ret;
574 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openInputStream(args, &ret)));
Mikhail Naganov712d71b2023-02-23 17:57:16 -0800575 StreamContextAidl context(ret.desc, false /*isAsynchronous*/);
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800576 if (!context.isValid()) {
577 ALOGE("%s: Failed to created a valid stream context from the descriptor: %s",
578 __func__, ret.desc.toString().c_str());
579 return NO_INIT;
580 }
Mikhail Naganove93a0862023-03-15 17:06:59 -0700581 *inStream = sp<StreamInHalAidl>::make(*config, std::move(context), aidlPatch.latenciesMs[0],
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800582 std::move(ret.stream), this /*micInfoProvider*/);
Mikhail Naganove93a0862023-03-15 17:06:59 -0700583 mStreams.insert(std::pair(*inStream, aidlPatch.id));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800584 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000585 return OK;
586}
587
588status_t DeviceHalAidl::supportsAudioPatches(bool* supportsPatches) {
589 *supportsPatches = true;
590 return OK;
591}
592
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800593status_t DeviceHalAidl::createAudioPatch(unsigned int num_sources,
594 const struct audio_port_config* sources,
595 unsigned int num_sinks,
596 const struct audio_port_config* sinks,
597 audio_patch_handle_t* patch) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800598 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000599 TIME_CHECK();
600 if (!mModule) return NO_INIT;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800601 if (num_sinks > AUDIO_PATCH_PORTS_MAX || num_sources > AUDIO_PATCH_PORTS_MAX ||
602 sources == nullptr || sinks == nullptr || patch == nullptr) {
603 return BAD_VALUE;
604 }
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800605 // When the patch handle (*patch) is AUDIO_PATCH_HANDLE_NONE, it means
606 // the framework wants to create a new patch. The handle has to be generated
607 // by the HAL. Since handles generated this way can only be unique within
608 // a HAL module, the framework generates a globally unique handle, and maps
609 // it on the <HAL module, patch handle> pair.
610 // When the patch handle is set, it meant the framework intends to update
611 // an existing patch.
612 //
613 // This behavior corresponds to HAL module behavior, with the only difference
614 // that the HAL module uses `int32_t` for patch IDs. The following assert ensures
615 // that both the framework and the HAL use the same value for "no ID":
616 static_assert(AUDIO_PATCH_HANDLE_NONE == 0);
617 int32_t halPatchId = static_cast<int32_t>(*patch);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800618
619 // Upon conversion, mix port configs contain audio configuration, while
620 // device port configs contain device address. This data is used to find
621 // or create HAL configs.
622 std::vector<AudioPortConfig> aidlSources, aidlSinks;
623 for (unsigned int i = 0; i < num_sources; ++i) {
624 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
625 sources[i].role, sources[i].type)) ==
626 ::aidl::android::AudioPortDirection::INPUT;
627 aidlSources.push_back(VALUE_OR_RETURN_STATUS(
628 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
629 sources[i], isInput, 0)));
630 }
631 for (unsigned int i = 0; i < num_sinks; ++i) {
632 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
633 sinks[i].role, sinks[i].type)) ==
634 ::aidl::android::AudioPortDirection::INPUT;
635 aidlSinks.push_back(VALUE_OR_RETURN_STATUS(
636 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
637 sinks[i], isInput, 0)));
638 }
639 Cleanups cleanups;
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800640 auto existingPatchIt = halPatchId != 0 ? mPatches.find(halPatchId): mPatches.end();
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800641 AudioPatch aidlPatch;
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800642 if (existingPatchIt != mPatches.end()) {
643 aidlPatch = existingPatchIt->second;
644 aidlPatch.sourcePortConfigIds.clear();
645 aidlPatch.sinkPortConfigIds.clear();
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800646 }
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800647 ALOGD("%s: sources: %s, sinks: %s",
648 __func__, ::android::internal::ToString(aidlSources).c_str(),
649 ::android::internal::ToString(aidlSinks).c_str());
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800650 auto fillPortConfigs = [&](
Mikhail Naganov289468a2023-03-29 10:06:15 -0700651 const std::vector<AudioPortConfig>& configs,
652 const std::set<int32_t>& destinationPortIds,
653 std::vector<int32_t>* ids, std::set<int32_t>* portIds) -> status_t {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800654 for (const auto& s : configs) {
655 AudioPortConfig portConfig;
656 bool created = false;
Mikhail Naganov289468a2023-03-29 10:06:15 -0700657 RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(
658 s, destinationPortIds, &portConfig, &created));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800659 if (created) {
660 cleanups.emplace_front(this, &DeviceHalAidl::resetPortConfig, portConfig.id);
661 }
662 ids->push_back(portConfig.id);
Mikhail Naganov289468a2023-03-29 10:06:15 -0700663 if (portIds != nullptr) {
664 portIds->insert(portConfig.portId);
665 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800666 }
667 return OK;
668 };
Mikhail Naganov289468a2023-03-29 10:06:15 -0700669 // When looking up port configs, the destinationPortId is only used for mix ports.
670 // Thus, we process device port configs first, and look up the destination port ID from them.
671 bool sourceIsDevice = std::any_of(aidlSources.begin(), aidlSources.end(),
672 [](const auto& config) { return config.ext.getTag() == AudioPortExt::device; });
673 const std::vector<AudioPortConfig>& devicePortConfigs =
674 sourceIsDevice ? aidlSources : aidlSinks;
675 std::vector<int32_t>* devicePortConfigIds =
676 sourceIsDevice ? &aidlPatch.sourcePortConfigIds : &aidlPatch.sinkPortConfigIds;
677 const std::vector<AudioPortConfig>& mixPortConfigs =
678 sourceIsDevice ? aidlSinks : aidlSources;
679 std::vector<int32_t>* mixPortConfigIds =
680 sourceIsDevice ? &aidlPatch.sinkPortConfigIds : &aidlPatch.sourcePortConfigIds;
681 std::set<int32_t> devicePortIds;
682 RETURN_STATUS_IF_ERROR(fillPortConfigs(
683 devicePortConfigs, std::set<int32_t>(), devicePortConfigIds, &devicePortIds));
684 RETURN_STATUS_IF_ERROR(fillPortConfigs(
685 mixPortConfigs, devicePortIds, mixPortConfigIds, nullptr));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800686 if (existingPatchIt != mPatches.end()) {
687 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
688 mModule->setAudioPatch(aidlPatch, &aidlPatch)));
689 existingPatchIt->second = aidlPatch;
690 } else {
691 bool created = false;
692 RETURN_STATUS_IF_ERROR(findOrCreatePatch(aidlPatch, &aidlPatch, &created));
693 // Since no cleanup of the patch is needed, 'created' is ignored.
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800694 halPatchId = aidlPatch.id;
695 *patch = static_cast<audio_patch_handle_t>(halPatchId);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800696 }
697 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000698 return OK;
699}
700
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800701status_t DeviceHalAidl::releaseAudioPatch(audio_patch_handle_t patch) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800702 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000703 TIME_CHECK();
704 if (!mModule) return NO_INIT;
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800705 static_assert(AUDIO_PATCH_HANDLE_NONE == 0);
706 if (patch == AUDIO_PATCH_HANDLE_NONE) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800707 return BAD_VALUE;
708 }
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800709 int32_t halPatchId = static_cast<int32_t>(patch);
710 auto patchIt = mPatches.find(halPatchId);
711 if (patchIt == mPatches.end()) {
712 ALOGE("%s: patch with id %d not found", __func__, halPatchId);
713 return BAD_VALUE;
714 }
715 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->resetAudioPatch(halPatchId)));
716 mPatches.erase(patchIt);
Shunkai Yao51202502022-12-12 06:11:46 +0000717 return OK;
718}
719
Mikhail Naganove93a0862023-03-15 17:06:59 -0700720status_t DeviceHalAidl::getAudioPort(struct audio_port* port) {
721 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000722 TIME_CHECK();
723 if (!mModule) return NO_INIT;
Mikhail Naganove93a0862023-03-15 17:06:59 -0700724 if (port == nullptr) {
725 return BAD_VALUE;
726 }
727 audio_port_v7 portV7;
728 audio_populate_audio_port_v7(port, &portV7);
729 RETURN_STATUS_IF_ERROR(getAudioPort(&portV7));
730 return audio_populate_audio_port(&portV7, port) ? OK : BAD_VALUE;
731}
732
733status_t DeviceHalAidl::getAudioPort(struct audio_port_v7 *port) {
734 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
735 TIME_CHECK();
736 if (!mModule) return NO_INIT;
737 if (port == nullptr) {
738 return BAD_VALUE;
739 }
740 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(port->role, port->type)) ==
741 ::aidl::android::AudioPortDirection::INPUT;
742 auto aidlPort = VALUE_OR_RETURN_STATUS(
743 ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
744 if (aidlPort.ext.getTag() != AudioPortExt::device) {
745 ALOGE("%s: provided port is not a device port (module %s): %s",
746 __func__, mInstance.c_str(), aidlPort.toString().c_str());
747 return BAD_VALUE;
748 }
749 const auto& matchDevice = aidlPort.ext.get<AudioPortExt::device>().device;
750 // It seems that we don't have to call HAL since all valid ports have been added either
751 // during initialization, or while handling connection of an external device.
752 auto portsIt = findPort(matchDevice);
753 if (portsIt == mPorts.end()) {
754 ALOGE("%s: device port for device %s is not found in the module %s",
755 __func__, matchDevice.toString().c_str(), mInstance.c_str());
756 return BAD_VALUE;
757 }
758 const int32_t fwkId = aidlPort.id;
759 aidlPort = portsIt->second;
760 aidlPort.id = fwkId;
761 *port = VALUE_OR_RETURN_STATUS(::aidl::android::aidl2legacy_AudioPort_audio_port_v7(
762 aidlPort, isInput));
763 return OK;
764}
765
766status_t DeviceHalAidl::setAudioPortConfig(const struct audio_port_config* config) {
767 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
768 TIME_CHECK();
769 if (!mModule) return NO_INIT;
770 if (config == nullptr) {
771 return BAD_VALUE;
772 }
773 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
774 config->role, config->type)) == ::aidl::android::AudioPortDirection::INPUT;
775 AudioPortConfig requestedPortConfig = VALUE_OR_RETURN_STATUS(
776 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
777 *config, isInput, 0 /*portId*/));
778 AudioPortConfig portConfig;
779 bool created = false;
Mikhail Naganov289468a2023-03-29 10:06:15 -0700780 RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(
781 requestedPortConfig, std::set<int32_t>(), &portConfig, &created));
Shunkai Yao51202502022-12-12 06:11:46 +0000782 return OK;
783}
784
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800785MicrophoneInfoProvider::Info const* DeviceHalAidl::getMicrophoneInfo() {
786 if (mMicrophones.status == Microphones::Status::UNKNOWN) {
787 TIME_CHECK();
788 std::vector<MicrophoneInfo> aidlInfo;
789 status_t status = statusTFromBinderStatus(mModule->getMicrophones(&aidlInfo));
790 if (status == OK) {
791 mMicrophones.status = Microphones::Status::QUERIED;
792 mMicrophones.info = std::move(aidlInfo);
793 } else if (status == INVALID_OPERATION) {
794 mMicrophones.status = Microphones::Status::NOT_SUPPORTED;
795 } else {
796 ALOGE("%s: Unexpected status from 'IModule.getMicrophones': %d", __func__, status);
797 return {};
798 }
799 }
800 if (mMicrophones.status == Microphones::Status::QUERIED) {
801 return &mMicrophones.info;
802 }
803 return {}; // NOT_SUPPORTED
804}
805
Shunkai Yao51202502022-12-12 06:11:46 +0000806status_t DeviceHalAidl::getMicrophones(
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800807 std::vector<audio_microphone_characteristic_t>* microphones) {
808 if (!microphones) {
809 return BAD_VALUE;
810 }
Mikhail Naganov31d46652023-01-10 18:29:25 +0000811 TIME_CHECK();
812 if (!mModule) return NO_INIT;
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800813 auto staticInfo = getMicrophoneInfo();
814 if (!staticInfo) return INVALID_OPERATION;
815 std::vector<MicrophoneDynamicInfo> emptyDynamicInfo;
816 emptyDynamicInfo.reserve(staticInfo->size());
817 std::transform(staticInfo->begin(), staticInfo->end(), std::back_inserter(emptyDynamicInfo),
818 [](const auto& info) { return MicrophoneDynamicInfo{ .id = info.id }; });
819 *microphones = VALUE_OR_RETURN_STATUS(
820 ::aidl::android::convertContainers<std::vector<audio_microphone_characteristic_t>>(
821 *staticInfo, emptyDynamicInfo,
822 ::aidl::android::aidl2legacy_MicrophoneInfos_audio_microphone_characteristic_t)
823 );
Shunkai Yao51202502022-12-12 06:11:46 +0000824 return OK;
825}
826
Mikhail Naganov31d46652023-01-10 18:29:25 +0000827status_t DeviceHalAidl::addDeviceEffect(audio_port_handle_t device __unused,
828 sp<EffectHalInterface> effect) {
Shunkai Yao51202502022-12-12 06:11:46 +0000829 if (!effect) {
830 return BAD_VALUE;
831 }
Mikhail Naganov31d46652023-01-10 18:29:25 +0000832 TIME_CHECK();
833 if (!mModule) return NO_INIT;
834 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000835 return OK;
836}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000837status_t DeviceHalAidl::removeDeviceEffect(audio_port_handle_t device __unused,
Shunkai Yao51202502022-12-12 06:11:46 +0000838 sp<EffectHalInterface> effect) {
839 if (!effect) {
840 return BAD_VALUE;
841 }
Mikhail Naganov31d46652023-01-10 18:29:25 +0000842 TIME_CHECK();
843 if (!mModule) return NO_INIT;
844 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000845 return OK;
846}
847
848status_t DeviceHalAidl::getMmapPolicyInfos(
David Li9cf5e622023-03-21 00:51:10 +0800849 media::audio::common::AudioMMapPolicyType policyType,
850 std::vector<media::audio::common::AudioMMapPolicyInfo>* policyInfos) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000851 TIME_CHECK();
Mikhail Naganov25bc9a22023-04-21 18:48:16 -0700852 AudioMMapPolicyType mmapPolicyType = VALUE_OR_RETURN_STATUS(
853 cpp2ndk_AudioMMapPolicyType(policyType));
David Li9cf5e622023-03-21 00:51:10 +0800854
855 std::vector<AudioMMapPolicyInfo> mmapPolicyInfos;
856
857 if (status_t status = statusTFromBinderStatus(
858 mModule->getMmapPolicyInfos(mmapPolicyType, &mmapPolicyInfos)); status != OK) {
859 return status;
860 }
861
862 *policyInfos = VALUE_OR_RETURN_STATUS(
863 convertContainer<std::vector<media::audio::common::AudioMMapPolicyInfo>>(
864 mmapPolicyInfos, ndk2cpp_AudioMMapPolicyInfo));
Shunkai Yao51202502022-12-12 06:11:46 +0000865 return OK;
866}
867
868int32_t DeviceHalAidl::getAAudioMixerBurstCount() {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000869 TIME_CHECK();
David Li9cf5e622023-03-21 00:51:10 +0800870 int32_t mixerBurstCount = 0;
871 if (mModule->getAAudioMixerBurstCount(&mixerBurstCount).isOk()) {
872 return mixerBurstCount;
873 }
874 return 0;
Shunkai Yao51202502022-12-12 06:11:46 +0000875}
876
877int32_t DeviceHalAidl::getAAudioHardwareBurstMinUsec() {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000878 TIME_CHECK();
David Li9cf5e622023-03-21 00:51:10 +0800879 int32_t hardwareBurstMinUsec = 0;
880 if (mModule->getAAudioHardwareBurstMinUsec(&hardwareBurstMinUsec).isOk()) {
881 return hardwareBurstMinUsec;
882 }
883 return 0;
Shunkai Yao51202502022-12-12 06:11:46 +0000884}
885
886error::Result<audio_hw_sync_t> DeviceHalAidl::getHwAvSync() {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000887 TIME_CHECK();
Mikhail Naganov08a62ab2023-03-14 17:11:51 -0700888 if (!mModule) return NO_INIT;
889 int32_t aidlHwAvSync;
890 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->generateHwAvSyncId(&aidlHwAvSync)));
891 return VALUE_OR_RETURN_STATUS(
892 ::aidl::android::aidl2legacy_int32_t_audio_hw_sync_t(aidlHwAvSync));
Shunkai Yao51202502022-12-12 06:11:46 +0000893}
894
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000895status_t DeviceHalAidl::dump(int fd, const Vector<String16>& args) {
896 TIME_CHECK();
897 if (!mModule) return NO_INIT;
898 return mModule->dump(fd, Args(args).args(), args.size());
David Li9cf5e622023-03-21 00:51:10 +0800899}
Shunkai Yao51202502022-12-12 06:11:46 +0000900
Mikhail Naganov3ac95c92023-04-12 13:14:30 -0700901int32_t DeviceHalAidl::supportsBluetoothVariableLatency(bool* supports) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000902 TIME_CHECK();
Mikhail Naganov3ac95c92023-04-12 13:14:30 -0700903 if (!mModule) return NO_INIT;
904 if (supports == nullptr) {
905 return BAD_VALUE;
906 }
907 return statusTFromBinderStatus(mModule->supportsVariableLatency(supports));
Shunkai Yao51202502022-12-12 06:11:46 +0000908}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000909
jiabin872de702023-04-27 22:04:31 +0000910
911status_t DeviceHalAidl::prepareToDisconnectExternalDevice(const struct audio_port_v7* port) {
912 // There is not AIDL API defined for `prepareToDisconnectExternalDevice`.
913 // Call `setConnectedState` instead.
914 // TODO(b/279824103): call prepareToDisconnectExternalDevice when it is added.
915 const status_t status = setConnectedState(port, false /*connected*/);
916 if (status == NO_ERROR) {
917 mDeviceDisconnectionNotified.insert(port->id);
918 }
919 return status;
920}
921
Mikhail Naganove93a0862023-03-15 17:06:59 -0700922status_t DeviceHalAidl::setConnectedState(const struct audio_port_v7 *port, bool connected) {
923 TIME_CHECK();
924 if (!mModule) return NO_INIT;
925 if (port == nullptr) {
926 return BAD_VALUE;
927 }
jiabin872de702023-04-27 22:04:31 +0000928 if (!connected && mDeviceDisconnectionNotified.erase(port->id) > 0) {
929 // For device disconnection, APM will first call `prepareToDisconnectExternalDevice`
930 // and then call `setConnectedState`. However, there is no API for
931 // `prepareToDisconnectExternalDevice` yet. In that case, `setConnectedState` will be
932 // called when calling `prepareToDisconnectExternalDevice`. Do not call to the HAL if
933 // previous call is successful. Also remove the cache here to avoid a large cache after
934 // a long run.
935 return NO_ERROR;
936 }
Mikhail Naganove93a0862023-03-15 17:06:59 -0700937 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(port->role, port->type)) ==
938 ::aidl::android::AudioPortDirection::INPUT;
939 AudioPort aidlPort = VALUE_OR_RETURN_STATUS(
940 ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
941 if (aidlPort.ext.getTag() != AudioPortExt::device) {
942 ALOGE("%s: provided port is not a device port (module %s): %s",
943 __func__, mInstance.c_str(), aidlPort.toString().c_str());
944 return BAD_VALUE;
945 }
946 if (connected) {
947 AudioDevice matchDevice = aidlPort.ext.get<AudioPortExt::device>().device;
948 // Reset the device address to find the "template" port.
949 matchDevice.address = AudioDeviceAddress::make<AudioDeviceAddress::id>();
950 auto portsIt = findPort(matchDevice);
951 if (portsIt == mPorts.end()) {
952 ALOGW("%s: device port for device %s is not found in the module %s",
953 __func__, matchDevice.toString().c_str(), mInstance.c_str());
954 return BAD_VALUE;
955 }
956 // Use the ID of the "template" port, use all the information from the provided port.
957 aidlPort.id = portsIt->first;
958 AudioPort connectedPort;
959 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->connectExternalDevice(
960 aidlPort, &connectedPort)));
961 const auto [it, inserted] = mPorts.insert(std::make_pair(connectedPort.id, connectedPort));
962 LOG_ALWAYS_FATAL_IF(!inserted,
963 "%s: module %s, duplicate port ID received from HAL: %s, existing port: %s",
964 __func__, mInstance.c_str(), connectedPort.toString().c_str(),
965 it->second.toString().c_str());
966 } else { // !connected
967 AudioDevice matchDevice = aidlPort.ext.get<AudioPortExt::device>().device;
968 auto portsIt = findPort(matchDevice);
969 if (portsIt == mPorts.end()) {
970 ALOGW("%s: device port for device %s is not found in the module %s",
971 __func__, matchDevice.toString().c_str(), mInstance.c_str());
972 return BAD_VALUE;
973 }
974 // Any streams opened on the external device must be closed by this time,
975 // thus we can clean up patches and port configs that were created for them.
976 resetUnusedPatchesAndPortConfigs();
977 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->disconnectExternalDevice(
978 portsIt->second.id)));
979 mPorts.erase(portsIt);
980 }
Mikhail Naganov289468a2023-03-29 10:06:15 -0700981 return updateRoutes();
Mikhail Naganove93a0862023-03-15 17:06:59 -0700982}
983
984status_t DeviceHalAidl::setSimulateDeviceConnections(bool enabled) {
985 TIME_CHECK();
986 if (!mModule) return NO_INIT;
987 ModuleDebug debug{ .simulateDeviceConnections = enabled };
988 status_t status = statusTFromBinderStatus(mModule->setModuleDebug(debug));
989 // This is important to log as it affects HAL behavior.
990 if (status == OK) {
991 ALOGI("%s: set enabled: %d", __func__, enabled);
992 } else {
993 ALOGW("%s: set enabled to %d failed: %d", __func__, enabled, status);
994 }
995 return status;
996}
997
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800998bool DeviceHalAidl::audioDeviceMatches(const AudioDevice& device, const AudioPort& p) {
999 if (p.ext.getTag() != AudioPortExt::Tag::device) return false;
1000 return p.ext.get<AudioPortExt::Tag::device>().device == device;
1001}
1002
1003bool DeviceHalAidl::audioDeviceMatches(const AudioDevice& device, const AudioPortConfig& p) {
1004 if (p.ext.getTag() != AudioPortExt::Tag::device) return false;
1005 if (device.type.type == AudioDeviceType::IN_DEFAULT) {
1006 return p.portId == mDefaultInputPortId;
1007 } else if (device.type.type == AudioDeviceType::OUT_DEFAULT) {
1008 return p.portId == mDefaultOutputPortId;
1009 }
1010 return p.ext.get<AudioPortExt::Tag::device>().device == device;
1011}
1012
David Lia8675d42023-03-30 21:08:06 +08001013status_t DeviceHalAidl::createOrUpdatePortConfig(
1014 const AudioPortConfig& requestedPortConfig, PortConfigs::iterator* result, bool* created) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001015 TIME_CHECK();
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001016 AudioPortConfig appliedPortConfig;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001017 bool applied = false;
1018 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPortConfig(
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001019 requestedPortConfig, &appliedPortConfig, &applied)));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001020 if (!applied) {
1021 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPortConfig(
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001022 appliedPortConfig, &appliedPortConfig, &applied)));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001023 if (!applied) {
1024 ALOGE("%s: module %s did not apply suggested config %s",
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001025 __func__, mInstance.c_str(), appliedPortConfig.toString().c_str());
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001026 return NO_INIT;
1027 }
1028 }
David Lia8675d42023-03-30 21:08:06 +08001029
1030 int32_t id = appliedPortConfig.id;
1031 if (requestedPortConfig.id != 0 && requestedPortConfig.id != id) {
1032 LOG_ALWAYS_FATAL("%s: requested port config id %d changed to %d", __func__,
1033 requestedPortConfig.id, id);
1034 }
1035
1036 auto [it, inserted] = mPortConfigs.insert_or_assign(std::move(id),
1037 std::move(appliedPortConfig));
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001038 *result = it;
David Lia8675d42023-03-30 21:08:06 +08001039 *created = inserted;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001040 return OK;
1041}
1042
1043status_t DeviceHalAidl::findOrCreatePatch(
1044 const AudioPatch& requestedPatch, AudioPatch* patch, bool* created) {
1045 std::set<int32_t> sourcePortConfigIds(requestedPatch.sourcePortConfigIds.begin(),
1046 requestedPatch.sourcePortConfigIds.end());
1047 std::set<int32_t> sinkPortConfigIds(requestedPatch.sinkPortConfigIds.begin(),
1048 requestedPatch.sinkPortConfigIds.end());
1049 return findOrCreatePatch(sourcePortConfigIds, sinkPortConfigIds, patch, created);
1050}
1051
1052status_t DeviceHalAidl::findOrCreatePatch(
1053 const std::set<int32_t>& sourcePortConfigIds, const std::set<int32_t>& sinkPortConfigIds,
1054 AudioPatch* patch, bool* created) {
1055 auto patchIt = findPatch(sourcePortConfigIds, sinkPortConfigIds);
1056 if (patchIt == mPatches.end()) {
1057 TIME_CHECK();
1058 AudioPatch requestedPatch, appliedPatch;
1059 requestedPatch.sourcePortConfigIds.insert(requestedPatch.sourcePortConfigIds.end(),
1060 sourcePortConfigIds.begin(), sourcePortConfigIds.end());
1061 requestedPatch.sinkPortConfigIds.insert(requestedPatch.sinkPortConfigIds.end(),
1062 sinkPortConfigIds.begin(), sinkPortConfigIds.end());
1063 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPatch(
1064 requestedPatch, &appliedPatch)));
1065 patchIt = mPatches.insert(mPatches.end(), std::make_pair(appliedPatch.id, appliedPatch));
1066 *created = true;
1067 } else {
1068 *created = false;
1069 }
1070 *patch = patchIt->second;
1071 return OK;
1072}
1073
jiabin9c07faf2023-04-26 22:00:44 +00001074status_t DeviceHalAidl::findOrCreatePortConfig(const AudioDevice& device, const AudioConfig* config,
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001075 AudioPortConfig* portConfig, bool* created) {
1076 auto portConfigIt = findPortConfig(device);
1077 if (portConfigIt == mPortConfigs.end()) {
1078 auto portsIt = findPort(device);
1079 if (portsIt == mPorts.end()) {
1080 ALOGE("%s: device port for device %s is not found in the module %s",
1081 __func__, device.toString().c_str(), mInstance.c_str());
1082 return BAD_VALUE;
1083 }
1084 AudioPortConfig requestedPortConfig;
1085 requestedPortConfig.portId = portsIt->first;
jiabin9c07faf2023-04-26 22:00:44 +00001086 if (config != nullptr) {
1087 setPortConfigFromConfig(&requestedPortConfig, *config);
1088 }
David Lia8675d42023-03-30 21:08:06 +08001089 RETURN_STATUS_IF_ERROR(createOrUpdatePortConfig(requestedPortConfig, &portConfigIt,
1090 created));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001091 } else {
1092 *created = false;
1093 }
1094 *portConfig = portConfigIt->second;
1095 return OK;
1096}
1097
1098status_t DeviceHalAidl::findOrCreatePortConfig(
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001099 const AudioConfig& config, const std::optional<AudioIoFlags>& flags, int32_t ioHandle,
Mikhail Naganov289468a2023-03-29 10:06:15 -07001100 AudioSource source, const std::set<int32_t>& destinationPortIds,
1101 AudioPortConfig* portConfig, bool* created) {
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001102 // These flags get removed one by one in this order when retrying port finding.
1103 static const std::vector<AudioInputFlags> kOptionalInputFlags{
1104 AudioInputFlags::FAST, AudioInputFlags::RAW };
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001105 auto portConfigIt = findPortConfig(config, flags, ioHandle);
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001106 if (portConfigIt == mPortConfigs.end() && flags.has_value()) {
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001107 auto optionalInputFlagsIt = kOptionalInputFlags.begin();
1108 AudioIoFlags matchFlags = flags.value();
Mikhail Naganov289468a2023-03-29 10:06:15 -07001109 auto portsIt = findPort(config, matchFlags, destinationPortIds);
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001110 while (portsIt == mPorts.end() && matchFlags.getTag() == AudioIoFlags::Tag::input
1111 && optionalInputFlagsIt != kOptionalInputFlags.end()) {
1112 if (!isBitPositionFlagSet(
1113 matchFlags.get<AudioIoFlags::Tag::input>(), *optionalInputFlagsIt)) {
1114 ++optionalInputFlagsIt;
1115 continue;
1116 }
1117 matchFlags.set<AudioIoFlags::Tag::input>(matchFlags.get<AudioIoFlags::Tag::input>() &
1118 ~makeBitPositionFlagMask(*optionalInputFlagsIt++));
Mikhail Naganov289468a2023-03-29 10:06:15 -07001119 portsIt = findPort(config, matchFlags, destinationPortIds);
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001120 ALOGI("%s: mix port for config %s, flags %s was not found in the module %s, "
1121 "retried with flags %s", __func__, config.toString().c_str(),
1122 flags.value().toString().c_str(), mInstance.c_str(),
1123 matchFlags.toString().c_str());
1124 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001125 if (portsIt == mPorts.end()) {
1126 ALOGE("%s: mix port for config %s, flags %s is not found in the module %s",
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001127 __func__, config.toString().c_str(), matchFlags.toString().c_str(),
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001128 mInstance.c_str());
1129 return BAD_VALUE;
1130 }
1131 AudioPortConfig requestedPortConfig;
1132 requestedPortConfig.portId = portsIt->first;
1133 setPortConfigFromConfig(&requestedPortConfig, config);
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001134 requestedPortConfig.ext = AudioPortMixExt{ .handle = ioHandle };
Mikhail Naganovd8d01f72023-03-09 16:24:40 -08001135 if (matchFlags.getTag() == AudioIoFlags::Tag::input
1136 && source != AudioSource::SYS_RESERVED_INVALID) {
1137 requestedPortConfig.ext.get<AudioPortExt::Tag::mix>().usecase =
1138 AudioPortMixExtUseCase::make<AudioPortMixExtUseCase::Tag::source>(source);
1139 }
David Lia8675d42023-03-30 21:08:06 +08001140 RETURN_STATUS_IF_ERROR(createOrUpdatePortConfig(requestedPortConfig, &portConfigIt,
1141 created));
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001142 } else if (!flags.has_value()) {
1143 ALOGW("%s: mix port config for %s, handle %d not found in the module %s, "
1144 "and was not created as flags are not specified",
1145 __func__, config.toString().c_str(), ioHandle, mInstance.c_str());
1146 return BAD_VALUE;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001147 } else {
David Lia8675d42023-03-30 21:08:06 +08001148 AudioPortConfig requestedPortConfig = portConfigIt->second;
1149 if (requestedPortConfig.ext.getTag() == AudioPortExt::Tag::mix) {
1150 AudioPortMixExt& mixExt = requestedPortConfig.ext.get<AudioPortExt::Tag::mix>();
1151 if (mixExt.usecase.getTag() == AudioPortMixExtUseCase::Tag::source &&
1152 source != AudioSource::SYS_RESERVED_INVALID) {
1153 mixExt.usecase.get<AudioPortMixExtUseCase::Tag::source>() = source;
1154 }
1155 }
1156
1157 if (requestedPortConfig != portConfigIt->second) {
1158 RETURN_STATUS_IF_ERROR(createOrUpdatePortConfig(requestedPortConfig, &portConfigIt,
1159 created));
1160 } else {
1161 *created = false;
1162 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001163 }
1164 *portConfig = portConfigIt->second;
1165 return OK;
1166}
1167
1168status_t DeviceHalAidl::findOrCreatePortConfig(
Mikhail Naganov289468a2023-03-29 10:06:15 -07001169 const AudioPortConfig& requestedPortConfig, const std::set<int32_t>& destinationPortIds,
1170 AudioPortConfig* portConfig, bool* created) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001171 using Tag = AudioPortExt::Tag;
1172 if (requestedPortConfig.ext.getTag() == Tag::mix) {
1173 if (const auto& p = requestedPortConfig;
1174 !p.sampleRate.has_value() || !p.channelMask.has_value() ||
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001175 !p.format.has_value()) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001176 ALOGW("%s: provided mix port config is not fully specified: %s",
1177 __func__, p.toString().c_str());
1178 return BAD_VALUE;
1179 }
1180 AudioConfig config;
1181 setConfigFromPortConfig(&config, requestedPortConfig);
Mikhail Naganovd8d01f72023-03-09 16:24:40 -08001182 AudioSource source = requestedPortConfig.ext.get<Tag::mix>().usecase.getTag() ==
1183 AudioPortMixExtUseCase::Tag::source ?
1184 requestedPortConfig.ext.get<Tag::mix>().usecase.
1185 get<AudioPortMixExtUseCase::Tag::source>() : AudioSource::SYS_RESERVED_INVALID;
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001186 return findOrCreatePortConfig(config, requestedPortConfig.flags,
Mikhail Naganov289468a2023-03-29 10:06:15 -07001187 requestedPortConfig.ext.get<Tag::mix>().handle, source, destinationPortIds,
1188 portConfig, created);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001189 } else if (requestedPortConfig.ext.getTag() == Tag::device) {
1190 return findOrCreatePortConfig(
jiabin9c07faf2023-04-26 22:00:44 +00001191 requestedPortConfig.ext.get<Tag::device>().device, nullptr /*config*/,
1192 portConfig, created);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001193 }
1194 ALOGW("%s: unsupported audio port config: %s",
1195 __func__, requestedPortConfig.toString().c_str());
1196 return BAD_VALUE;
1197}
1198
1199DeviceHalAidl::Patches::iterator DeviceHalAidl::findPatch(
1200 const std::set<int32_t>& sourcePortConfigIds, const std::set<int32_t>& sinkPortConfigIds) {
1201 return std::find_if(mPatches.begin(), mPatches.end(),
1202 [&](const auto& pair) {
1203 const auto& p = pair.second;
1204 std::set<int32_t> patchSrcs(
1205 p.sourcePortConfigIds.begin(), p.sourcePortConfigIds.end());
1206 std::set<int32_t> patchSinks(
1207 p.sinkPortConfigIds.begin(), p.sinkPortConfigIds.end());
1208 return sourcePortConfigIds == patchSrcs && sinkPortConfigIds == patchSinks; });
1209}
1210
1211DeviceHalAidl::Ports::iterator DeviceHalAidl::findPort(const AudioDevice& device) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001212 if (device.type.type == AudioDeviceType::IN_DEFAULT) {
1213 return mPorts.find(mDefaultInputPortId);
1214 } else if (device.type.type == AudioDeviceType::OUT_DEFAULT) {
1215 return mPorts.find(mDefaultOutputPortId);
1216 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001217 return std::find_if(mPorts.begin(), mPorts.end(),
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001218 [&](const auto& pair) { return audioDeviceMatches(device, pair.second); });
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001219}
1220
1221DeviceHalAidl::Ports::iterator DeviceHalAidl::findPort(
Mikhail Naganov289468a2023-03-29 10:06:15 -07001222 const AudioConfig& config, const AudioIoFlags& flags,
1223 const std::set<int32_t>& destinationPortIds) {
Mikhail Naganove93a0862023-03-15 17:06:59 -07001224 auto belongsToProfile = [&config](const AudioProfile& prof) {
1225 return (isDefaultAudioFormat(config.base.format) || prof.format == config.base.format) &&
1226 (config.base.channelMask.getTag() == AudioChannelLayout::none ||
1227 std::find(prof.channelMasks.begin(), prof.channelMasks.end(),
1228 config.base.channelMask) != prof.channelMasks.end()) &&
1229 (config.base.sampleRate == 0 ||
1230 std::find(prof.sampleRates.begin(), prof.sampleRates.end(),
1231 config.base.sampleRate) != prof.sampleRates.end());
1232 };
jiabin9c07faf2023-04-26 22:00:44 +00001233 static const std::vector<AudioOutputFlags> kOptionalOutputFlags{AudioOutputFlags::BIT_PERFECT};
1234 int optionalFlags = 0;
1235 auto flagMatches = [&flags, &optionalFlags](const AudioIoFlags& portFlags) {
1236 // Ports should be able to match if the optional flags are not requested.
1237 return portFlags == flags ||
1238 (portFlags.getTag() == AudioIoFlags::Tag::output &&
1239 AudioIoFlags::make<AudioIoFlags::Tag::output>(
1240 portFlags.get<AudioIoFlags::Tag::output>() &
1241 ~optionalFlags) == flags);
1242 };
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001243 auto matcher = [&](const auto& pair) {
1244 const auto& p = pair.second;
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001245 return p.ext.getTag() == AudioPortExt::Tag::mix &&
jiabin9c07faf2023-04-26 22:00:44 +00001246 flagMatches(p.flags) &&
Mikhail Naganov289468a2023-03-29 10:06:15 -07001247 (destinationPortIds.empty() ||
1248 std::any_of(destinationPortIds.begin(), destinationPortIds.end(),
1249 [&](const int32_t destId) { return mRoutingMatrix.count(
1250 std::make_pair(p.id, destId)) != 0; })) &&
Mikhail Naganove93a0862023-03-15 17:06:59 -07001251 (p.profiles.empty() ||
1252 std::find_if(p.profiles.begin(), p.profiles.end(), belongsToProfile) !=
1253 p.profiles.end()); };
jiabin9c07faf2023-04-26 22:00:44 +00001254 auto result = std::find_if(mPorts.begin(), mPorts.end(), matcher);
1255 if (result == mPorts.end() && flags.getTag() == AudioIoFlags::Tag::output) {
1256 auto optionalOutputFlagsIt = kOptionalOutputFlags.begin();
1257 while (result == mPorts.end() && optionalOutputFlagsIt != kOptionalOutputFlags.end()) {
1258 if (isBitPositionFlagSet(
1259 flags.get<AudioIoFlags::Tag::output>(), *optionalOutputFlagsIt)) {
1260 // If the flag is set by the request, it must be matched.
1261 ++optionalOutputFlagsIt;
1262 continue;
1263 }
1264 optionalFlags |= makeBitPositionFlagMask(*optionalOutputFlagsIt++);
1265 result = std::find_if(mPorts.begin(), mPorts.end(), matcher);
1266 ALOGI("%s: port for config %s, flags %s was not found in the module %s, "
1267 "retried with excluding optional flags %#x", __func__, config.toString().c_str(),
1268 flags.toString().c_str(), mInstance.c_str(), optionalFlags);
1269 }
1270 }
1271 return result;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001272}
1273
1274DeviceHalAidl::PortConfigs::iterator DeviceHalAidl::findPortConfig(const AudioDevice& device) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001275 return std::find_if(mPortConfigs.begin(), mPortConfigs.end(),
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001276 [&](const auto& pair) { return audioDeviceMatches(device, pair.second); });
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001277}
1278
1279DeviceHalAidl::PortConfigs::iterator DeviceHalAidl::findPortConfig(
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001280 const AudioConfig& config, const std::optional<AudioIoFlags>& flags, int32_t ioHandle) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001281 using Tag = AudioPortExt::Tag;
1282 return std::find_if(mPortConfigs.begin(), mPortConfigs.end(),
1283 [&](const auto& pair) {
1284 const auto& p = pair.second;
1285 LOG_ALWAYS_FATAL_IF(p.ext.getTag() == Tag::mix &&
1286 !p.sampleRate.has_value() || !p.channelMask.has_value() ||
1287 !p.format.has_value() || !p.flags.has_value(),
1288 "%s: stored mix port config is not fully specified: %s",
1289 __func__, p.toString().c_str());
1290 return p.ext.getTag() == Tag::mix &&
1291 isConfigEqualToPortConfig(config, p) &&
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001292 (!flags.has_value() || p.flags.value() == flags.value()) &&
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001293 p.ext.template get<Tag::mix>().handle == ioHandle; });
1294}
Mikhail Naganove93a0862023-03-15 17:06:59 -07001295
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001296void DeviceHalAidl::resetPatch(int32_t patchId) {
1297 if (auto it = mPatches.find(patchId); it != mPatches.end()) {
1298 mPatches.erase(it);
1299 TIME_CHECK();
1300 if (ndk::ScopedAStatus status = mModule->resetAudioPatch(patchId); !status.isOk()) {
1301 ALOGE("%s: error while resetting patch %d: %s",
1302 __func__, patchId, status.getDescription().c_str());
1303 }
1304 return;
1305 }
1306 ALOGE("%s: patch id %d not found", __func__, patchId);
1307}
1308
1309void DeviceHalAidl::resetPortConfig(int32_t portConfigId) {
1310 if (auto it = mPortConfigs.find(portConfigId); it != mPortConfigs.end()) {
1311 mPortConfigs.erase(it);
1312 TIME_CHECK();
1313 if (ndk::ScopedAStatus status = mModule->resetAudioPortConfig(portConfigId);
1314 !status.isOk()) {
1315 ALOGE("%s: error while resetting port config %d: %s",
1316 __func__, portConfigId, status.getDescription().c_str());
1317 }
1318 return;
1319 }
1320 ALOGE("%s: port config id %d not found", __func__, portConfigId);
1321}
1322
Mikhail Naganove93a0862023-03-15 17:06:59 -07001323void DeviceHalAidl::resetUnusedPatches() {
1324 // Since patches can be created independently of streams via 'createAudioPatch',
1325 // here we only clean up patches for released streams.
1326 for (auto it = mStreams.begin(); it != mStreams.end(); ) {
1327 if (auto streamSp = it->first.promote(); streamSp) {
1328 ++it;
1329 } else {
1330 resetPatch(it->second);
1331 it = mStreams.erase(it);
1332 }
1333 }
1334}
1335
1336void DeviceHalAidl::resetUnusedPatchesAndPortConfigs() {
1337 resetUnusedPatches();
1338 resetUnusedPortConfigs();
1339}
1340
1341void DeviceHalAidl::resetUnusedPortConfigs() {
1342 // The assumption is that port configs are used to create patches
1343 // (or to open streams, but that involves creation of patches, too). Thus,
1344 // orphaned port configs can and should be reset.
1345 std::set<int32_t> portConfigIds;
1346 std::transform(mPortConfigs.begin(), mPortConfigs.end(),
1347 std::inserter(portConfigIds, portConfigIds.end()),
1348 [](const auto& pcPair) { return pcPair.first; });
1349 for (const auto& p : mPatches) {
1350 for (int32_t id : p.second.sourcePortConfigIds) portConfigIds.erase(id);
1351 for (int32_t id : p.second.sinkPortConfigIds) portConfigIds.erase(id);
1352 }
jiabin9c07faf2023-04-26 22:00:44 +00001353 for (int32_t id : mInitialPortConfigIds) {
1354 portConfigIds.erase(id);
1355 }
Mikhail Naganove93a0862023-03-15 17:06:59 -07001356 for (int32_t id : portConfigIds) resetPortConfig(id);
1357}
1358
Mikhail Naganov289468a2023-03-29 10:06:15 -07001359status_t DeviceHalAidl::updateRoutes() {
1360 TIME_CHECK();
Mikhail Naganov289468a2023-03-29 10:06:15 -07001361 RETURN_STATUS_IF_ERROR(
Mikhail Naganovf83b9742023-04-24 13:06:04 -07001362 statusTFromBinderStatus(mModule->getAudioRoutes(&mRoutes)));
1363 ALOGW_IF(mRoutes.empty(), "%s: module %s returned an empty list of audio routes",
Mikhail Naganov289468a2023-03-29 10:06:15 -07001364 __func__, mInstance.c_str());
1365 mRoutingMatrix.clear();
Mikhail Naganovf83b9742023-04-24 13:06:04 -07001366 for (const auto& r : mRoutes) {
Mikhail Naganov289468a2023-03-29 10:06:15 -07001367 for (auto portId : r.sourcePortIds) {
1368 mRoutingMatrix.emplace(r.sinkPortId, portId);
1369 mRoutingMatrix.emplace(portId, r.sinkPortId);
1370 }
1371 }
1372 return OK;
1373}
1374
Mikhail Naganovdfd594e2023-02-08 16:59:41 -08001375void DeviceHalAidl::clearCallbacks(void* cookie) {
1376 std::lock_guard l(mLock);
1377 mCallbacks.erase(cookie);
1378}
1379
1380sp<StreamOutHalInterfaceCallback> DeviceHalAidl::getStreamOutCallback(void* cookie) {
1381 return getCallbackImpl(cookie, &Callbacks::out);
1382}
1383
1384void DeviceHalAidl::setStreamOutCallback(
1385 void* cookie, const sp<StreamOutHalInterfaceCallback>& cb) {
1386 setCallbackImpl(cookie, &Callbacks::out, cb);
1387}
1388
1389sp<StreamOutHalInterfaceEventCallback> DeviceHalAidl::getStreamOutEventCallback(
1390 void* cookie) {
1391 return getCallbackImpl(cookie, &Callbacks::event);
1392}
1393
1394void DeviceHalAidl::setStreamOutEventCallback(
1395 void* cookie, const sp<StreamOutHalInterfaceEventCallback>& cb) {
1396 setCallbackImpl(cookie, &Callbacks::event, cb);
1397}
1398
1399sp<StreamOutHalInterfaceLatencyModeCallback> DeviceHalAidl::getStreamOutLatencyModeCallback(
1400 void* cookie) {
1401 return getCallbackImpl(cookie, &Callbacks::latency);
1402}
1403
1404void DeviceHalAidl::setStreamOutLatencyModeCallback(
1405 void* cookie, const sp<StreamOutHalInterfaceLatencyModeCallback>& cb) {
1406 setCallbackImpl(cookie, &Callbacks::latency, cb);
1407}
1408
1409template<class C>
1410sp<C> DeviceHalAidl::getCallbackImpl(void* cookie, wp<C> DeviceHalAidl::Callbacks::* field) {
1411 std::lock_guard l(mLock);
1412 if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
1413 return ((it->second).*field).promote();
1414 }
1415 return nullptr;
1416}
1417template<class C>
1418void DeviceHalAidl::setCallbackImpl(
1419 void* cookie, wp<C> DeviceHalAidl::Callbacks::* field, const sp<C>& cb) {
1420 std::lock_guard l(mLock);
1421 if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
1422 (it->second).*field = cb;
1423 }
1424}
1425
Mikhail Naganov31d46652023-01-10 18:29:25 +00001426} // namespace android