blob: f9939071cd1a70798a443bac91d983aa09a4c5c9 [file] [log] [blame]
Shunkai Yao51202502022-12-12 06:11:46 +00001/*
2 * Copyright (C) 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "DeviceHalAidl"
Vlad Popa03bd5bc2023-01-17 16:16:51 +010018// #define LOG_NDEBUG 0
Shunkai Yao51202502022-12-12 06:11:46 +000019
Mikhail Naganovf56ce782023-01-25 11:29:11 -080020#include <algorithm>
21#include <forward_list>
22
Mikhail Naganovb0c55252023-02-08 16:59:41 -080023#include <aidl/android/hardware/audio/core/BnStreamCallback.h>
24#include <aidl/android/hardware/audio/core/BnStreamOutEventCallback.h>
Mikhail Naganovfab697c2023-01-11 19:33:13 +000025#include <aidl/android/hardware/audio/core/StreamDescriptor.h>
26#include <error/expected_utils.h>
27#include <media/AidlConversionCppNdk.h>
Mikhail Naganovbfbb75b2023-04-21 18:48:16 -070028#include <media/AidlConversionNdkCpp.h>
Mikhail Naganovfab697c2023-01-11 19:33:13 +000029#include <media/AidlConversionUtil.h>
Mikhail Naganov31d46652023-01-10 18:29:25 +000030#include <mediautils/TimeCheck.h>
Mikhail Naganov8bd806e2023-01-30 12:33:18 -080031#include <Utils.h>
Mikhail Naganov31d46652023-01-10 18:29:25 +000032#include <utils/Log.h>
Shunkai Yao51202502022-12-12 06:11:46 +000033
Mikhail Naganov31d46652023-01-10 18:29:25 +000034#include "DeviceHalAidl.h"
35#include "StreamHalAidl.h"
36
Mikhail Naganovfab697c2023-01-11 19:33:13 +000037using aidl::android::aidl_utils::statusTFromBinderStatus;
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -070038using aidl::android::media::audio::common::AudioChannelLayout;
Mikhail Naganovf56ce782023-01-25 11:29:11 -080039using aidl::android::media::audio::common::AudioConfig;
40using aidl::android::media::audio::common::AudioDevice;
David Li9cf5e622023-03-21 00:51:10 +080041using aidl::android::media::audio::common::AudioDeviceAddress;
Mikhail Naganov8bd806e2023-01-30 12:33:18 -080042using aidl::android::media::audio::common::AudioDeviceType;
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -070043using aidl::android::media::audio::common::AudioFormatType;
Mikhail Naganov8bd806e2023-01-30 12:33:18 -080044using aidl::android::media::audio::common::AudioInputFlags;
Mikhail Naganovf56ce782023-01-25 11:29:11 -080045using aidl::android::media::audio::common::AudioIoFlags;
Mikhail Naganovb0c55252023-02-08 16:59:41 -080046using aidl::android::media::audio::common::AudioLatencyMode;
David Li9cf5e622023-03-21 00:51:10 +080047using aidl::android::media::audio::common::AudioMMapPolicy;
48using aidl::android::media::audio::common::AudioMMapPolicyInfo;
49using aidl::android::media::audio::common::AudioMMapPolicyType;
Mikhail Naganovfab697c2023-01-11 19:33:13 +000050using aidl::android::media::audio::common::AudioMode;
Mikhail Naganovf56ce782023-01-25 11:29:11 -080051using aidl::android::media::audio::common::AudioOutputFlags;
52using aidl::android::media::audio::common::AudioPort;
53using aidl::android::media::audio::common::AudioPortConfig;
Mikhail Naganov8bd806e2023-01-30 12:33:18 -080054using aidl::android::media::audio::common::AudioPortDeviceExt;
David Li9cf5e622023-03-21 00:51:10 +080055using aidl::android::media::audio::common::AudioPortExt;
Mikhail Naganov1a44bc62023-02-16 17:35:06 -080056using aidl::android::media::audio::common::AudioPortMixExt;
Mikhail Naganovd8d01f72023-03-09 16:24:40 -080057using aidl::android::media::audio::common::AudioPortMixExtUseCase;
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -070058using aidl::android::media::audio::common::AudioProfile;
Mikhail Naganovf56ce782023-01-25 11:29:11 -080059using aidl::android::media::audio::common::AudioSource;
Mikhail Naganovfab697c2023-01-11 19:33:13 +000060using aidl::android::media::audio::common::Float;
David Li9cf5e622023-03-21 00:51:10 +080061using aidl::android::media::audio::common::Int;
62using aidl::android::media::audio::common::MicrophoneDynamicInfo;
63using aidl::android::media::audio::common::MicrophoneInfo;
Mikhail Naganov6352e822023-03-09 18:22:36 -080064using aidl::android::hardware::audio::common::getFrameSizeInBytes;
65using aidl::android::hardware::audio::common::isBitPositionFlagSet;
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -070066using aidl::android::hardware::audio::common::isDefaultAudioFormat;
Mikhail Naganov6352e822023-03-09 18:22:36 -080067using aidl::android::hardware::audio::common::makeBitPositionFlagMask;
Mikhail Naganovf56ce782023-01-25 11:29:11 -080068using aidl::android::hardware::audio::common::RecordTrackMetadata;
69using aidl::android::hardware::audio::core::AudioPatch;
Mikhail Naganovecfafb72023-03-29 10:06:15 -070070using aidl::android::hardware::audio::core::AudioRoute;
Mikhail Naganovfab697c2023-01-11 19:33:13 +000071using aidl::android::hardware::audio::core::IModule;
72using aidl::android::hardware::audio::core::ITelephony;
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -070073using aidl::android::hardware::audio::core::ModuleDebug;
Mikhail Naganovfab697c2023-01-11 19:33:13 +000074using aidl::android::hardware::audio::core::StreamDescriptor;
Mikhail Naganov31d46652023-01-10 18:29:25 +000075
76namespace android {
77
Mikhail Naganovf56ce782023-01-25 11:29:11 -080078namespace {
79
80bool isConfigEqualToPortConfig(const AudioConfig& config, const AudioPortConfig& portConfig) {
81 return portConfig.sampleRate.value().value == config.base.sampleRate &&
82 portConfig.channelMask.value() == config.base.channelMask &&
83 portConfig.format.value() == config.base.format;
84}
85
86void setConfigFromPortConfig(AudioConfig* config, const AudioPortConfig& portConfig) {
87 config->base.sampleRate = portConfig.sampleRate.value().value;
88 config->base.channelMask = portConfig.channelMask.value();
89 config->base.format = portConfig.format.value();
90}
91
92void setPortConfigFromConfig(AudioPortConfig* portConfig, const AudioConfig& config) {
93 portConfig->sampleRate = Int{ .value = config.base.sampleRate };
94 portConfig->channelMask = config.base.channelMask;
95 portConfig->format = config.base.format;
96}
97
Mikhail Naganov2d814892023-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;
107 return cpp;
108}
109
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800110} // namespace
111
Mikhail Naganov2d814892023-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 Naganovf56ce782023-01-25 11:29:11 -0800133 TIME_CHECK();
Mikhail Naganov31d46652023-01-10 18:29:25 +0000134 if (mModule == nullptr) return NO_INIT;
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800135 std::vector<AudioPort> ports;
Mikhail Naganov2d814892023-04-24 13:06:04 -0700136 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->getAudioPorts(&ports)));
Mikhail Naganovf56ce782023-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 Naganov8bd806e2023-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 Naganovecfafb72023-03-29 10:06:15 -0700156 RETURN_STATUS_IF_ERROR(updateRoutes());
Mikhail Naganovf56ce782023-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); });
jiabin2248fa12023-04-27 22:04:16 +0000163 std::transform(mPortConfigs.begin(), mPortConfigs.end(),
164 std::inserter(mInitialPortConfigIds, mInitialPortConfigIds.end()),
165 [](const auto& pcPair) { return pcPair.first; });
Mikhail Naganovf56ce782023-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 Naganovf56ce782023-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 Naganov8bd806e2023-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 Naganov8bd806e2023-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 Naganovb1ddbb02023-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 Naganovb1ddbb02023-03-15 17:06:59 -0700303 &writableConfig, &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
Mikhail Naganov8bd806e2023-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 Naganovf56ce782023-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 Naganov8bd806e2023-01-30 12:33:18 -0800313 Cleanups* cleanups, AudioConfig* aidlConfig, AudioPortConfig* mixPortConfig,
Mikhail Naganovb1ddbb02023-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());
jiabin2248fa12023-04-27 22:04:16 +0000319 resetUnusedPatchesAndPortConfigs();
Mikhail Naganovf56ce782023-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;
jiabin2248fa12023-04-27 22:04:16 +0000325 RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(aidlDevice, aidlConfig,
326 &devicePortConfig, &created));
Mikhail Naganovf56ce782023-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 Naganovecfafb72023-03-29 10:06:15 -0700331 std::set<int32_t>{devicePortConfig.portId}, mixPortConfig, &created));
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800332 if (created) {
333 cleanups->emplace_front(this, &DeviceHalAidl::resetPortConfig, mixPortConfig->id);
334 }
335 setConfigFromPortConfig(aidlConfig, *mixPortConfig);
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800336 if (isInput) {
337 RETURN_STATUS_IF_ERROR(findOrCreatePatch(
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700338 {devicePortConfig.id}, {mixPortConfig->id}, aidlPatch, &created));
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800339 } else {
340 RETURN_STATUS_IF_ERROR(findOrCreatePatch(
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700341 {mixPortConfig->id}, {devicePortConfig.id}, aidlPatch, &created));
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800342 }
343 if (created) {
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700344 cleanups->emplace_front(this, &DeviceHalAidl::resetPatch, aidlPatch->id);
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800345 }
346 if (aidlConfig->frameCount <= 0) {
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700347 aidlConfig->frameCount = aidlPatch->minimumStreamBufferSizeFrames;
Mikhail Naganovf56ce782023-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 Naganovb0c55252023-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 Naganovf56ce782023-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 Naganov8bd806e2023-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 Naganovf56ce782023-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 Naganovb1ddbb02023-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 Naganovb1ddbb02023-03-15 17:06:59 -0700496 config, &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800497 ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamArguments args;
498 args.portConfigId = mixPortConfig.id;
Mikhail Naganovb0c55252023-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 Naganovf56ce782023-01-25 11:29:11 -0800510 args.bufferSizeFrames = aidlConfig.frameCount;
Mikhail Naganovb0c55252023-02-08 16:59:41 -0800511 args.eventCallback = eventCb;
Mikhail Naganovf56ce782023-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 Naganov8bd806e2023-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 Naganovb1ddbb02023-03-15 17:06:59 -0700520 *outStream = sp<StreamOutHalAidl>::make(*config, std::move(context), aidlPatch.latenciesMs[0],
Mikhail Naganovb0c55252023-02-08 16:59:41 -0800521 std::move(ret.stream), this /*callbackBroker*/);
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700522 mStreams.insert(std::pair(*outStream, aidlPatch.id));
Mikhail Naganovb0c55252023-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 Naganovf56ce782023-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 Naganovf56ce782023-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 Naganov8bd806e2023-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 Naganovf56ce782023-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 Naganovb1ddbb02023-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 Naganovb1ddbb02023-03-15 17:06:59 -0700561 config, &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
Mikhail Naganovf56ce782023-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 Naganov8bd806e2023-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 Naganovb1ddbb02023-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 Naganovb1ddbb02023-03-15 17:06:59 -0700583 mStreams.insert(std::pair(*inStream, aidlPatch.id));
Mikhail Naganovf56ce782023-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 Naganovf56ce782023-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 Naganov8bd806e2023-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 Naganovf56ce782023-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 Naganovf56ce782023-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 Naganovf56ce782023-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 Naganovf56ce782023-01-25 11:29:11 -0800646 }
Mikhail Naganov8bd806e2023-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 Naganovf56ce782023-01-25 11:29:11 -0800650 auto fillPortConfigs = [&](
Mikhail Naganovecfafb72023-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 Naganovf56ce782023-01-25 11:29:11 -0800654 for (const auto& s : configs) {
655 AudioPortConfig portConfig;
656 bool created = false;
Mikhail Naganovecfafb72023-03-29 10:06:15 -0700657 RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(
658 s, destinationPortIds, &portConfig, &created));
Mikhail Naganovf56ce782023-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 Naganovecfafb72023-03-29 10:06:15 -0700663 if (portIds != nullptr) {
664 portIds->insert(portConfig.portId);
665 }
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800666 }
667 return OK;
668 };
Mikhail Naganovecfafb72023-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 Naganovf56ce782023-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 Naganovf56ce782023-01-25 11:29:11 -0800696 }
697 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000698 return OK;
699}
700
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800701status_t DeviceHalAidl::releaseAudioPatch(audio_patch_handle_t patch) {
Mikhail Naganov8bd806e2023-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 Naganovf56ce782023-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 Naganovb1ddbb02023-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 Naganovb1ddbb02023-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 Naganovecfafb72023-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 Naganovbfbb75b2023-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
Vlad Popa03bd5bc2023-01-17 16:16:51 +0100910status_t DeviceHalAidl::getSoundDoseInterface(const std::string& module,
911 ::ndk::SpAIBinder* soundDoseBinder) {
912 TIME_CHECK();
913 if (!mModule) return NO_INIT;
914 if (mSoundDose == nullptr) {
915 ndk::ScopedAStatus status = mModule->getSoundDose(&mSoundDose);
916 if (!status.isOk()) {
917 ALOGE("%s failed to return the sound dose interface for module %s: %s",
918 __func__,
919 module.c_str(),
920 status.getDescription().c_str());
921 return BAD_VALUE;
922 }
923 }
924 *soundDoseBinder = mSoundDose->asBinder();
925 ALOGI("%s using audio AIDL HAL sound dose interface", __func__);
926
927 return OK;
928}
929
jiabinc0048632023-04-27 22:04:31 +0000930status_t DeviceHalAidl::prepareToDisconnectExternalDevice(const struct audio_port_v7* port) {
931 // There is not AIDL API defined for `prepareToDisconnectExternalDevice`.
932 // Call `setConnectedState` instead.
933 // TODO(b/279824103): call prepareToDisconnectExternalDevice when it is added.
934 const status_t status = setConnectedState(port, false /*connected*/);
935 if (status == NO_ERROR) {
936 mDeviceDisconnectionNotified.insert(port->id);
937 }
938 return status;
939}
940
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700941status_t DeviceHalAidl::setConnectedState(const struct audio_port_v7 *port, bool connected) {
942 TIME_CHECK();
943 if (!mModule) return NO_INIT;
944 if (port == nullptr) {
945 return BAD_VALUE;
946 }
jiabinc0048632023-04-27 22:04:31 +0000947 if (!connected && mDeviceDisconnectionNotified.erase(port->id) > 0) {
948 // For device disconnection, APM will first call `prepareToDisconnectExternalDevice`
949 // and then call `setConnectedState`. However, there is no API for
950 // `prepareToDisconnectExternalDevice` yet. In that case, `setConnectedState` will be
951 // called when calling `prepareToDisconnectExternalDevice`. Do not call to the HAL if
952 // previous call is successful. Also remove the cache here to avoid a large cache after
953 // a long run.
954 return NO_ERROR;
955 }
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700956 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(port->role, port->type)) ==
957 ::aidl::android::AudioPortDirection::INPUT;
958 AudioPort aidlPort = VALUE_OR_RETURN_STATUS(
959 ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
960 if (aidlPort.ext.getTag() != AudioPortExt::device) {
961 ALOGE("%s: provided port is not a device port (module %s): %s",
962 __func__, mInstance.c_str(), aidlPort.toString().c_str());
963 return BAD_VALUE;
964 }
965 if (connected) {
966 AudioDevice matchDevice = aidlPort.ext.get<AudioPortExt::device>().device;
967 // Reset the device address to find the "template" port.
968 matchDevice.address = AudioDeviceAddress::make<AudioDeviceAddress::id>();
969 auto portsIt = findPort(matchDevice);
970 if (portsIt == mPorts.end()) {
971 ALOGW("%s: device port for device %s is not found in the module %s",
972 __func__, matchDevice.toString().c_str(), mInstance.c_str());
973 return BAD_VALUE;
974 }
975 // Use the ID of the "template" port, use all the information from the provided port.
976 aidlPort.id = portsIt->first;
977 AudioPort connectedPort;
978 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->connectExternalDevice(
979 aidlPort, &connectedPort)));
980 const auto [it, inserted] = mPorts.insert(std::make_pair(connectedPort.id, connectedPort));
981 LOG_ALWAYS_FATAL_IF(!inserted,
982 "%s: module %s, duplicate port ID received from HAL: %s, existing port: %s",
983 __func__, mInstance.c_str(), connectedPort.toString().c_str(),
984 it->second.toString().c_str());
985 } else { // !connected
986 AudioDevice matchDevice = aidlPort.ext.get<AudioPortExt::device>().device;
987 auto portsIt = findPort(matchDevice);
988 if (portsIt == mPorts.end()) {
989 ALOGW("%s: device port for device %s is not found in the module %s",
990 __func__, matchDevice.toString().c_str(), mInstance.c_str());
991 return BAD_VALUE;
992 }
993 // Any streams opened on the external device must be closed by this time,
994 // thus we can clean up patches and port configs that were created for them.
995 resetUnusedPatchesAndPortConfigs();
996 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->disconnectExternalDevice(
997 portsIt->second.id)));
998 mPorts.erase(portsIt);
999 }
Mikhail Naganovecfafb72023-03-29 10:06:15 -07001000 return updateRoutes();
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -07001001}
1002
1003status_t DeviceHalAidl::setSimulateDeviceConnections(bool enabled) {
1004 TIME_CHECK();
1005 if (!mModule) return NO_INIT;
1006 ModuleDebug debug{ .simulateDeviceConnections = enabled };
1007 status_t status = statusTFromBinderStatus(mModule->setModuleDebug(debug));
1008 // This is important to log as it affects HAL behavior.
1009 if (status == OK) {
1010 ALOGI("%s: set enabled: %d", __func__, enabled);
1011 } else {
1012 ALOGW("%s: set enabled to %d failed: %d", __func__, enabled, status);
1013 }
1014 return status;
1015}
1016
Mikhail Naganov8bd806e2023-01-30 12:33:18 -08001017bool DeviceHalAidl::audioDeviceMatches(const AudioDevice& device, const AudioPort& p) {
1018 if (p.ext.getTag() != AudioPortExt::Tag::device) return false;
1019 return p.ext.get<AudioPortExt::Tag::device>().device == device;
1020}
1021
1022bool DeviceHalAidl::audioDeviceMatches(const AudioDevice& device, const AudioPortConfig& p) {
1023 if (p.ext.getTag() != AudioPortExt::Tag::device) return false;
1024 if (device.type.type == AudioDeviceType::IN_DEFAULT) {
1025 return p.portId == mDefaultInputPortId;
1026 } else if (device.type.type == AudioDeviceType::OUT_DEFAULT) {
1027 return p.portId == mDefaultOutputPortId;
1028 }
1029 return p.ext.get<AudioPortExt::Tag::device>().device == device;
1030}
1031
David Lia8f1e582023-03-30 21:08:06 +08001032status_t DeviceHalAidl::createOrUpdatePortConfig(
1033 const AudioPortConfig& requestedPortConfig, PortConfigs::iterator* result, bool* created) {
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001034 TIME_CHECK();
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001035 AudioPortConfig appliedPortConfig;
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001036 bool applied = false;
1037 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPortConfig(
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001038 requestedPortConfig, &appliedPortConfig, &applied)));
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001039 if (!applied) {
1040 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPortConfig(
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001041 appliedPortConfig, &appliedPortConfig, &applied)));
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001042 if (!applied) {
1043 ALOGE("%s: module %s did not apply suggested config %s",
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001044 __func__, mInstance.c_str(), appliedPortConfig.toString().c_str());
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001045 return NO_INIT;
1046 }
1047 }
David Lia8f1e582023-03-30 21:08:06 +08001048
1049 int32_t id = appliedPortConfig.id;
1050 if (requestedPortConfig.id != 0 && requestedPortConfig.id != id) {
1051 LOG_ALWAYS_FATAL("%s: requested port config id %d changed to %d", __func__,
1052 requestedPortConfig.id, id);
1053 }
1054
1055 auto [it, inserted] = mPortConfigs.insert_or_assign(std::move(id),
1056 std::move(appliedPortConfig));
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001057 *result = it;
David Lia8f1e582023-03-30 21:08:06 +08001058 *created = inserted;
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001059 return OK;
1060}
1061
1062status_t DeviceHalAidl::findOrCreatePatch(
1063 const AudioPatch& requestedPatch, AudioPatch* patch, bool* created) {
1064 std::set<int32_t> sourcePortConfigIds(requestedPatch.sourcePortConfigIds.begin(),
1065 requestedPatch.sourcePortConfigIds.end());
1066 std::set<int32_t> sinkPortConfigIds(requestedPatch.sinkPortConfigIds.begin(),
1067 requestedPatch.sinkPortConfigIds.end());
1068 return findOrCreatePatch(sourcePortConfigIds, sinkPortConfigIds, patch, created);
1069}
1070
1071status_t DeviceHalAidl::findOrCreatePatch(
1072 const std::set<int32_t>& sourcePortConfigIds, const std::set<int32_t>& sinkPortConfigIds,
1073 AudioPatch* patch, bool* created) {
1074 auto patchIt = findPatch(sourcePortConfigIds, sinkPortConfigIds);
1075 if (patchIt == mPatches.end()) {
1076 TIME_CHECK();
1077 AudioPatch requestedPatch, appliedPatch;
1078 requestedPatch.sourcePortConfigIds.insert(requestedPatch.sourcePortConfigIds.end(),
1079 sourcePortConfigIds.begin(), sourcePortConfigIds.end());
1080 requestedPatch.sinkPortConfigIds.insert(requestedPatch.sinkPortConfigIds.end(),
1081 sinkPortConfigIds.begin(), sinkPortConfigIds.end());
1082 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPatch(
1083 requestedPatch, &appliedPatch)));
1084 patchIt = mPatches.insert(mPatches.end(), std::make_pair(appliedPatch.id, appliedPatch));
1085 *created = true;
1086 } else {
1087 *created = false;
1088 }
1089 *patch = patchIt->second;
1090 return OK;
1091}
1092
jiabin2248fa12023-04-27 22:04:16 +00001093status_t DeviceHalAidl::findOrCreatePortConfig(const AudioDevice& device, const AudioConfig* config,
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001094 AudioPortConfig* portConfig, bool* created) {
1095 auto portConfigIt = findPortConfig(device);
1096 if (portConfigIt == mPortConfigs.end()) {
1097 auto portsIt = findPort(device);
1098 if (portsIt == mPorts.end()) {
1099 ALOGE("%s: device port for device %s is not found in the module %s",
1100 __func__, device.toString().c_str(), mInstance.c_str());
1101 return BAD_VALUE;
1102 }
1103 AudioPortConfig requestedPortConfig;
1104 requestedPortConfig.portId = portsIt->first;
jiabin2248fa12023-04-27 22:04:16 +00001105 if (config != nullptr) {
1106 setPortConfigFromConfig(&requestedPortConfig, *config);
1107 }
David Lia8f1e582023-03-30 21:08:06 +08001108 RETURN_STATUS_IF_ERROR(createOrUpdatePortConfig(requestedPortConfig, &portConfigIt,
1109 created));
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001110 } else {
1111 *created = false;
1112 }
1113 *portConfig = portConfigIt->second;
1114 return OK;
1115}
1116
1117status_t DeviceHalAidl::findOrCreatePortConfig(
Mikhail Naganov8bd806e2023-01-30 12:33:18 -08001118 const AudioConfig& config, const std::optional<AudioIoFlags>& flags, int32_t ioHandle,
Mikhail Naganovecfafb72023-03-29 10:06:15 -07001119 AudioSource source, const std::set<int32_t>& destinationPortIds,
1120 AudioPortConfig* portConfig, bool* created) {
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001121 // These flags get removed one by one in this order when retrying port finding.
1122 static const std::vector<AudioInputFlags> kOptionalInputFlags{
1123 AudioInputFlags::FAST, AudioInputFlags::RAW };
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001124 auto portConfigIt = findPortConfig(config, flags, ioHandle);
Mikhail Naganov8bd806e2023-01-30 12:33:18 -08001125 if (portConfigIt == mPortConfigs.end() && flags.has_value()) {
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001126 auto optionalInputFlagsIt = kOptionalInputFlags.begin();
1127 AudioIoFlags matchFlags = flags.value();
Mikhail Naganovecfafb72023-03-29 10:06:15 -07001128 auto portsIt = findPort(config, matchFlags, destinationPortIds);
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001129 while (portsIt == mPorts.end() && matchFlags.getTag() == AudioIoFlags::Tag::input
1130 && optionalInputFlagsIt != kOptionalInputFlags.end()) {
1131 if (!isBitPositionFlagSet(
1132 matchFlags.get<AudioIoFlags::Tag::input>(), *optionalInputFlagsIt)) {
1133 ++optionalInputFlagsIt;
1134 continue;
1135 }
1136 matchFlags.set<AudioIoFlags::Tag::input>(matchFlags.get<AudioIoFlags::Tag::input>() &
1137 ~makeBitPositionFlagMask(*optionalInputFlagsIt++));
Mikhail Naganovecfafb72023-03-29 10:06:15 -07001138 portsIt = findPort(config, matchFlags, destinationPortIds);
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001139 ALOGI("%s: mix port for config %s, flags %s was not found in the module %s, "
1140 "retried with flags %s", __func__, config.toString().c_str(),
1141 flags.value().toString().c_str(), mInstance.c_str(),
1142 matchFlags.toString().c_str());
1143 }
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001144 if (portsIt == mPorts.end()) {
1145 ALOGE("%s: mix port for config %s, flags %s is not found in the module %s",
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001146 __func__, config.toString().c_str(), matchFlags.toString().c_str(),
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001147 mInstance.c_str());
1148 return BAD_VALUE;
1149 }
1150 AudioPortConfig requestedPortConfig;
1151 requestedPortConfig.portId = portsIt->first;
1152 setPortConfigFromConfig(&requestedPortConfig, config);
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001153 requestedPortConfig.ext = AudioPortMixExt{ .handle = ioHandle };
Mikhail Naganovd8d01f72023-03-09 16:24:40 -08001154 if (matchFlags.getTag() == AudioIoFlags::Tag::input
1155 && source != AudioSource::SYS_RESERVED_INVALID) {
1156 requestedPortConfig.ext.get<AudioPortExt::Tag::mix>().usecase =
1157 AudioPortMixExtUseCase::make<AudioPortMixExtUseCase::Tag::source>(source);
1158 }
David Lia8f1e582023-03-30 21:08:06 +08001159 RETURN_STATUS_IF_ERROR(createOrUpdatePortConfig(requestedPortConfig, &portConfigIt,
1160 created));
Mikhail Naganov8bd806e2023-01-30 12:33:18 -08001161 } else if (!flags.has_value()) {
1162 ALOGW("%s: mix port config for %s, handle %d not found in the module %s, "
1163 "and was not created as flags are not specified",
1164 __func__, config.toString().c_str(), ioHandle, mInstance.c_str());
1165 return BAD_VALUE;
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001166 } else {
David Lia8f1e582023-03-30 21:08:06 +08001167 AudioPortConfig requestedPortConfig = portConfigIt->second;
1168 if (requestedPortConfig.ext.getTag() == AudioPortExt::Tag::mix) {
1169 AudioPortMixExt& mixExt = requestedPortConfig.ext.get<AudioPortExt::Tag::mix>();
1170 if (mixExt.usecase.getTag() == AudioPortMixExtUseCase::Tag::source &&
1171 source != AudioSource::SYS_RESERVED_INVALID) {
1172 mixExt.usecase.get<AudioPortMixExtUseCase::Tag::source>() = source;
1173 }
1174 }
1175
1176 if (requestedPortConfig != portConfigIt->second) {
1177 RETURN_STATUS_IF_ERROR(createOrUpdatePortConfig(requestedPortConfig, &portConfigIt,
1178 created));
1179 } else {
1180 *created = false;
1181 }
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001182 }
1183 *portConfig = portConfigIt->second;
1184 return OK;
1185}
1186
1187status_t DeviceHalAidl::findOrCreatePortConfig(
Mikhail Naganovecfafb72023-03-29 10:06:15 -07001188 const AudioPortConfig& requestedPortConfig, const std::set<int32_t>& destinationPortIds,
1189 AudioPortConfig* portConfig, bool* created) {
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001190 using Tag = AudioPortExt::Tag;
1191 if (requestedPortConfig.ext.getTag() == Tag::mix) {
1192 if (const auto& p = requestedPortConfig;
1193 !p.sampleRate.has_value() || !p.channelMask.has_value() ||
Mikhail Naganov8bd806e2023-01-30 12:33:18 -08001194 !p.format.has_value()) {
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001195 ALOGW("%s: provided mix port config is not fully specified: %s",
1196 __func__, p.toString().c_str());
1197 return BAD_VALUE;
1198 }
1199 AudioConfig config;
1200 setConfigFromPortConfig(&config, requestedPortConfig);
Mikhail Naganovd8d01f72023-03-09 16:24:40 -08001201 AudioSource source = requestedPortConfig.ext.get<Tag::mix>().usecase.getTag() ==
1202 AudioPortMixExtUseCase::Tag::source ?
1203 requestedPortConfig.ext.get<Tag::mix>().usecase.
1204 get<AudioPortMixExtUseCase::Tag::source>() : AudioSource::SYS_RESERVED_INVALID;
Mikhail Naganov8bd806e2023-01-30 12:33:18 -08001205 return findOrCreatePortConfig(config, requestedPortConfig.flags,
Mikhail Naganovecfafb72023-03-29 10:06:15 -07001206 requestedPortConfig.ext.get<Tag::mix>().handle, source, destinationPortIds,
1207 portConfig, created);
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001208 } else if (requestedPortConfig.ext.getTag() == Tag::device) {
1209 return findOrCreatePortConfig(
jiabin2248fa12023-04-27 22:04:16 +00001210 requestedPortConfig.ext.get<Tag::device>().device, nullptr /*config*/,
1211 portConfig, created);
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001212 }
1213 ALOGW("%s: unsupported audio port config: %s",
1214 __func__, requestedPortConfig.toString().c_str());
1215 return BAD_VALUE;
1216}
1217
1218DeviceHalAidl::Patches::iterator DeviceHalAidl::findPatch(
1219 const std::set<int32_t>& sourcePortConfigIds, const std::set<int32_t>& sinkPortConfigIds) {
1220 return std::find_if(mPatches.begin(), mPatches.end(),
1221 [&](const auto& pair) {
1222 const auto& p = pair.second;
1223 std::set<int32_t> patchSrcs(
1224 p.sourcePortConfigIds.begin(), p.sourcePortConfigIds.end());
1225 std::set<int32_t> patchSinks(
1226 p.sinkPortConfigIds.begin(), p.sinkPortConfigIds.end());
1227 return sourcePortConfigIds == patchSrcs && sinkPortConfigIds == patchSinks; });
1228}
1229
1230DeviceHalAidl::Ports::iterator DeviceHalAidl::findPort(const AudioDevice& device) {
Mikhail Naganov8bd806e2023-01-30 12:33:18 -08001231 if (device.type.type == AudioDeviceType::IN_DEFAULT) {
1232 return mPorts.find(mDefaultInputPortId);
1233 } else if (device.type.type == AudioDeviceType::OUT_DEFAULT) {
1234 return mPorts.find(mDefaultOutputPortId);
1235 }
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001236 return std::find_if(mPorts.begin(), mPorts.end(),
Mikhail Naganov8bd806e2023-01-30 12:33:18 -08001237 [&](const auto& pair) { return audioDeviceMatches(device, pair.second); });
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001238}
1239
1240DeviceHalAidl::Ports::iterator DeviceHalAidl::findPort(
Mikhail Naganovecfafb72023-03-29 10:06:15 -07001241 const AudioConfig& config, const AudioIoFlags& flags,
1242 const std::set<int32_t>& destinationPortIds) {
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -07001243 auto belongsToProfile = [&config](const AudioProfile& prof) {
1244 return (isDefaultAudioFormat(config.base.format) || prof.format == config.base.format) &&
1245 (config.base.channelMask.getTag() == AudioChannelLayout::none ||
1246 std::find(prof.channelMasks.begin(), prof.channelMasks.end(),
1247 config.base.channelMask) != prof.channelMasks.end()) &&
1248 (config.base.sampleRate == 0 ||
1249 std::find(prof.sampleRates.begin(), prof.sampleRates.end(),
1250 config.base.sampleRate) != prof.sampleRates.end());
1251 };
jiabin2248fa12023-04-27 22:04:16 +00001252 static const std::vector<AudioOutputFlags> kOptionalOutputFlags{AudioOutputFlags::BIT_PERFECT};
1253 int optionalFlags = 0;
1254 auto flagMatches = [&flags, &optionalFlags](const AudioIoFlags& portFlags) {
1255 // Ports should be able to match if the optional flags are not requested.
1256 return portFlags == flags ||
1257 (portFlags.getTag() == AudioIoFlags::Tag::output &&
1258 AudioIoFlags::make<AudioIoFlags::Tag::output>(
1259 portFlags.get<AudioIoFlags::Tag::output>() &
1260 ~optionalFlags) == flags);
1261 };
Mikhail Naganov8bd806e2023-01-30 12:33:18 -08001262 auto matcher = [&](const auto& pair) {
1263 const auto& p = pair.second;
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001264 return p.ext.getTag() == AudioPortExt::Tag::mix &&
jiabin2248fa12023-04-27 22:04:16 +00001265 flagMatches(p.flags) &&
Mikhail Naganovecfafb72023-03-29 10:06:15 -07001266 (destinationPortIds.empty() ||
1267 std::any_of(destinationPortIds.begin(), destinationPortIds.end(),
1268 [&](const int32_t destId) { return mRoutingMatrix.count(
1269 std::make_pair(p.id, destId)) != 0; })) &&
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -07001270 (p.profiles.empty() ||
1271 std::find_if(p.profiles.begin(), p.profiles.end(), belongsToProfile) !=
1272 p.profiles.end()); };
jiabin2248fa12023-04-27 22:04:16 +00001273 auto result = std::find_if(mPorts.begin(), mPorts.end(), matcher);
1274 if (result == mPorts.end() && flags.getTag() == AudioIoFlags::Tag::output) {
1275 auto optionalOutputFlagsIt = kOptionalOutputFlags.begin();
1276 while (result == mPorts.end() && optionalOutputFlagsIt != kOptionalOutputFlags.end()) {
1277 if (isBitPositionFlagSet(
1278 flags.get<AudioIoFlags::Tag::output>(), *optionalOutputFlagsIt)) {
1279 // If the flag is set by the request, it must be matched.
1280 ++optionalOutputFlagsIt;
1281 continue;
1282 }
1283 optionalFlags |= makeBitPositionFlagMask(*optionalOutputFlagsIt++);
1284 result = std::find_if(mPorts.begin(), mPorts.end(), matcher);
1285 ALOGI("%s: port for config %s, flags %s was not found in the module %s, "
1286 "retried with excluding optional flags %#x", __func__, config.toString().c_str(),
1287 flags.toString().c_str(), mInstance.c_str(), optionalFlags);
1288 }
1289 }
1290 return result;
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001291}
1292
1293DeviceHalAidl::PortConfigs::iterator DeviceHalAidl::findPortConfig(const AudioDevice& device) {
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001294 return std::find_if(mPortConfigs.begin(), mPortConfigs.end(),
Mikhail Naganov8bd806e2023-01-30 12:33:18 -08001295 [&](const auto& pair) { return audioDeviceMatches(device, pair.second); });
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001296}
1297
1298DeviceHalAidl::PortConfigs::iterator DeviceHalAidl::findPortConfig(
Mikhail Naganov8bd806e2023-01-30 12:33:18 -08001299 const AudioConfig& config, const std::optional<AudioIoFlags>& flags, int32_t ioHandle) {
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001300 using Tag = AudioPortExt::Tag;
1301 return std::find_if(mPortConfigs.begin(), mPortConfigs.end(),
1302 [&](const auto& pair) {
1303 const auto& p = pair.second;
1304 LOG_ALWAYS_FATAL_IF(p.ext.getTag() == Tag::mix &&
1305 !p.sampleRate.has_value() || !p.channelMask.has_value() ||
1306 !p.format.has_value() || !p.flags.has_value(),
1307 "%s: stored mix port config is not fully specified: %s",
1308 __func__, p.toString().c_str());
1309 return p.ext.getTag() == Tag::mix &&
1310 isConfigEqualToPortConfig(config, p) &&
Mikhail Naganov8bd806e2023-01-30 12:33:18 -08001311 (!flags.has_value() || p.flags.value() == flags.value()) &&
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001312 p.ext.template get<Tag::mix>().handle == ioHandle; });
1313}
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -07001314
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001315void DeviceHalAidl::resetPatch(int32_t patchId) {
1316 if (auto it = mPatches.find(patchId); it != mPatches.end()) {
1317 mPatches.erase(it);
1318 TIME_CHECK();
1319 if (ndk::ScopedAStatus status = mModule->resetAudioPatch(patchId); !status.isOk()) {
1320 ALOGE("%s: error while resetting patch %d: %s",
1321 __func__, patchId, status.getDescription().c_str());
1322 }
1323 return;
1324 }
1325 ALOGE("%s: patch id %d not found", __func__, patchId);
1326}
1327
1328void DeviceHalAidl::resetPortConfig(int32_t portConfigId) {
1329 if (auto it = mPortConfigs.find(portConfigId); it != mPortConfigs.end()) {
1330 mPortConfigs.erase(it);
1331 TIME_CHECK();
1332 if (ndk::ScopedAStatus status = mModule->resetAudioPortConfig(portConfigId);
1333 !status.isOk()) {
1334 ALOGE("%s: error while resetting port config %d: %s",
1335 __func__, portConfigId, status.getDescription().c_str());
1336 }
1337 return;
1338 }
1339 ALOGE("%s: port config id %d not found", __func__, portConfigId);
1340}
1341
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -07001342void DeviceHalAidl::resetUnusedPatches() {
1343 // Since patches can be created independently of streams via 'createAudioPatch',
1344 // here we only clean up patches for released streams.
1345 for (auto it = mStreams.begin(); it != mStreams.end(); ) {
1346 if (auto streamSp = it->first.promote(); streamSp) {
1347 ++it;
1348 } else {
1349 resetPatch(it->second);
1350 it = mStreams.erase(it);
1351 }
1352 }
1353}
1354
1355void DeviceHalAidl::resetUnusedPatchesAndPortConfigs() {
1356 resetUnusedPatches();
1357 resetUnusedPortConfigs();
1358}
1359
1360void DeviceHalAidl::resetUnusedPortConfigs() {
1361 // The assumption is that port configs are used to create patches
1362 // (or to open streams, but that involves creation of patches, too). Thus,
1363 // orphaned port configs can and should be reset.
1364 std::set<int32_t> portConfigIds;
1365 std::transform(mPortConfigs.begin(), mPortConfigs.end(),
1366 std::inserter(portConfigIds, portConfigIds.end()),
1367 [](const auto& pcPair) { return pcPair.first; });
1368 for (const auto& p : mPatches) {
1369 for (int32_t id : p.second.sourcePortConfigIds) portConfigIds.erase(id);
1370 for (int32_t id : p.second.sinkPortConfigIds) portConfigIds.erase(id);
1371 }
jiabin2248fa12023-04-27 22:04:16 +00001372 for (int32_t id : mInitialPortConfigIds) {
1373 portConfigIds.erase(id);
1374 }
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -07001375 for (int32_t id : portConfigIds) resetPortConfig(id);
1376}
1377
Mikhail Naganovecfafb72023-03-29 10:06:15 -07001378status_t DeviceHalAidl::updateRoutes() {
1379 TIME_CHECK();
Mikhail Naganovecfafb72023-03-29 10:06:15 -07001380 RETURN_STATUS_IF_ERROR(
Mikhail Naganov2d814892023-04-24 13:06:04 -07001381 statusTFromBinderStatus(mModule->getAudioRoutes(&mRoutes)));
1382 ALOGW_IF(mRoutes.empty(), "%s: module %s returned an empty list of audio routes",
Mikhail Naganovecfafb72023-03-29 10:06:15 -07001383 __func__, mInstance.c_str());
1384 mRoutingMatrix.clear();
Mikhail Naganov2d814892023-04-24 13:06:04 -07001385 for (const auto& r : mRoutes) {
Mikhail Naganovecfafb72023-03-29 10:06:15 -07001386 for (auto portId : r.sourcePortIds) {
1387 mRoutingMatrix.emplace(r.sinkPortId, portId);
1388 mRoutingMatrix.emplace(portId, r.sinkPortId);
1389 }
1390 }
1391 return OK;
1392}
1393
Mikhail Naganovb0c55252023-02-08 16:59:41 -08001394void DeviceHalAidl::clearCallbacks(void* cookie) {
1395 std::lock_guard l(mLock);
1396 mCallbacks.erase(cookie);
1397}
1398
1399sp<StreamOutHalInterfaceCallback> DeviceHalAidl::getStreamOutCallback(void* cookie) {
1400 return getCallbackImpl(cookie, &Callbacks::out);
1401}
1402
1403void DeviceHalAidl::setStreamOutCallback(
1404 void* cookie, const sp<StreamOutHalInterfaceCallback>& cb) {
1405 setCallbackImpl(cookie, &Callbacks::out, cb);
1406}
1407
1408sp<StreamOutHalInterfaceEventCallback> DeviceHalAidl::getStreamOutEventCallback(
1409 void* cookie) {
1410 return getCallbackImpl(cookie, &Callbacks::event);
1411}
1412
1413void DeviceHalAidl::setStreamOutEventCallback(
1414 void* cookie, const sp<StreamOutHalInterfaceEventCallback>& cb) {
1415 setCallbackImpl(cookie, &Callbacks::event, cb);
1416}
1417
1418sp<StreamOutHalInterfaceLatencyModeCallback> DeviceHalAidl::getStreamOutLatencyModeCallback(
1419 void* cookie) {
1420 return getCallbackImpl(cookie, &Callbacks::latency);
1421}
1422
1423void DeviceHalAidl::setStreamOutLatencyModeCallback(
1424 void* cookie, const sp<StreamOutHalInterfaceLatencyModeCallback>& cb) {
1425 setCallbackImpl(cookie, &Callbacks::latency, cb);
1426}
1427
1428template<class C>
1429sp<C> DeviceHalAidl::getCallbackImpl(void* cookie, wp<C> DeviceHalAidl::Callbacks::* field) {
1430 std::lock_guard l(mLock);
1431 if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
1432 return ((it->second).*field).promote();
1433 }
1434 return nullptr;
1435}
1436template<class C>
1437void DeviceHalAidl::setCallbackImpl(
1438 void* cookie, wp<C> DeviceHalAidl::Callbacks::* field, const sp<C>& cb) {
1439 std::lock_guard l(mLock);
1440 if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
1441 (it->second).*field = cb;
1442 }
1443}
1444
Mikhail Naganov31d46652023-01-10 18:29:25 +00001445} // namespace android