blob: 3079d9192cb16dabc471f4b5393a67653209cb5b [file] [log] [blame]
Shunkai Yao51202502022-12-12 06:11:46 +00001/*
2 * Copyright (C) 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "DeviceHalAidl"
Mikhail Naganov89a9f742023-01-30 12:33:18 -080018// #define LOG_NDEBUG 0
Shunkai Yao51202502022-12-12 06:11:46 +000019
Mikhail Naganov5b1eed12023-01-25 11:29:11 -080020#include <algorithm>
21#include <forward_list>
22
Mikhail Naganovdfd594e2023-02-08 16:59:41 -080023#include <aidl/android/hardware/audio/core/BnStreamCallback.h>
24#include <aidl/android/hardware/audio/core/BnStreamOutEventCallback.h>
Mikhail Naganovfab697c2023-01-11 19:33:13 +000025#include <aidl/android/hardware/audio/core/StreamDescriptor.h>
26#include <error/expected_utils.h>
27#include <media/AidlConversionCppNdk.h>
Mikhail Naganov25bc9a22023-04-21 18:48:16 -070028#include <media/AidlConversionNdkCpp.h>
Mikhail Naganovfab697c2023-01-11 19:33:13 +000029#include <media/AidlConversionUtil.h>
Mikhail Naganov31d46652023-01-10 18:29:25 +000030#include <mediautils/TimeCheck.h>
Mikhail Naganov89a9f742023-01-30 12:33:18 -080031#include <Utils.h>
Mikhail Naganov31d46652023-01-10 18:29:25 +000032#include <utils/Log.h>
Shunkai Yao51202502022-12-12 06:11:46 +000033
Mikhail Naganov31d46652023-01-10 18:29:25 +000034#include "DeviceHalAidl.h"
35#include "StreamHalAidl.h"
36
Mikhail Naganovfab697c2023-01-11 19:33:13 +000037using aidl::android::aidl_utils::statusTFromBinderStatus;
Mikhail Naganove93a0862023-03-15 17:06:59 -070038using aidl::android::media::audio::common::AudioChannelLayout;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -080039using aidl::android::media::audio::common::AudioConfig;
40using aidl::android::media::audio::common::AudioDevice;
David Li9cf5e622023-03-21 00:51:10 +080041using aidl::android::media::audio::common::AudioDeviceAddress;
Mikhail Naganov89a9f742023-01-30 12:33:18 -080042using aidl::android::media::audio::common::AudioDeviceType;
Mikhail Naganove93a0862023-03-15 17:06:59 -070043using aidl::android::media::audio::common::AudioFormatType;
Mikhail Naganov89a9f742023-01-30 12:33:18 -080044using aidl::android::media::audio::common::AudioInputFlags;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -080045using aidl::android::media::audio::common::AudioIoFlags;
Mikhail Naganovdfd594e2023-02-08 16:59:41 -080046using aidl::android::media::audio::common::AudioLatencyMode;
David Li9cf5e622023-03-21 00:51:10 +080047using aidl::android::media::audio::common::AudioMMapPolicy;
48using aidl::android::media::audio::common::AudioMMapPolicyInfo;
49using aidl::android::media::audio::common::AudioMMapPolicyType;
Mikhail Naganovfab697c2023-01-11 19:33:13 +000050using aidl::android::media::audio::common::AudioMode;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -080051using aidl::android::media::audio::common::AudioOutputFlags;
52using aidl::android::media::audio::common::AudioPort;
53using aidl::android::media::audio::common::AudioPortConfig;
Mikhail Naganov89a9f742023-01-30 12:33:18 -080054using aidl::android::media::audio::common::AudioPortDeviceExt;
David Li9cf5e622023-03-21 00:51:10 +080055using aidl::android::media::audio::common::AudioPortExt;
Mikhail Naganov1a44bc62023-02-16 17:35:06 -080056using aidl::android::media::audio::common::AudioPortMixExt;
Mikhail Naganovd8d01f72023-03-09 16:24:40 -080057using aidl::android::media::audio::common::AudioPortMixExtUseCase;
Mikhail Naganove93a0862023-03-15 17:06:59 -070058using aidl::android::media::audio::common::AudioProfile;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -080059using aidl::android::media::audio::common::AudioSource;
Mikhail Naganovfab697c2023-01-11 19:33:13 +000060using aidl::android::media::audio::common::Float;
David Li9cf5e622023-03-21 00:51:10 +080061using aidl::android::media::audio::common::Int;
62using aidl::android::media::audio::common::MicrophoneDynamicInfo;
63using aidl::android::media::audio::common::MicrophoneInfo;
Mikhail Naganov6352e822023-03-09 18:22:36 -080064using aidl::android::hardware::audio::common::getFrameSizeInBytes;
65using aidl::android::hardware::audio::common::isBitPositionFlagSet;
Mikhail Naganove93a0862023-03-15 17:06:59 -070066using aidl::android::hardware::audio::common::isDefaultAudioFormat;
Mikhail Naganov6352e822023-03-09 18:22:36 -080067using aidl::android::hardware::audio::common::makeBitPositionFlagMask;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -080068using aidl::android::hardware::audio::common::RecordTrackMetadata;
69using aidl::android::hardware::audio::core::AudioPatch;
Mikhail Naganov289468a2023-03-29 10:06:15 -070070using aidl::android::hardware::audio::core::AudioRoute;
Mikhail Naganovfab697c2023-01-11 19:33:13 +000071using aidl::android::hardware::audio::core::IModule;
72using aidl::android::hardware::audio::core::ITelephony;
Mikhail Naganove93a0862023-03-15 17:06:59 -070073using aidl::android::hardware::audio::core::ModuleDebug;
Mikhail Naganovfab697c2023-01-11 19:33:13 +000074using aidl::android::hardware::audio::core::StreamDescriptor;
Mikhail Naganov31d46652023-01-10 18:29:25 +000075
76namespace android {
77
Mikhail Naganov5b1eed12023-01-25 11:29:11 -080078namespace {
79
80bool isConfigEqualToPortConfig(const AudioConfig& config, const AudioPortConfig& portConfig) {
81 return portConfig.sampleRate.value().value == config.base.sampleRate &&
82 portConfig.channelMask.value() == config.base.channelMask &&
83 portConfig.format.value() == config.base.format;
84}
85
86void setConfigFromPortConfig(AudioConfig* config, const AudioPortConfig& portConfig) {
87 config->base.sampleRate = portConfig.sampleRate.value().value;
88 config->base.channelMask = portConfig.channelMask.value();
89 config->base.format = portConfig.format.value();
90}
91
92void setPortConfigFromConfig(AudioPortConfig* portConfig, const AudioConfig& config) {
93 portConfig->sampleRate = Int{ .value = config.base.sampleRate };
94 portConfig->channelMask = config.base.channelMask;
95 portConfig->format = config.base.format;
96}
97
Mikhail Naganovf83b9742023-04-24 13:06:04 -070098// Note: these converters are for types defined in different AIDL files. Although these
99// AIDL files are copies of each other, however formally these are different types
100// thus we don't use a conversion via a parcelable.
101ConversionResult<media::AudioRoute> ndk2cpp_AudioRoute(const AudioRoute& ndk) {
102 media::AudioRoute cpp;
103 cpp.sourcePortIds.insert(
104 cpp.sourcePortIds.end(), ndk.sourcePortIds.begin(), ndk.sourcePortIds.end());
105 cpp.sinkPortId = ndk.sinkPortId;
106 cpp.isExclusive = ndk.isExclusive;
David Li9cf5e622023-03-21 00:51:10 +0800107 return cpp;
108}
109
Mikhail Naganov1fba38c2023-05-03 17:45:36 -0700110template<typename T>
111std::shared_ptr<T> retrieveSubInterface(const std::shared_ptr<IModule>& module,
112 ::ndk::ScopedAStatus (IModule::*getT)(std::shared_ptr<T>*)) {
113 if (module != nullptr) {
114 std::shared_ptr<T> instance;
115 if (auto status = (module.get()->*getT)(&instance); status.isOk()) {
116 return instance;
117 }
118 }
119 return nullptr;
120}
121
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800122} // namespace
123
Mikhail Naganov1fba38c2023-05-03 17:45:36 -0700124DeviceHalAidl::DeviceHalAidl(const std::string& instance, const std::shared_ptr<IModule>& module)
125 : ConversionHelperAidl("DeviceHalAidl"),
126 mInstance(instance), mModule(module),
127 mTelephony(retrieveSubInterface<ITelephony>(module, &IModule::getTelephony)) {
128}
129
Mikhail Naganovf83b9742023-04-24 13:06:04 -0700130status_t DeviceHalAidl::getAudioPorts(std::vector<media::audio::common::AudioPort> *ports) {
131 auto convertAudioPortFromMap = [](const Ports::value_type& pair) {
132 return ndk2cpp_AudioPort(pair.second);
133 };
134 return ::aidl::android::convertRange(mPorts.begin(), mPorts.end(), ports->begin(),
135 convertAudioPortFromMap);
136}
137
138status_t DeviceHalAidl::getAudioRoutes(std::vector<media::AudioRoute> *routes) {
139 *routes = VALUE_OR_RETURN_STATUS(
140 ::aidl::android::convertContainer<std::vector<media::AudioRoute>>(
141 mRoutes, ndk2cpp_AudioRoute));
142 return OK;
143}
144
Mikhail Naganov1fba38c2023-05-03 17:45:36 -0700145status_t DeviceHalAidl::getSupportedModes(std::vector<media::audio::common::AudioMode> *modes) {
146 TIME_CHECK();
147 if (modes == nullptr) {
148 return BAD_VALUE;
149 }
150 if (mModule == nullptr) return NO_INIT;
151 if (mTelephony == nullptr) return INVALID_OPERATION;
152 std::vector<AudioMode> aidlModes;
153 RETURN_STATUS_IF_ERROR(
154 statusTFromBinderStatus(mTelephony->getSupportedAudioModes(&aidlModes)));
155 *modes = VALUE_OR_RETURN_STATUS(
156 ::aidl::android::convertContainer<std::vector<media::audio::common::AudioMode>>(
157 aidlModes, ndk2cpp_AudioMode));
158 return OK;
159}
160
Mikhail Naganov31d46652023-01-10 18:29:25 +0000161status_t DeviceHalAidl::getSupportedDevices(uint32_t*) {
162 // Obsolete.
163 return INVALID_OPERATION;
Shunkai Yao51202502022-12-12 06:11:46 +0000164}
165
166status_t DeviceHalAidl::initCheck() {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800167 TIME_CHECK();
Mikhail Naganov31d46652023-01-10 18:29:25 +0000168 if (mModule == nullptr) return NO_INIT;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800169 std::vector<AudioPort> ports;
Mikhail Naganovf83b9742023-04-24 13:06:04 -0700170 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->getAudioPorts(&ports)));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800171 ALOGW_IF(ports.empty(), "%s: module %s returned an empty list of audio ports",
172 __func__, mInstance.c_str());
173 std::transform(ports.begin(), ports.end(), std::inserter(mPorts, mPorts.end()),
174 [](const auto& p) { return std::make_pair(p.id, p); });
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800175 mDefaultInputPortId = mDefaultOutputPortId = -1;
176 const int defaultDeviceFlag = 1 << AudioPortDeviceExt::FLAG_INDEX_DEFAULT_DEVICE;
177 for (const auto& pair : mPorts) {
178 const auto& p = pair.second;
179 if (p.ext.getTag() == AudioPortExt::Tag::device &&
180 (p.ext.get<AudioPortExt::Tag::device>().flags & defaultDeviceFlag) != 0) {
181 if (p.flags.getTag() == AudioIoFlags::Tag::input) {
182 mDefaultInputPortId = p.id;
183 } else if (p.flags.getTag() == AudioIoFlags::Tag::output) {
184 mDefaultOutputPortId = p.id;
185 }
186 }
187 }
188 ALOGI("%s: module %s default port ids: input %d, output %d",
189 __func__, mInstance.c_str(), mDefaultInputPortId, mDefaultOutputPortId);
Mikhail Naganov289468a2023-03-29 10:06:15 -0700190 RETURN_STATUS_IF_ERROR(updateRoutes());
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800191 std::vector<AudioPortConfig> portConfigs;
192 RETURN_STATUS_IF_ERROR(
193 statusTFromBinderStatus(mModule->getAudioPortConfigs(&portConfigs))); // OK if empty
194 std::transform(portConfigs.begin(), portConfigs.end(),
195 std::inserter(mPortConfigs, mPortConfigs.end()),
196 [](const auto& p) { return std::make_pair(p.id, p); });
jiabin9c07faf2023-04-26 22:00:44 +0000197 std::transform(mPortConfigs.begin(), mPortConfigs.end(),
198 std::inserter(mInitialPortConfigIds, mInitialPortConfigIds.end()),
199 [](const auto& pcPair) { return pcPair.first; });
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800200 std::vector<AudioPatch> patches;
201 RETURN_STATUS_IF_ERROR(
202 statusTFromBinderStatus(mModule->getAudioPatches(&patches))); // OK if empty
203 std::transform(patches.begin(), patches.end(),
204 std::inserter(mPatches, mPatches.end()),
205 [](const auto& p) { return std::make_pair(p.id, p); });
Shunkai Yao51202502022-12-12 06:11:46 +0000206 return OK;
207}
208
209status_t DeviceHalAidl::setVoiceVolume(float volume) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000210 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000211 if (!mModule) return NO_INIT;
Mikhail Naganov1fba38c2023-05-03 17:45:36 -0700212 if (mTelephony == nullptr) return INVALID_OPERATION;
213 ITelephony::TelecomConfig inConfig{ .voiceVolume = Float{volume} }, outConfig;
214 RETURN_STATUS_IF_ERROR(
215 statusTFromBinderStatus(mTelephony->setTelecomConfig(inConfig, &outConfig)));
216 ALOGW_IF(outConfig.voiceVolume.has_value() && volume != outConfig.voiceVolume.value().value,
217 "%s: the resulting voice volume %f is not the same as requested %f",
218 __func__, outConfig.voiceVolume.value().value, volume);
219 return OK;
Shunkai Yao51202502022-12-12 06:11:46 +0000220}
221
222status_t DeviceHalAidl::setMasterVolume(float volume) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000223 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000224 if (!mModule) return NO_INIT;
225 return statusTFromBinderStatus(mModule->setMasterVolume(volume));
Shunkai Yao51202502022-12-12 06:11:46 +0000226}
227
228status_t DeviceHalAidl::getMasterVolume(float *volume) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000229 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000230 if (!mModule) return NO_INIT;
231 return statusTFromBinderStatus(mModule->getMasterVolume(volume));
Shunkai Yao51202502022-12-12 06:11:46 +0000232}
233
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000234status_t DeviceHalAidl::setMode(audio_mode_t mode) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000235 TIME_CHECK();
236 if (!mModule) return NO_INIT;
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000237 AudioMode audioMode = VALUE_OR_FATAL(::aidl::android::legacy2aidl_audio_mode_t_AudioMode(mode));
Mikhail Naganov1fba38c2023-05-03 17:45:36 -0700238 if (mTelephony != nullptr) {
239 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mTelephony->switchAudioMode(audioMode)));
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000240 }
241 return statusTFromBinderStatus(mModule->updateAudioMode(audioMode));
Shunkai Yao51202502022-12-12 06:11:46 +0000242}
243
244status_t DeviceHalAidl::setMicMute(bool state) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000245 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000246 if (!mModule) return NO_INIT;
247 return statusTFromBinderStatus(mModule->setMicMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000248}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000249
Shunkai Yao51202502022-12-12 06:11:46 +0000250status_t DeviceHalAidl::getMicMute(bool *state) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000251 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000252 if (!mModule) return NO_INIT;
253 return statusTFromBinderStatus(mModule->getMicMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000254}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000255
Shunkai Yao51202502022-12-12 06:11:46 +0000256status_t DeviceHalAidl::setMasterMute(bool state) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000257 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000258 if (!mModule) return NO_INIT;
259 return statusTFromBinderStatus(mModule->setMasterMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000260}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000261
Shunkai Yao51202502022-12-12 06:11:46 +0000262status_t DeviceHalAidl::getMasterMute(bool *state) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000263 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000264 if (!mModule) return NO_INIT;
265 return statusTFromBinderStatus(mModule->getMasterMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000266}
267
Mikhail Naganov31d46652023-01-10 18:29:25 +0000268status_t DeviceHalAidl::setParameters(const String8& kvPairs __unused) {
269 TIME_CHECK();
270 if (!mModule) return NO_INIT;
271 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000272 return OK;
273}
274
Mikhail Naganov31d46652023-01-10 18:29:25 +0000275status_t DeviceHalAidl::getParameters(const String8& keys __unused, String8 *values) {
276 TIME_CHECK();
277 values->clear();
278 if (!mModule) return NO_INIT;
279 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000280 return OK;
281}
282
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800283namespace {
284
285class Cleanup {
286 public:
287 typedef void (DeviceHalAidl::*Cleaner)(int32_t);
288
289 Cleanup(DeviceHalAidl* device, Cleaner cleaner, int32_t id) :
290 mDevice(device), mCleaner(cleaner), mId(id) {}
291 ~Cleanup() { clean(); }
292 void clean() {
293 if (mDevice != nullptr) (mDevice->*mCleaner)(mId);
294 disarm();
295 }
296 void disarm() { mDevice = nullptr; }
297
298 private:
299 DeviceHalAidl* mDevice;
300 const Cleaner mCleaner;
301 const int32_t mId;
302};
303
304} // namespace
305
306// Since the order of container elements destruction is unspecified,
307// ensure that cleanups are performed from the most recent one and upwards.
308// This is the same as if there were individual Cleanup instances on the stack,
309// however the bonus is that we can disarm all of them with just one statement.
310class DeviceHalAidl::Cleanups : public std::forward_list<Cleanup> {
311 public:
312 ~Cleanups() { for (auto& c : *this) c.clean(); }
313 void disarmAll() { for (auto& c : *this) c.disarm(); }
314};
315
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800316status_t DeviceHalAidl::getInputBufferSize(const struct audio_config* config, size_t* size) {
317 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
318 if (size == nullptr) return BAD_VALUE;
319 TIME_CHECK();
320 if (!mModule) return NO_INIT;
321 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
322 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, true /*isInput*/));
323 AudioDevice aidlDevice;
324 aidlDevice.type.type = AudioDeviceType::IN_DEFAULT;
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800325 AudioSource aidlSource = AudioSource::DEFAULT;
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800326 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::input>(0);
327 AudioPortConfig mixPortConfig;
328 Cleanups cleanups;
329 audio_config writableConfig = *config;
Mikhail Naganove93a0862023-03-15 17:06:59 -0700330 AudioPatch aidlPatch;
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800331 RETURN_STATUS_IF_ERROR(prepareToOpenStream(0 /*handle*/, aidlDevice, aidlFlags, aidlSource,
Mikhail Naganove93a0862023-03-15 17:06:59 -0700332 &writableConfig, &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800333 *size = aidlConfig.frameCount *
334 getFrameSizeInBytes(aidlConfig.base.format, aidlConfig.base.channelMask);
335 // Do not disarm cleanups to release temporary port configs.
336 return OK;
337}
338
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800339status_t DeviceHalAidl::prepareToOpenStream(
340 int32_t aidlHandle, const AudioDevice& aidlDevice, const AudioIoFlags& aidlFlags,
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800341 AudioSource aidlSource, struct audio_config* config,
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800342 Cleanups* cleanups, AudioConfig* aidlConfig, AudioPortConfig* mixPortConfig,
Mikhail Naganove93a0862023-03-15 17:06:59 -0700343 AudioPatch* aidlPatch) {
344 ALOGD("%p %s::%s: handle %d, device %s, flags %s, source %s, config %s, mix port config %s",
345 this, getClassName().c_str(), __func__, aidlHandle, aidlDevice.toString().c_str(),
346 aidlFlags.toString().c_str(), toString(aidlSource).c_str(),
347 aidlConfig->toString().c_str(), mixPortConfig->toString().c_str());
jiabin9c07faf2023-04-26 22:00:44 +0000348 resetUnusedPatchesAndPortConfigs();
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800349 const bool isInput = aidlFlags.getTag() == AudioIoFlags::Tag::input;
350 // Find / create AudioPortConfigs for the device port and the mix port,
351 // then find / create a patch between them, and open a stream on the mix port.
352 AudioPortConfig devicePortConfig;
353 bool created = false;
jiabin9c07faf2023-04-26 22:00:44 +0000354 RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(aidlDevice, aidlConfig,
355 &devicePortConfig, &created));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800356 if (created) {
357 cleanups->emplace_front(this, &DeviceHalAidl::resetPortConfig, devicePortConfig.id);
358 }
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800359 RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(*aidlConfig, aidlFlags, aidlHandle, aidlSource,
Mikhail Naganov289468a2023-03-29 10:06:15 -0700360 std::set<int32_t>{devicePortConfig.portId}, mixPortConfig, &created));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800361 if (created) {
362 cleanups->emplace_front(this, &DeviceHalAidl::resetPortConfig, mixPortConfig->id);
363 }
364 setConfigFromPortConfig(aidlConfig, *mixPortConfig);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800365 if (isInput) {
366 RETURN_STATUS_IF_ERROR(findOrCreatePatch(
Mikhail Naganove93a0862023-03-15 17:06:59 -0700367 {devicePortConfig.id}, {mixPortConfig->id}, aidlPatch, &created));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800368 } else {
369 RETURN_STATUS_IF_ERROR(findOrCreatePatch(
Mikhail Naganove93a0862023-03-15 17:06:59 -0700370 {mixPortConfig->id}, {devicePortConfig.id}, aidlPatch, &created));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800371 }
372 if (created) {
Mikhail Naganove93a0862023-03-15 17:06:59 -0700373 cleanups->emplace_front(this, &DeviceHalAidl::resetPatch, aidlPatch->id);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800374 }
375 if (aidlConfig->frameCount <= 0) {
Mikhail Naganove93a0862023-03-15 17:06:59 -0700376 aidlConfig->frameCount = aidlPatch->minimumStreamBufferSizeFrames;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800377 }
378 *config = VALUE_OR_RETURN_STATUS(
379 ::aidl::android::aidl2legacy_AudioConfig_audio_config_t(*aidlConfig, isInput));
380 return OK;
381}
382
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800383namespace {
384
385class StreamCallbackBase {
386 protected:
387 explicit StreamCallbackBase(const sp<CallbackBroker>& broker) : mBroker(broker) {}
388 public:
389 void* getCookie() const { return mCookie; }
390 void setCookie(void* cookie) { mCookie = cookie; }
391 sp<CallbackBroker> getBroker() const {
392 if (void* cookie = mCookie; cookie != nullptr) return mBroker.promote();
393 return nullptr;
394 }
395 private:
396 const wp<CallbackBroker> mBroker;
397 std::atomic<void*> mCookie;
398};
399
400template<class C>
401class StreamCallbackBaseHelper {
402 protected:
403 explicit StreamCallbackBaseHelper(const StreamCallbackBase& base) : mBase(base) {}
404 sp<C> getCb(const sp<CallbackBroker>& broker, void* cookie);
405 using CbRef = const sp<C>&;
406 ndk::ScopedAStatus runCb(const std::function<void(CbRef cb)>& f) {
407 if (auto cb = getCb(mBase.getBroker(), mBase.getCookie()); cb != nullptr) f(cb);
408 return ndk::ScopedAStatus::ok();
409 }
410 private:
411 const StreamCallbackBase& mBase;
412};
413
414template<>
415sp<StreamOutHalInterfaceCallback> StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>::getCb(
416 const sp<CallbackBroker>& broker, void* cookie) {
417 if (broker != nullptr) return broker->getStreamOutCallback(cookie);
418 return nullptr;
419}
420
421template<>
422sp<StreamOutHalInterfaceEventCallback>
423StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>::getCb(
424 const sp<CallbackBroker>& broker, void* cookie) {
425 if (broker != nullptr) return broker->getStreamOutEventCallback(cookie);
426 return nullptr;
427}
428
429template<>
430sp<StreamOutHalInterfaceLatencyModeCallback>
431StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>::getCb(
432 const sp<CallbackBroker>& broker, void* cookie) {
433 if (broker != nullptr) return broker->getStreamOutLatencyModeCallback(cookie);
434 return nullptr;
435}
436
437/*
438Note on the callback ownership.
439
440In the Binder ownership model, the server implementation is kept alive
441as long as there is any client (proxy object) alive. This is done by
442incrementing the refcount of the server-side object by the Binder framework.
443When it detects that the last client is gone, it decrements the refcount back.
444
445Thus, it is not needed to keep any references to StreamCallback on our
446side (after we have sent an instance to the client), because we are
447the server-side. The callback object will be kept alive as long as the HAL server
448holds a strong ref to IStreamCallback proxy.
449*/
450
451class OutputStreamCallbackAidl : public StreamCallbackBase,
452 public StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>,
453 public ::aidl::android::hardware::audio::core::BnStreamCallback {
454 public:
455 explicit OutputStreamCallbackAidl(const sp<CallbackBroker>& broker)
456 : StreamCallbackBase(broker),
457 StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>(
458 *static_cast<StreamCallbackBase*>(this)) {}
459 ndk::ScopedAStatus onTransferReady() override {
460 return runCb([](CbRef cb) { cb->onWriteReady(); });
461 }
462 ndk::ScopedAStatus onError() override {
463 return runCb([](CbRef cb) { cb->onError(); });
464 }
465 ndk::ScopedAStatus onDrainReady() override {
466 return runCb([](CbRef cb) { cb->onDrainReady(); });
467 }
468};
469
470class OutputStreamEventCallbackAidl :
471 public StreamCallbackBase,
472 public StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>,
473 public StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>,
474 public ::aidl::android::hardware::audio::core::BnStreamOutEventCallback {
475 public:
476 explicit OutputStreamEventCallbackAidl(const sp<CallbackBroker>& broker)
477 : StreamCallbackBase(broker),
478 StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>(
479 *static_cast<StreamCallbackBase*>(this)),
480 StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>(
481 *static_cast<StreamCallbackBase*>(this)) {}
482 ndk::ScopedAStatus onCodecFormatChanged(const std::vector<uint8_t>& in_audioMetadata) override {
483 std::basic_string<uint8_t> halMetadata(in_audioMetadata.begin(), in_audioMetadata.end());
484 return StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>::runCb(
485 [&halMetadata](auto cb) { cb->onCodecFormatChanged(halMetadata); });
486 }
487 ndk::ScopedAStatus onRecommendedLatencyModeChanged(
488 const std::vector<AudioLatencyMode>& in_modes) override {
489 auto halModes = VALUE_OR_FATAL(
490 ::aidl::android::convertContainer<std::vector<audio_latency_mode_t>>(
491 in_modes,
492 ::aidl::android::aidl2legacy_AudioLatencyMode_audio_latency_mode_t));
493 return StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>::runCb(
494 [&halModes](auto cb) { cb->onRecommendedLatencyModeChanged(halModes); });
495 }
496};
497
498} // namespace
499
Mikhail Naganov31d46652023-01-10 18:29:25 +0000500status_t DeviceHalAidl::openOutputStream(
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800501 audio_io_handle_t handle, audio_devices_t devices,
502 audio_output_flags_t flags, struct audio_config* config,
503 const char* address,
Mikhail Naganov31d46652023-01-10 18:29:25 +0000504 sp<StreamOutHalInterface>* outStream) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800505 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000506 if (!outStream || !config) {
507 return BAD_VALUE;
508 }
509 TIME_CHECK();
510 if (!mModule) return NO_INIT;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800511 int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
512 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(handle));
513 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
514 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, false /*isInput*/));
515 AudioDevice aidlDevice = VALUE_OR_RETURN_STATUS(
516 ::aidl::android::legacy2aidl_audio_device_AudioDevice(devices, address));
517 int32_t aidlOutputFlags = VALUE_OR_RETURN_STATUS(
518 ::aidl::android::legacy2aidl_audio_output_flags_t_int32_t_mask(flags));
519 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::output>(aidlOutputFlags);
520 AudioPortConfig mixPortConfig;
521 Cleanups cleanups;
Mikhail Naganove93a0862023-03-15 17:06:59 -0700522 AudioPatch aidlPatch;
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800523 RETURN_STATUS_IF_ERROR(prepareToOpenStream(aidlHandle, aidlDevice, aidlFlags,
524 AudioSource::SYS_RESERVED_INVALID /*only needed for input*/,
Mikhail Naganove93a0862023-03-15 17:06:59 -0700525 config, &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800526 ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamArguments args;
527 args.portConfigId = mixPortConfig.id;
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800528 const bool isOffload = isBitPositionFlagSet(
529 aidlOutputFlags, AudioOutputFlags::COMPRESS_OFFLOAD);
530 std::shared_ptr<OutputStreamCallbackAidl> streamCb;
531 if (isOffload) {
532 streamCb = ndk::SharedRefBase::make<OutputStreamCallbackAidl>(this);
533 }
534 auto eventCb = ndk::SharedRefBase::make<OutputStreamEventCallbackAidl>(this);
535 if (isOffload) {
536 args.offloadInfo = aidlConfig.offloadInfo;
537 args.callback = streamCb;
538 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800539 args.bufferSizeFrames = aidlConfig.frameCount;
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800540 args.eventCallback = eventCb;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800541 ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamReturn ret;
542 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openOutputStream(args, &ret)));
Mikhail Naganov712d71b2023-02-23 17:57:16 -0800543 StreamContextAidl context(ret.desc, isOffload);
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800544 if (!context.isValid()) {
545 ALOGE("%s: Failed to created a valid stream context from the descriptor: %s",
546 __func__, ret.desc.toString().c_str());
547 return NO_INIT;
548 }
Mikhail Naganove93a0862023-03-15 17:06:59 -0700549 *outStream = sp<StreamOutHalAidl>::make(*config, std::move(context), aidlPatch.latenciesMs[0],
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800550 std::move(ret.stream), this /*callbackBroker*/);
Mikhail Naganove93a0862023-03-15 17:06:59 -0700551 mStreams.insert(std::pair(*outStream, aidlPatch.id));
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800552 void* cbCookie = (*outStream).get();
553 {
554 std::lock_guard l(mLock);
555 mCallbacks.emplace(cbCookie, Callbacks{});
556 }
557 if (streamCb) streamCb->setCookie(cbCookie);
558 eventCb->setCookie(cbCookie);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800559 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000560 return OK;
561}
562
Mikhail Naganov31d46652023-01-10 18:29:25 +0000563status_t DeviceHalAidl::openInputStream(
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800564 audio_io_handle_t handle, audio_devices_t devices,
565 struct audio_config* config, audio_input_flags_t flags,
566 const char* address, audio_source_t source,
567 audio_devices_t outputDevice, const char* outputDeviceAddress,
Mikhail Naganov31d46652023-01-10 18:29:25 +0000568 sp<StreamInHalInterface>* inStream) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800569 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000570 if (!inStream || !config) {
571 return BAD_VALUE;
572 }
573 TIME_CHECK();
574 if (!mModule) return NO_INIT;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800575 int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
576 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(handle));
577 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
578 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, true /*isInput*/));
579 AudioDevice aidlDevice = VALUE_OR_RETURN_STATUS(
580 ::aidl::android::legacy2aidl_audio_device_AudioDevice(devices, address));
581 int32_t aidlInputFlags = VALUE_OR_RETURN_STATUS(
582 ::aidl::android::legacy2aidl_audio_input_flags_t_int32_t_mask(flags));
583 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::input>(aidlInputFlags);
584 AudioSource aidlSource = VALUE_OR_RETURN_STATUS(
585 ::aidl::android::legacy2aidl_audio_source_t_AudioSource(source));
586 AudioPortConfig mixPortConfig;
587 Cleanups cleanups;
Mikhail Naganove93a0862023-03-15 17:06:59 -0700588 AudioPatch aidlPatch;
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800589 RETURN_STATUS_IF_ERROR(prepareToOpenStream(aidlHandle, aidlDevice, aidlFlags, aidlSource,
Mikhail Naganove93a0862023-03-15 17:06:59 -0700590 config, &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800591 ::aidl::android::hardware::audio::core::IModule::OpenInputStreamArguments args;
592 args.portConfigId = mixPortConfig.id;
593 RecordTrackMetadata aidlTrackMetadata{
594 .source = aidlSource, .gain = 1, .channelMask = aidlConfig.base.channelMask };
595 if (outputDevice != AUDIO_DEVICE_NONE) {
596 aidlTrackMetadata.destinationDevice = VALUE_OR_RETURN_STATUS(
597 ::aidl::android::legacy2aidl_audio_device_AudioDevice(
598 outputDevice, outputDeviceAddress));
599 }
600 args.sinkMetadata.tracks.push_back(std::move(aidlTrackMetadata));
601 args.bufferSizeFrames = aidlConfig.frameCount;
602 ::aidl::android::hardware::audio::core::IModule::OpenInputStreamReturn ret;
603 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openInputStream(args, &ret)));
Mikhail Naganov712d71b2023-02-23 17:57:16 -0800604 StreamContextAidl context(ret.desc, false /*isAsynchronous*/);
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800605 if (!context.isValid()) {
606 ALOGE("%s: Failed to created a valid stream context from the descriptor: %s",
607 __func__, ret.desc.toString().c_str());
608 return NO_INIT;
609 }
Mikhail Naganove93a0862023-03-15 17:06:59 -0700610 *inStream = sp<StreamInHalAidl>::make(*config, std::move(context), aidlPatch.latenciesMs[0],
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800611 std::move(ret.stream), this /*micInfoProvider*/);
Mikhail Naganove93a0862023-03-15 17:06:59 -0700612 mStreams.insert(std::pair(*inStream, aidlPatch.id));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800613 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000614 return OK;
615}
616
617status_t DeviceHalAidl::supportsAudioPatches(bool* supportsPatches) {
618 *supportsPatches = true;
619 return OK;
620}
621
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800622status_t DeviceHalAidl::createAudioPatch(unsigned int num_sources,
623 const struct audio_port_config* sources,
624 unsigned int num_sinks,
625 const struct audio_port_config* sinks,
626 audio_patch_handle_t* patch) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800627 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000628 TIME_CHECK();
629 if (!mModule) return NO_INIT;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800630 if (num_sinks > AUDIO_PATCH_PORTS_MAX || num_sources > AUDIO_PATCH_PORTS_MAX ||
631 sources == nullptr || sinks == nullptr || patch == nullptr) {
632 return BAD_VALUE;
633 }
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800634 // When the patch handle (*patch) is AUDIO_PATCH_HANDLE_NONE, it means
635 // the framework wants to create a new patch. The handle has to be generated
636 // by the HAL. Since handles generated this way can only be unique within
637 // a HAL module, the framework generates a globally unique handle, and maps
638 // it on the <HAL module, patch handle> pair.
639 // When the patch handle is set, it meant the framework intends to update
640 // an existing patch.
641 //
642 // This behavior corresponds to HAL module behavior, with the only difference
643 // that the HAL module uses `int32_t` for patch IDs. The following assert ensures
644 // that both the framework and the HAL use the same value for "no ID":
645 static_assert(AUDIO_PATCH_HANDLE_NONE == 0);
646 int32_t halPatchId = static_cast<int32_t>(*patch);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800647
648 // Upon conversion, mix port configs contain audio configuration, while
649 // device port configs contain device address. This data is used to find
650 // or create HAL configs.
651 std::vector<AudioPortConfig> aidlSources, aidlSinks;
652 for (unsigned int i = 0; i < num_sources; ++i) {
653 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
654 sources[i].role, sources[i].type)) ==
655 ::aidl::android::AudioPortDirection::INPUT;
656 aidlSources.push_back(VALUE_OR_RETURN_STATUS(
657 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
658 sources[i], isInput, 0)));
659 }
660 for (unsigned int i = 0; i < num_sinks; ++i) {
661 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
662 sinks[i].role, sinks[i].type)) ==
663 ::aidl::android::AudioPortDirection::INPUT;
664 aidlSinks.push_back(VALUE_OR_RETURN_STATUS(
665 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
666 sinks[i], isInput, 0)));
667 }
668 Cleanups cleanups;
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800669 auto existingPatchIt = halPatchId != 0 ? mPatches.find(halPatchId): mPatches.end();
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800670 AudioPatch aidlPatch;
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800671 if (existingPatchIt != mPatches.end()) {
672 aidlPatch = existingPatchIt->second;
673 aidlPatch.sourcePortConfigIds.clear();
674 aidlPatch.sinkPortConfigIds.clear();
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800675 }
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800676 ALOGD("%s: sources: %s, sinks: %s",
677 __func__, ::android::internal::ToString(aidlSources).c_str(),
678 ::android::internal::ToString(aidlSinks).c_str());
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800679 auto fillPortConfigs = [&](
Mikhail Naganov289468a2023-03-29 10:06:15 -0700680 const std::vector<AudioPortConfig>& configs,
681 const std::set<int32_t>& destinationPortIds,
682 std::vector<int32_t>* ids, std::set<int32_t>* portIds) -> status_t {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800683 for (const auto& s : configs) {
684 AudioPortConfig portConfig;
685 bool created = false;
Mikhail Naganov289468a2023-03-29 10:06:15 -0700686 RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(
687 s, destinationPortIds, &portConfig, &created));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800688 if (created) {
689 cleanups.emplace_front(this, &DeviceHalAidl::resetPortConfig, portConfig.id);
690 }
691 ids->push_back(portConfig.id);
Mikhail Naganov289468a2023-03-29 10:06:15 -0700692 if (portIds != nullptr) {
693 portIds->insert(portConfig.portId);
694 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800695 }
696 return OK;
697 };
Mikhail Naganov289468a2023-03-29 10:06:15 -0700698 // When looking up port configs, the destinationPortId is only used for mix ports.
699 // Thus, we process device port configs first, and look up the destination port ID from them.
700 bool sourceIsDevice = std::any_of(aidlSources.begin(), aidlSources.end(),
701 [](const auto& config) { return config.ext.getTag() == AudioPortExt::device; });
702 const std::vector<AudioPortConfig>& devicePortConfigs =
703 sourceIsDevice ? aidlSources : aidlSinks;
704 std::vector<int32_t>* devicePortConfigIds =
705 sourceIsDevice ? &aidlPatch.sourcePortConfigIds : &aidlPatch.sinkPortConfigIds;
706 const std::vector<AudioPortConfig>& mixPortConfigs =
707 sourceIsDevice ? aidlSinks : aidlSources;
708 std::vector<int32_t>* mixPortConfigIds =
709 sourceIsDevice ? &aidlPatch.sinkPortConfigIds : &aidlPatch.sourcePortConfigIds;
710 std::set<int32_t> devicePortIds;
711 RETURN_STATUS_IF_ERROR(fillPortConfigs(
712 devicePortConfigs, std::set<int32_t>(), devicePortConfigIds, &devicePortIds));
713 RETURN_STATUS_IF_ERROR(fillPortConfigs(
714 mixPortConfigs, devicePortIds, mixPortConfigIds, nullptr));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800715 if (existingPatchIt != mPatches.end()) {
716 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
717 mModule->setAudioPatch(aidlPatch, &aidlPatch)));
718 existingPatchIt->second = aidlPatch;
719 } else {
720 bool created = false;
721 RETURN_STATUS_IF_ERROR(findOrCreatePatch(aidlPatch, &aidlPatch, &created));
722 // Since no cleanup of the patch is needed, 'created' is ignored.
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800723 halPatchId = aidlPatch.id;
724 *patch = static_cast<audio_patch_handle_t>(halPatchId);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800725 }
726 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000727 return OK;
728}
729
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800730status_t DeviceHalAidl::releaseAudioPatch(audio_patch_handle_t patch) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800731 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000732 TIME_CHECK();
733 if (!mModule) return NO_INIT;
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800734 static_assert(AUDIO_PATCH_HANDLE_NONE == 0);
735 if (patch == AUDIO_PATCH_HANDLE_NONE) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800736 return BAD_VALUE;
737 }
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800738 int32_t halPatchId = static_cast<int32_t>(patch);
739 auto patchIt = mPatches.find(halPatchId);
740 if (patchIt == mPatches.end()) {
741 ALOGE("%s: patch with id %d not found", __func__, halPatchId);
742 return BAD_VALUE;
743 }
744 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->resetAudioPatch(halPatchId)));
745 mPatches.erase(patchIt);
Shunkai Yao51202502022-12-12 06:11:46 +0000746 return OK;
747}
748
Mikhail Naganove93a0862023-03-15 17:06:59 -0700749status_t DeviceHalAidl::getAudioPort(struct audio_port* port) {
750 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000751 TIME_CHECK();
752 if (!mModule) return NO_INIT;
Mikhail Naganove93a0862023-03-15 17:06:59 -0700753 if (port == nullptr) {
754 return BAD_VALUE;
755 }
756 audio_port_v7 portV7;
757 audio_populate_audio_port_v7(port, &portV7);
758 RETURN_STATUS_IF_ERROR(getAudioPort(&portV7));
759 return audio_populate_audio_port(&portV7, port) ? OK : BAD_VALUE;
760}
761
762status_t DeviceHalAidl::getAudioPort(struct audio_port_v7 *port) {
763 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
764 TIME_CHECK();
765 if (!mModule) return NO_INIT;
766 if (port == nullptr) {
767 return BAD_VALUE;
768 }
769 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(port->role, port->type)) ==
770 ::aidl::android::AudioPortDirection::INPUT;
771 auto aidlPort = VALUE_OR_RETURN_STATUS(
772 ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
773 if (aidlPort.ext.getTag() != AudioPortExt::device) {
774 ALOGE("%s: provided port is not a device port (module %s): %s",
775 __func__, mInstance.c_str(), aidlPort.toString().c_str());
776 return BAD_VALUE;
777 }
778 const auto& matchDevice = aidlPort.ext.get<AudioPortExt::device>().device;
779 // It seems that we don't have to call HAL since all valid ports have been added either
780 // during initialization, or while handling connection of an external device.
781 auto portsIt = findPort(matchDevice);
782 if (portsIt == mPorts.end()) {
783 ALOGE("%s: device port for device %s is not found in the module %s",
784 __func__, matchDevice.toString().c_str(), mInstance.c_str());
785 return BAD_VALUE;
786 }
787 const int32_t fwkId = aidlPort.id;
788 aidlPort = portsIt->second;
789 aidlPort.id = fwkId;
790 *port = VALUE_OR_RETURN_STATUS(::aidl::android::aidl2legacy_AudioPort_audio_port_v7(
791 aidlPort, isInput));
792 return OK;
793}
794
795status_t DeviceHalAidl::setAudioPortConfig(const struct audio_port_config* config) {
796 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
797 TIME_CHECK();
798 if (!mModule) return NO_INIT;
799 if (config == nullptr) {
800 return BAD_VALUE;
801 }
802 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
803 config->role, config->type)) == ::aidl::android::AudioPortDirection::INPUT;
804 AudioPortConfig requestedPortConfig = VALUE_OR_RETURN_STATUS(
805 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
806 *config, isInput, 0 /*portId*/));
807 AudioPortConfig portConfig;
808 bool created = false;
Mikhail Naganov289468a2023-03-29 10:06:15 -0700809 RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(
810 requestedPortConfig, std::set<int32_t>(), &portConfig, &created));
Shunkai Yao51202502022-12-12 06:11:46 +0000811 return OK;
812}
813
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800814MicrophoneInfoProvider::Info const* DeviceHalAidl::getMicrophoneInfo() {
815 if (mMicrophones.status == Microphones::Status::UNKNOWN) {
816 TIME_CHECK();
817 std::vector<MicrophoneInfo> aidlInfo;
818 status_t status = statusTFromBinderStatus(mModule->getMicrophones(&aidlInfo));
819 if (status == OK) {
820 mMicrophones.status = Microphones::Status::QUERIED;
821 mMicrophones.info = std::move(aidlInfo);
822 } else if (status == INVALID_OPERATION) {
823 mMicrophones.status = Microphones::Status::NOT_SUPPORTED;
824 } else {
825 ALOGE("%s: Unexpected status from 'IModule.getMicrophones': %d", __func__, status);
826 return {};
827 }
828 }
829 if (mMicrophones.status == Microphones::Status::QUERIED) {
830 return &mMicrophones.info;
831 }
832 return {}; // NOT_SUPPORTED
833}
834
Shunkai Yao51202502022-12-12 06:11:46 +0000835status_t DeviceHalAidl::getMicrophones(
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800836 std::vector<audio_microphone_characteristic_t>* microphones) {
837 if (!microphones) {
838 return BAD_VALUE;
839 }
Mikhail Naganov31d46652023-01-10 18:29:25 +0000840 TIME_CHECK();
841 if (!mModule) return NO_INIT;
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800842 auto staticInfo = getMicrophoneInfo();
843 if (!staticInfo) return INVALID_OPERATION;
844 std::vector<MicrophoneDynamicInfo> emptyDynamicInfo;
845 emptyDynamicInfo.reserve(staticInfo->size());
846 std::transform(staticInfo->begin(), staticInfo->end(), std::back_inserter(emptyDynamicInfo),
847 [](const auto& info) { return MicrophoneDynamicInfo{ .id = info.id }; });
848 *microphones = VALUE_OR_RETURN_STATUS(
849 ::aidl::android::convertContainers<std::vector<audio_microphone_characteristic_t>>(
850 *staticInfo, emptyDynamicInfo,
851 ::aidl::android::aidl2legacy_MicrophoneInfos_audio_microphone_characteristic_t)
852 );
Shunkai Yao51202502022-12-12 06:11:46 +0000853 return OK;
854}
855
Mikhail Naganov31d46652023-01-10 18:29:25 +0000856status_t DeviceHalAidl::addDeviceEffect(audio_port_handle_t device __unused,
857 sp<EffectHalInterface> effect) {
Shunkai Yao51202502022-12-12 06:11:46 +0000858 if (!effect) {
859 return BAD_VALUE;
860 }
Mikhail Naganov31d46652023-01-10 18:29:25 +0000861 TIME_CHECK();
862 if (!mModule) return NO_INIT;
863 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000864 return OK;
865}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000866status_t DeviceHalAidl::removeDeviceEffect(audio_port_handle_t device __unused,
Shunkai Yao51202502022-12-12 06:11:46 +0000867 sp<EffectHalInterface> effect) {
868 if (!effect) {
869 return BAD_VALUE;
870 }
Mikhail Naganov31d46652023-01-10 18:29:25 +0000871 TIME_CHECK();
872 if (!mModule) return NO_INIT;
873 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000874 return OK;
875}
876
877status_t DeviceHalAidl::getMmapPolicyInfos(
David Li9cf5e622023-03-21 00:51:10 +0800878 media::audio::common::AudioMMapPolicyType policyType,
879 std::vector<media::audio::common::AudioMMapPolicyInfo>* policyInfos) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000880 TIME_CHECK();
Mikhail Naganov25bc9a22023-04-21 18:48:16 -0700881 AudioMMapPolicyType mmapPolicyType = VALUE_OR_RETURN_STATUS(
882 cpp2ndk_AudioMMapPolicyType(policyType));
David Li9cf5e622023-03-21 00:51:10 +0800883
884 std::vector<AudioMMapPolicyInfo> mmapPolicyInfos;
885
886 if (status_t status = statusTFromBinderStatus(
887 mModule->getMmapPolicyInfos(mmapPolicyType, &mmapPolicyInfos)); status != OK) {
888 return status;
889 }
890
891 *policyInfos = VALUE_OR_RETURN_STATUS(
892 convertContainer<std::vector<media::audio::common::AudioMMapPolicyInfo>>(
893 mmapPolicyInfos, ndk2cpp_AudioMMapPolicyInfo));
Shunkai Yao51202502022-12-12 06:11:46 +0000894 return OK;
895}
896
897int32_t DeviceHalAidl::getAAudioMixerBurstCount() {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000898 TIME_CHECK();
David Li9cf5e622023-03-21 00:51:10 +0800899 int32_t mixerBurstCount = 0;
900 if (mModule->getAAudioMixerBurstCount(&mixerBurstCount).isOk()) {
901 return mixerBurstCount;
902 }
903 return 0;
Shunkai Yao51202502022-12-12 06:11:46 +0000904}
905
906int32_t DeviceHalAidl::getAAudioHardwareBurstMinUsec() {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000907 TIME_CHECK();
David Li9cf5e622023-03-21 00:51:10 +0800908 int32_t hardwareBurstMinUsec = 0;
909 if (mModule->getAAudioHardwareBurstMinUsec(&hardwareBurstMinUsec).isOk()) {
910 return hardwareBurstMinUsec;
911 }
912 return 0;
Shunkai Yao51202502022-12-12 06:11:46 +0000913}
914
915error::Result<audio_hw_sync_t> DeviceHalAidl::getHwAvSync() {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000916 TIME_CHECK();
Mikhail Naganov08a62ab2023-03-14 17:11:51 -0700917 if (!mModule) return NO_INIT;
918 int32_t aidlHwAvSync;
919 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->generateHwAvSyncId(&aidlHwAvSync)));
920 return VALUE_OR_RETURN_STATUS(
921 ::aidl::android::aidl2legacy_int32_t_audio_hw_sync_t(aidlHwAvSync));
Shunkai Yao51202502022-12-12 06:11:46 +0000922}
923
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000924status_t DeviceHalAidl::dump(int fd, const Vector<String16>& args) {
925 TIME_CHECK();
926 if (!mModule) return NO_INIT;
927 return mModule->dump(fd, Args(args).args(), args.size());
David Li9cf5e622023-03-21 00:51:10 +0800928}
Shunkai Yao51202502022-12-12 06:11:46 +0000929
Mikhail Naganov3ac95c92023-04-12 13:14:30 -0700930int32_t DeviceHalAidl::supportsBluetoothVariableLatency(bool* supports) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000931 TIME_CHECK();
Mikhail Naganov3ac95c92023-04-12 13:14:30 -0700932 if (!mModule) return NO_INIT;
933 if (supports == nullptr) {
934 return BAD_VALUE;
935 }
936 return statusTFromBinderStatus(mModule->supportsVariableLatency(supports));
Shunkai Yao51202502022-12-12 06:11:46 +0000937}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000938
jiabin872de702023-04-27 22:04:31 +0000939
940status_t DeviceHalAidl::prepareToDisconnectExternalDevice(const struct audio_port_v7* port) {
941 // There is not AIDL API defined for `prepareToDisconnectExternalDevice`.
942 // Call `setConnectedState` instead.
943 // TODO(b/279824103): call prepareToDisconnectExternalDevice when it is added.
944 const status_t status = setConnectedState(port, false /*connected*/);
945 if (status == NO_ERROR) {
946 mDeviceDisconnectionNotified.insert(port->id);
947 }
948 return status;
949}
950
Mikhail Naganove93a0862023-03-15 17:06:59 -0700951status_t DeviceHalAidl::setConnectedState(const struct audio_port_v7 *port, bool connected) {
952 TIME_CHECK();
953 if (!mModule) return NO_INIT;
954 if (port == nullptr) {
955 return BAD_VALUE;
956 }
jiabin872de702023-04-27 22:04:31 +0000957 if (!connected && mDeviceDisconnectionNotified.erase(port->id) > 0) {
958 // For device disconnection, APM will first call `prepareToDisconnectExternalDevice`
959 // and then call `setConnectedState`. However, there is no API for
960 // `prepareToDisconnectExternalDevice` yet. In that case, `setConnectedState` will be
961 // called when calling `prepareToDisconnectExternalDevice`. Do not call to the HAL if
962 // previous call is successful. Also remove the cache here to avoid a large cache after
963 // a long run.
964 return NO_ERROR;
965 }
Mikhail Naganove93a0862023-03-15 17:06:59 -0700966 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(port->role, port->type)) ==
967 ::aidl::android::AudioPortDirection::INPUT;
968 AudioPort aidlPort = VALUE_OR_RETURN_STATUS(
969 ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
970 if (aidlPort.ext.getTag() != AudioPortExt::device) {
971 ALOGE("%s: provided port is not a device port (module %s): %s",
972 __func__, mInstance.c_str(), aidlPort.toString().c_str());
973 return BAD_VALUE;
974 }
975 if (connected) {
976 AudioDevice matchDevice = aidlPort.ext.get<AudioPortExt::device>().device;
977 // Reset the device address to find the "template" port.
978 matchDevice.address = AudioDeviceAddress::make<AudioDeviceAddress::id>();
979 auto portsIt = findPort(matchDevice);
980 if (portsIt == mPorts.end()) {
981 ALOGW("%s: device port for device %s is not found in the module %s",
982 __func__, matchDevice.toString().c_str(), mInstance.c_str());
983 return BAD_VALUE;
984 }
985 // Use the ID of the "template" port, use all the information from the provided port.
986 aidlPort.id = portsIt->first;
987 AudioPort connectedPort;
988 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->connectExternalDevice(
989 aidlPort, &connectedPort)));
990 const auto [it, inserted] = mPorts.insert(std::make_pair(connectedPort.id, connectedPort));
991 LOG_ALWAYS_FATAL_IF(!inserted,
992 "%s: module %s, duplicate port ID received from HAL: %s, existing port: %s",
993 __func__, mInstance.c_str(), connectedPort.toString().c_str(),
994 it->second.toString().c_str());
995 } else { // !connected
996 AudioDevice matchDevice = aidlPort.ext.get<AudioPortExt::device>().device;
997 auto portsIt = findPort(matchDevice);
998 if (portsIt == mPorts.end()) {
999 ALOGW("%s: device port for device %s is not found in the module %s",
1000 __func__, matchDevice.toString().c_str(), mInstance.c_str());
1001 return BAD_VALUE;
1002 }
1003 // Any streams opened on the external device must be closed by this time,
1004 // thus we can clean up patches and port configs that were created for them.
1005 resetUnusedPatchesAndPortConfigs();
1006 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->disconnectExternalDevice(
1007 portsIt->second.id)));
1008 mPorts.erase(portsIt);
1009 }
Mikhail Naganov289468a2023-03-29 10:06:15 -07001010 return updateRoutes();
Mikhail Naganove93a0862023-03-15 17:06:59 -07001011}
1012
1013status_t DeviceHalAidl::setSimulateDeviceConnections(bool enabled) {
1014 TIME_CHECK();
1015 if (!mModule) return NO_INIT;
1016 ModuleDebug debug{ .simulateDeviceConnections = enabled };
1017 status_t status = statusTFromBinderStatus(mModule->setModuleDebug(debug));
1018 // This is important to log as it affects HAL behavior.
1019 if (status == OK) {
1020 ALOGI("%s: set enabled: %d", __func__, enabled);
1021 } else {
1022 ALOGW("%s: set enabled to %d failed: %d", __func__, enabled, status);
1023 }
1024 return status;
1025}
1026
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001027bool DeviceHalAidl::audioDeviceMatches(const AudioDevice& device, const AudioPort& p) {
1028 if (p.ext.getTag() != AudioPortExt::Tag::device) return false;
1029 return p.ext.get<AudioPortExt::Tag::device>().device == device;
1030}
1031
1032bool DeviceHalAidl::audioDeviceMatches(const AudioDevice& device, const AudioPortConfig& p) {
1033 if (p.ext.getTag() != AudioPortExt::Tag::device) return false;
1034 if (device.type.type == AudioDeviceType::IN_DEFAULT) {
1035 return p.portId == mDefaultInputPortId;
1036 } else if (device.type.type == AudioDeviceType::OUT_DEFAULT) {
1037 return p.portId == mDefaultOutputPortId;
1038 }
1039 return p.ext.get<AudioPortExt::Tag::device>().device == device;
1040}
1041
David Lia8675d42023-03-30 21:08:06 +08001042status_t DeviceHalAidl::createOrUpdatePortConfig(
1043 const AudioPortConfig& requestedPortConfig, PortConfigs::iterator* result, bool* created) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001044 TIME_CHECK();
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001045 AudioPortConfig appliedPortConfig;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001046 bool applied = false;
1047 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPortConfig(
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001048 requestedPortConfig, &appliedPortConfig, &applied)));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001049 if (!applied) {
1050 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPortConfig(
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001051 appliedPortConfig, &appliedPortConfig, &applied)));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001052 if (!applied) {
1053 ALOGE("%s: module %s did not apply suggested config %s",
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001054 __func__, mInstance.c_str(), appliedPortConfig.toString().c_str());
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001055 return NO_INIT;
1056 }
1057 }
David Lia8675d42023-03-30 21:08:06 +08001058
1059 int32_t id = appliedPortConfig.id;
1060 if (requestedPortConfig.id != 0 && requestedPortConfig.id != id) {
1061 LOG_ALWAYS_FATAL("%s: requested port config id %d changed to %d", __func__,
1062 requestedPortConfig.id, id);
1063 }
1064
1065 auto [it, inserted] = mPortConfigs.insert_or_assign(std::move(id),
1066 std::move(appliedPortConfig));
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001067 *result = it;
David Lia8675d42023-03-30 21:08:06 +08001068 *created = inserted;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001069 return OK;
1070}
1071
1072status_t DeviceHalAidl::findOrCreatePatch(
1073 const AudioPatch& requestedPatch, AudioPatch* patch, bool* created) {
1074 std::set<int32_t> sourcePortConfigIds(requestedPatch.sourcePortConfigIds.begin(),
1075 requestedPatch.sourcePortConfigIds.end());
1076 std::set<int32_t> sinkPortConfigIds(requestedPatch.sinkPortConfigIds.begin(),
1077 requestedPatch.sinkPortConfigIds.end());
1078 return findOrCreatePatch(sourcePortConfigIds, sinkPortConfigIds, patch, created);
1079}
1080
1081status_t DeviceHalAidl::findOrCreatePatch(
1082 const std::set<int32_t>& sourcePortConfigIds, const std::set<int32_t>& sinkPortConfigIds,
1083 AudioPatch* patch, bool* created) {
1084 auto patchIt = findPatch(sourcePortConfigIds, sinkPortConfigIds);
1085 if (patchIt == mPatches.end()) {
1086 TIME_CHECK();
1087 AudioPatch requestedPatch, appliedPatch;
1088 requestedPatch.sourcePortConfigIds.insert(requestedPatch.sourcePortConfigIds.end(),
1089 sourcePortConfigIds.begin(), sourcePortConfigIds.end());
1090 requestedPatch.sinkPortConfigIds.insert(requestedPatch.sinkPortConfigIds.end(),
1091 sinkPortConfigIds.begin(), sinkPortConfigIds.end());
1092 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPatch(
1093 requestedPatch, &appliedPatch)));
1094 patchIt = mPatches.insert(mPatches.end(), std::make_pair(appliedPatch.id, appliedPatch));
1095 *created = true;
1096 } else {
1097 *created = false;
1098 }
1099 *patch = patchIt->second;
1100 return OK;
1101}
1102
jiabin9c07faf2023-04-26 22:00:44 +00001103status_t DeviceHalAidl::findOrCreatePortConfig(const AudioDevice& device, const AudioConfig* config,
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001104 AudioPortConfig* portConfig, bool* created) {
1105 auto portConfigIt = findPortConfig(device);
1106 if (portConfigIt == mPortConfigs.end()) {
1107 auto portsIt = findPort(device);
1108 if (portsIt == mPorts.end()) {
1109 ALOGE("%s: device port for device %s is not found in the module %s",
1110 __func__, device.toString().c_str(), mInstance.c_str());
1111 return BAD_VALUE;
1112 }
1113 AudioPortConfig requestedPortConfig;
1114 requestedPortConfig.portId = portsIt->first;
jiabin9c07faf2023-04-26 22:00:44 +00001115 if (config != nullptr) {
1116 setPortConfigFromConfig(&requestedPortConfig, *config);
1117 }
David Lia8675d42023-03-30 21:08:06 +08001118 RETURN_STATUS_IF_ERROR(createOrUpdatePortConfig(requestedPortConfig, &portConfigIt,
1119 created));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001120 } else {
1121 *created = false;
1122 }
1123 *portConfig = portConfigIt->second;
1124 return OK;
1125}
1126
1127status_t DeviceHalAidl::findOrCreatePortConfig(
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001128 const AudioConfig& config, const std::optional<AudioIoFlags>& flags, int32_t ioHandle,
Mikhail Naganov289468a2023-03-29 10:06:15 -07001129 AudioSource source, const std::set<int32_t>& destinationPortIds,
1130 AudioPortConfig* portConfig, bool* created) {
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001131 // These flags get removed one by one in this order when retrying port finding.
1132 static const std::vector<AudioInputFlags> kOptionalInputFlags{
1133 AudioInputFlags::FAST, AudioInputFlags::RAW };
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001134 auto portConfigIt = findPortConfig(config, flags, ioHandle);
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001135 if (portConfigIt == mPortConfigs.end() && flags.has_value()) {
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001136 auto optionalInputFlagsIt = kOptionalInputFlags.begin();
1137 AudioIoFlags matchFlags = flags.value();
Mikhail Naganov289468a2023-03-29 10:06:15 -07001138 auto portsIt = findPort(config, matchFlags, destinationPortIds);
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001139 while (portsIt == mPorts.end() && matchFlags.getTag() == AudioIoFlags::Tag::input
1140 && optionalInputFlagsIt != kOptionalInputFlags.end()) {
1141 if (!isBitPositionFlagSet(
1142 matchFlags.get<AudioIoFlags::Tag::input>(), *optionalInputFlagsIt)) {
1143 ++optionalInputFlagsIt;
1144 continue;
1145 }
1146 matchFlags.set<AudioIoFlags::Tag::input>(matchFlags.get<AudioIoFlags::Tag::input>() &
1147 ~makeBitPositionFlagMask(*optionalInputFlagsIt++));
Mikhail Naganov289468a2023-03-29 10:06:15 -07001148 portsIt = findPort(config, matchFlags, destinationPortIds);
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001149 ALOGI("%s: mix port for config %s, flags %s was not found in the module %s, "
1150 "retried with flags %s", __func__, config.toString().c_str(),
1151 flags.value().toString().c_str(), mInstance.c_str(),
1152 matchFlags.toString().c_str());
1153 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001154 if (portsIt == mPorts.end()) {
1155 ALOGE("%s: mix port for config %s, flags %s is not found in the module %s",
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001156 __func__, config.toString().c_str(), matchFlags.toString().c_str(),
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001157 mInstance.c_str());
1158 return BAD_VALUE;
1159 }
1160 AudioPortConfig requestedPortConfig;
1161 requestedPortConfig.portId = portsIt->first;
1162 setPortConfigFromConfig(&requestedPortConfig, config);
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001163 requestedPortConfig.ext = AudioPortMixExt{ .handle = ioHandle };
Mikhail Naganovd8d01f72023-03-09 16:24:40 -08001164 if (matchFlags.getTag() == AudioIoFlags::Tag::input
1165 && source != AudioSource::SYS_RESERVED_INVALID) {
1166 requestedPortConfig.ext.get<AudioPortExt::Tag::mix>().usecase =
1167 AudioPortMixExtUseCase::make<AudioPortMixExtUseCase::Tag::source>(source);
1168 }
David Lia8675d42023-03-30 21:08:06 +08001169 RETURN_STATUS_IF_ERROR(createOrUpdatePortConfig(requestedPortConfig, &portConfigIt,
1170 created));
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001171 } else if (!flags.has_value()) {
1172 ALOGW("%s: mix port config for %s, handle %d not found in the module %s, "
1173 "and was not created as flags are not specified",
1174 __func__, config.toString().c_str(), ioHandle, mInstance.c_str());
1175 return BAD_VALUE;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001176 } else {
David Lia8675d42023-03-30 21:08:06 +08001177 AudioPortConfig requestedPortConfig = portConfigIt->second;
1178 if (requestedPortConfig.ext.getTag() == AudioPortExt::Tag::mix) {
1179 AudioPortMixExt& mixExt = requestedPortConfig.ext.get<AudioPortExt::Tag::mix>();
1180 if (mixExt.usecase.getTag() == AudioPortMixExtUseCase::Tag::source &&
1181 source != AudioSource::SYS_RESERVED_INVALID) {
1182 mixExt.usecase.get<AudioPortMixExtUseCase::Tag::source>() = source;
1183 }
1184 }
1185
1186 if (requestedPortConfig != portConfigIt->second) {
1187 RETURN_STATUS_IF_ERROR(createOrUpdatePortConfig(requestedPortConfig, &portConfigIt,
1188 created));
1189 } else {
1190 *created = false;
1191 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001192 }
1193 *portConfig = portConfigIt->second;
1194 return OK;
1195}
1196
1197status_t DeviceHalAidl::findOrCreatePortConfig(
Mikhail Naganov289468a2023-03-29 10:06:15 -07001198 const AudioPortConfig& requestedPortConfig, const std::set<int32_t>& destinationPortIds,
1199 AudioPortConfig* portConfig, bool* created) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001200 using Tag = AudioPortExt::Tag;
1201 if (requestedPortConfig.ext.getTag() == Tag::mix) {
1202 if (const auto& p = requestedPortConfig;
1203 !p.sampleRate.has_value() || !p.channelMask.has_value() ||
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001204 !p.format.has_value()) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001205 ALOGW("%s: provided mix port config is not fully specified: %s",
1206 __func__, p.toString().c_str());
1207 return BAD_VALUE;
1208 }
1209 AudioConfig config;
1210 setConfigFromPortConfig(&config, requestedPortConfig);
Mikhail Naganovd8d01f72023-03-09 16:24:40 -08001211 AudioSource source = requestedPortConfig.ext.get<Tag::mix>().usecase.getTag() ==
1212 AudioPortMixExtUseCase::Tag::source ?
1213 requestedPortConfig.ext.get<Tag::mix>().usecase.
1214 get<AudioPortMixExtUseCase::Tag::source>() : AudioSource::SYS_RESERVED_INVALID;
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001215 return findOrCreatePortConfig(config, requestedPortConfig.flags,
Mikhail Naganov289468a2023-03-29 10:06:15 -07001216 requestedPortConfig.ext.get<Tag::mix>().handle, source, destinationPortIds,
1217 portConfig, created);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001218 } else if (requestedPortConfig.ext.getTag() == Tag::device) {
1219 return findOrCreatePortConfig(
jiabin9c07faf2023-04-26 22:00:44 +00001220 requestedPortConfig.ext.get<Tag::device>().device, nullptr /*config*/,
1221 portConfig, created);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001222 }
1223 ALOGW("%s: unsupported audio port config: %s",
1224 __func__, requestedPortConfig.toString().c_str());
1225 return BAD_VALUE;
1226}
1227
1228DeviceHalAidl::Patches::iterator DeviceHalAidl::findPatch(
1229 const std::set<int32_t>& sourcePortConfigIds, const std::set<int32_t>& sinkPortConfigIds) {
1230 return std::find_if(mPatches.begin(), mPatches.end(),
1231 [&](const auto& pair) {
1232 const auto& p = pair.second;
1233 std::set<int32_t> patchSrcs(
1234 p.sourcePortConfigIds.begin(), p.sourcePortConfigIds.end());
1235 std::set<int32_t> patchSinks(
1236 p.sinkPortConfigIds.begin(), p.sinkPortConfigIds.end());
1237 return sourcePortConfigIds == patchSrcs && sinkPortConfigIds == patchSinks; });
1238}
1239
1240DeviceHalAidl::Ports::iterator DeviceHalAidl::findPort(const AudioDevice& device) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001241 if (device.type.type == AudioDeviceType::IN_DEFAULT) {
1242 return mPorts.find(mDefaultInputPortId);
1243 } else if (device.type.type == AudioDeviceType::OUT_DEFAULT) {
1244 return mPorts.find(mDefaultOutputPortId);
1245 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001246 return std::find_if(mPorts.begin(), mPorts.end(),
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001247 [&](const auto& pair) { return audioDeviceMatches(device, pair.second); });
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001248}
1249
1250DeviceHalAidl::Ports::iterator DeviceHalAidl::findPort(
Mikhail Naganov289468a2023-03-29 10:06:15 -07001251 const AudioConfig& config, const AudioIoFlags& flags,
1252 const std::set<int32_t>& destinationPortIds) {
Mikhail Naganove93a0862023-03-15 17:06:59 -07001253 auto belongsToProfile = [&config](const AudioProfile& prof) {
1254 return (isDefaultAudioFormat(config.base.format) || prof.format == config.base.format) &&
1255 (config.base.channelMask.getTag() == AudioChannelLayout::none ||
1256 std::find(prof.channelMasks.begin(), prof.channelMasks.end(),
1257 config.base.channelMask) != prof.channelMasks.end()) &&
1258 (config.base.sampleRate == 0 ||
1259 std::find(prof.sampleRates.begin(), prof.sampleRates.end(),
1260 config.base.sampleRate) != prof.sampleRates.end());
1261 };
jiabin9c07faf2023-04-26 22:00:44 +00001262 static const std::vector<AudioOutputFlags> kOptionalOutputFlags{AudioOutputFlags::BIT_PERFECT};
1263 int optionalFlags = 0;
1264 auto flagMatches = [&flags, &optionalFlags](const AudioIoFlags& portFlags) {
1265 // Ports should be able to match if the optional flags are not requested.
1266 return portFlags == flags ||
1267 (portFlags.getTag() == AudioIoFlags::Tag::output &&
1268 AudioIoFlags::make<AudioIoFlags::Tag::output>(
1269 portFlags.get<AudioIoFlags::Tag::output>() &
1270 ~optionalFlags) == flags);
1271 };
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001272 auto matcher = [&](const auto& pair) {
1273 const auto& p = pair.second;
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001274 return p.ext.getTag() == AudioPortExt::Tag::mix &&
jiabin9c07faf2023-04-26 22:00:44 +00001275 flagMatches(p.flags) &&
Mikhail Naganov289468a2023-03-29 10:06:15 -07001276 (destinationPortIds.empty() ||
1277 std::any_of(destinationPortIds.begin(), destinationPortIds.end(),
1278 [&](const int32_t destId) { return mRoutingMatrix.count(
1279 std::make_pair(p.id, destId)) != 0; })) &&
Mikhail Naganove93a0862023-03-15 17:06:59 -07001280 (p.profiles.empty() ||
1281 std::find_if(p.profiles.begin(), p.profiles.end(), belongsToProfile) !=
1282 p.profiles.end()); };
jiabin9c07faf2023-04-26 22:00:44 +00001283 auto result = std::find_if(mPorts.begin(), mPorts.end(), matcher);
1284 if (result == mPorts.end() && flags.getTag() == AudioIoFlags::Tag::output) {
1285 auto optionalOutputFlagsIt = kOptionalOutputFlags.begin();
1286 while (result == mPorts.end() && optionalOutputFlagsIt != kOptionalOutputFlags.end()) {
1287 if (isBitPositionFlagSet(
1288 flags.get<AudioIoFlags::Tag::output>(), *optionalOutputFlagsIt)) {
1289 // If the flag is set by the request, it must be matched.
1290 ++optionalOutputFlagsIt;
1291 continue;
1292 }
1293 optionalFlags |= makeBitPositionFlagMask(*optionalOutputFlagsIt++);
1294 result = std::find_if(mPorts.begin(), mPorts.end(), matcher);
1295 ALOGI("%s: port for config %s, flags %s was not found in the module %s, "
1296 "retried with excluding optional flags %#x", __func__, config.toString().c_str(),
1297 flags.toString().c_str(), mInstance.c_str(), optionalFlags);
1298 }
1299 }
1300 return result;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001301}
1302
1303DeviceHalAidl::PortConfigs::iterator DeviceHalAidl::findPortConfig(const AudioDevice& device) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001304 return std::find_if(mPortConfigs.begin(), mPortConfigs.end(),
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001305 [&](const auto& pair) { return audioDeviceMatches(device, pair.second); });
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001306}
1307
1308DeviceHalAidl::PortConfigs::iterator DeviceHalAidl::findPortConfig(
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001309 const AudioConfig& config, const std::optional<AudioIoFlags>& flags, int32_t ioHandle) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001310 using Tag = AudioPortExt::Tag;
1311 return std::find_if(mPortConfigs.begin(), mPortConfigs.end(),
1312 [&](const auto& pair) {
1313 const auto& p = pair.second;
1314 LOG_ALWAYS_FATAL_IF(p.ext.getTag() == Tag::mix &&
1315 !p.sampleRate.has_value() || !p.channelMask.has_value() ||
1316 !p.format.has_value() || !p.flags.has_value(),
1317 "%s: stored mix port config is not fully specified: %s",
1318 __func__, p.toString().c_str());
1319 return p.ext.getTag() == Tag::mix &&
1320 isConfigEqualToPortConfig(config, p) &&
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001321 (!flags.has_value() || p.flags.value() == flags.value()) &&
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001322 p.ext.template get<Tag::mix>().handle == ioHandle; });
1323}
Mikhail Naganove93a0862023-03-15 17:06:59 -07001324
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001325void DeviceHalAidl::resetPatch(int32_t patchId) {
1326 if (auto it = mPatches.find(patchId); it != mPatches.end()) {
1327 mPatches.erase(it);
1328 TIME_CHECK();
1329 if (ndk::ScopedAStatus status = mModule->resetAudioPatch(patchId); !status.isOk()) {
1330 ALOGE("%s: error while resetting patch %d: %s",
1331 __func__, patchId, status.getDescription().c_str());
1332 }
1333 return;
1334 }
1335 ALOGE("%s: patch id %d not found", __func__, patchId);
1336}
1337
1338void DeviceHalAidl::resetPortConfig(int32_t portConfigId) {
1339 if (auto it = mPortConfigs.find(portConfigId); it != mPortConfigs.end()) {
1340 mPortConfigs.erase(it);
1341 TIME_CHECK();
1342 if (ndk::ScopedAStatus status = mModule->resetAudioPortConfig(portConfigId);
1343 !status.isOk()) {
1344 ALOGE("%s: error while resetting port config %d: %s",
1345 __func__, portConfigId, status.getDescription().c_str());
1346 }
1347 return;
1348 }
1349 ALOGE("%s: port config id %d not found", __func__, portConfigId);
1350}
1351
Mikhail Naganove93a0862023-03-15 17:06:59 -07001352void DeviceHalAidl::resetUnusedPatches() {
1353 // Since patches can be created independently of streams via 'createAudioPatch',
1354 // here we only clean up patches for released streams.
1355 for (auto it = mStreams.begin(); it != mStreams.end(); ) {
1356 if (auto streamSp = it->first.promote(); streamSp) {
1357 ++it;
1358 } else {
1359 resetPatch(it->second);
1360 it = mStreams.erase(it);
1361 }
1362 }
1363}
1364
1365void DeviceHalAidl::resetUnusedPatchesAndPortConfigs() {
1366 resetUnusedPatches();
1367 resetUnusedPortConfigs();
1368}
1369
1370void DeviceHalAidl::resetUnusedPortConfigs() {
1371 // The assumption is that port configs are used to create patches
1372 // (or to open streams, but that involves creation of patches, too). Thus,
1373 // orphaned port configs can and should be reset.
1374 std::set<int32_t> portConfigIds;
1375 std::transform(mPortConfigs.begin(), mPortConfigs.end(),
1376 std::inserter(portConfigIds, portConfigIds.end()),
1377 [](const auto& pcPair) { return pcPair.first; });
1378 for (const auto& p : mPatches) {
1379 for (int32_t id : p.second.sourcePortConfigIds) portConfigIds.erase(id);
1380 for (int32_t id : p.second.sinkPortConfigIds) portConfigIds.erase(id);
1381 }
jiabin9c07faf2023-04-26 22:00:44 +00001382 for (int32_t id : mInitialPortConfigIds) {
1383 portConfigIds.erase(id);
1384 }
Mikhail Naganove93a0862023-03-15 17:06:59 -07001385 for (int32_t id : portConfigIds) resetPortConfig(id);
1386}
1387
Mikhail Naganov289468a2023-03-29 10:06:15 -07001388status_t DeviceHalAidl::updateRoutes() {
1389 TIME_CHECK();
Mikhail Naganov289468a2023-03-29 10:06:15 -07001390 RETURN_STATUS_IF_ERROR(
Mikhail Naganovf83b9742023-04-24 13:06:04 -07001391 statusTFromBinderStatus(mModule->getAudioRoutes(&mRoutes)));
1392 ALOGW_IF(mRoutes.empty(), "%s: module %s returned an empty list of audio routes",
Mikhail Naganov289468a2023-03-29 10:06:15 -07001393 __func__, mInstance.c_str());
1394 mRoutingMatrix.clear();
Mikhail Naganovf83b9742023-04-24 13:06:04 -07001395 for (const auto& r : mRoutes) {
Mikhail Naganov289468a2023-03-29 10:06:15 -07001396 for (auto portId : r.sourcePortIds) {
1397 mRoutingMatrix.emplace(r.sinkPortId, portId);
1398 mRoutingMatrix.emplace(portId, r.sinkPortId);
1399 }
1400 }
1401 return OK;
1402}
1403
Mikhail Naganovdfd594e2023-02-08 16:59:41 -08001404void DeviceHalAidl::clearCallbacks(void* cookie) {
1405 std::lock_guard l(mLock);
1406 mCallbacks.erase(cookie);
1407}
1408
1409sp<StreamOutHalInterfaceCallback> DeviceHalAidl::getStreamOutCallback(void* cookie) {
1410 return getCallbackImpl(cookie, &Callbacks::out);
1411}
1412
1413void DeviceHalAidl::setStreamOutCallback(
1414 void* cookie, const sp<StreamOutHalInterfaceCallback>& cb) {
1415 setCallbackImpl(cookie, &Callbacks::out, cb);
1416}
1417
1418sp<StreamOutHalInterfaceEventCallback> DeviceHalAidl::getStreamOutEventCallback(
1419 void* cookie) {
1420 return getCallbackImpl(cookie, &Callbacks::event);
1421}
1422
1423void DeviceHalAidl::setStreamOutEventCallback(
1424 void* cookie, const sp<StreamOutHalInterfaceEventCallback>& cb) {
1425 setCallbackImpl(cookie, &Callbacks::event, cb);
1426}
1427
1428sp<StreamOutHalInterfaceLatencyModeCallback> DeviceHalAidl::getStreamOutLatencyModeCallback(
1429 void* cookie) {
1430 return getCallbackImpl(cookie, &Callbacks::latency);
1431}
1432
1433void DeviceHalAidl::setStreamOutLatencyModeCallback(
1434 void* cookie, const sp<StreamOutHalInterfaceLatencyModeCallback>& cb) {
1435 setCallbackImpl(cookie, &Callbacks::latency, cb);
1436}
1437
1438template<class C>
1439sp<C> DeviceHalAidl::getCallbackImpl(void* cookie, wp<C> DeviceHalAidl::Callbacks::* field) {
1440 std::lock_guard l(mLock);
1441 if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
1442 return ((it->second).*field).promote();
1443 }
1444 return nullptr;
1445}
1446template<class C>
1447void DeviceHalAidl::setCallbackImpl(
1448 void* cookie, wp<C> DeviceHalAidl::Callbacks::* field, const sp<C>& cb) {
1449 std::lock_guard l(mLock);
1450 if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
1451 (it->second).*field = cb;
1452 }
1453}
1454
Mikhail Naganov31d46652023-01-10 18:29:25 +00001455} // namespace android