blob: 58b4406394ec4342db366440632073eedff1607c [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 Naganovccc82112023-04-27 18:14:15 -070038using aidl::android::media::audio::common::Boolean;
Mikhail Naganove93a0862023-03-15 17:06:59 -070039using aidl::android::media::audio::common::AudioChannelLayout;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -080040using aidl::android::media::audio::common::AudioConfig;
41using aidl::android::media::audio::common::AudioDevice;
David Li9cf5e622023-03-21 00:51:10 +080042using aidl::android::media::audio::common::AudioDeviceAddress;
Mikhail Naganov89a9f742023-01-30 12:33:18 -080043using aidl::android::media::audio::common::AudioDeviceType;
Mikhail Naganove93a0862023-03-15 17:06:59 -070044using aidl::android::media::audio::common::AudioFormatType;
Mikhail Naganov89a9f742023-01-30 12:33:18 -080045using aidl::android::media::audio::common::AudioInputFlags;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -080046using aidl::android::media::audio::common::AudioIoFlags;
Mikhail Naganovdfd594e2023-02-08 16:59:41 -080047using aidl::android::media::audio::common::AudioLatencyMode;
David Li9cf5e622023-03-21 00:51:10 +080048using aidl::android::media::audio::common::AudioMMapPolicy;
49using aidl::android::media::audio::common::AudioMMapPolicyInfo;
50using aidl::android::media::audio::common::AudioMMapPolicyType;
Mikhail Naganovfab697c2023-01-11 19:33:13 +000051using aidl::android::media::audio::common::AudioMode;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -080052using aidl::android::media::audio::common::AudioOutputFlags;
53using aidl::android::media::audio::common::AudioPort;
54using aidl::android::media::audio::common::AudioPortConfig;
Mikhail Naganov89a9f742023-01-30 12:33:18 -080055using aidl::android::media::audio::common::AudioPortDeviceExt;
David Li9cf5e622023-03-21 00:51:10 +080056using aidl::android::media::audio::common::AudioPortExt;
Mikhail Naganov1a44bc62023-02-16 17:35:06 -080057using aidl::android::media::audio::common::AudioPortMixExt;
Mikhail Naganovd8d01f72023-03-09 16:24:40 -080058using aidl::android::media::audio::common::AudioPortMixExtUseCase;
Mikhail Naganove93a0862023-03-15 17:06:59 -070059using aidl::android::media::audio::common::AudioProfile;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -080060using aidl::android::media::audio::common::AudioSource;
Mikhail Naganovfab697c2023-01-11 19:33:13 +000061using aidl::android::media::audio::common::Float;
David Li9cf5e622023-03-21 00:51:10 +080062using aidl::android::media::audio::common::Int;
63using aidl::android::media::audio::common::MicrophoneDynamicInfo;
64using aidl::android::media::audio::common::MicrophoneInfo;
Mikhail Naganov6352e822023-03-09 18:22:36 -080065using aidl::android::hardware::audio::common::getFrameSizeInBytes;
66using aidl::android::hardware::audio::common::isBitPositionFlagSet;
Mikhail Naganove93a0862023-03-15 17:06:59 -070067using aidl::android::hardware::audio::common::isDefaultAudioFormat;
Mikhail Naganov6352e822023-03-09 18:22:36 -080068using aidl::android::hardware::audio::common::makeBitPositionFlagMask;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -080069using aidl::android::hardware::audio::common::RecordTrackMetadata;
70using aidl::android::hardware::audio::core::AudioPatch;
Mikhail Naganov289468a2023-03-29 10:06:15 -070071using aidl::android::hardware::audio::core::AudioRoute;
Mikhail Naganovccc82112023-04-27 18:14:15 -070072using aidl::android::hardware::audio::core::IBluetooth;
73using aidl::android::hardware::audio::core::IBluetoothA2dp;
74using aidl::android::hardware::audio::core::IBluetoothLe;
Mikhail Naganovfab697c2023-01-11 19:33:13 +000075using aidl::android::hardware::audio::core::IModule;
76using aidl::android::hardware::audio::core::ITelephony;
Mikhail Naganove93a0862023-03-15 17:06:59 -070077using aidl::android::hardware::audio::core::ModuleDebug;
Mikhail Naganovfab697c2023-01-11 19:33:13 +000078using aidl::android::hardware::audio::core::StreamDescriptor;
Mikhail Naganov31d46652023-01-10 18:29:25 +000079
80namespace android {
81
Mikhail Naganov5b1eed12023-01-25 11:29:11 -080082namespace {
83
84bool isConfigEqualToPortConfig(const AudioConfig& config, const AudioPortConfig& portConfig) {
85 return portConfig.sampleRate.value().value == config.base.sampleRate &&
86 portConfig.channelMask.value() == config.base.channelMask &&
87 portConfig.format.value() == config.base.format;
88}
89
90void setConfigFromPortConfig(AudioConfig* config, const AudioPortConfig& portConfig) {
91 config->base.sampleRate = portConfig.sampleRate.value().value;
92 config->base.channelMask = portConfig.channelMask.value();
93 config->base.format = portConfig.format.value();
94}
95
96void setPortConfigFromConfig(AudioPortConfig* portConfig, const AudioConfig& config) {
97 portConfig->sampleRate = Int{ .value = config.base.sampleRate };
98 portConfig->channelMask = config.base.channelMask;
99 portConfig->format = config.base.format;
100}
101
Mikhail Naganovf83b9742023-04-24 13:06:04 -0700102// Note: these converters are for types defined in different AIDL files. Although these
103// AIDL files are copies of each other, however formally these are different types
104// thus we don't use a conversion via a parcelable.
105ConversionResult<media::AudioRoute> ndk2cpp_AudioRoute(const AudioRoute& ndk) {
106 media::AudioRoute cpp;
107 cpp.sourcePortIds.insert(
108 cpp.sourcePortIds.end(), ndk.sourcePortIds.begin(), ndk.sourcePortIds.end());
109 cpp.sinkPortId = ndk.sinkPortId;
110 cpp.isExclusive = ndk.isExclusive;
David Li9cf5e622023-03-21 00:51:10 +0800111 return cpp;
112}
113
Mikhail Naganov1fba38c2023-05-03 17:45:36 -0700114template<typename T>
115std::shared_ptr<T> retrieveSubInterface(const std::shared_ptr<IModule>& module,
116 ::ndk::ScopedAStatus (IModule::*getT)(std::shared_ptr<T>*)) {
117 if (module != nullptr) {
118 std::shared_ptr<T> instance;
119 if (auto status = (module.get()->*getT)(&instance); status.isOk()) {
120 return instance;
121 }
122 }
123 return nullptr;
124}
125
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800126} // namespace
127
Mikhail Naganov1fba38c2023-05-03 17:45:36 -0700128DeviceHalAidl::DeviceHalAidl(const std::string& instance, const std::shared_ptr<IModule>& module)
129 : ConversionHelperAidl("DeviceHalAidl"),
130 mInstance(instance), mModule(module),
Mikhail Naganovccc82112023-04-27 18:14:15 -0700131 mTelephony(retrieveSubInterface<ITelephony>(module, &IModule::getTelephony)),
132 mBluetooth(retrieveSubInterface<IBluetooth>(module, &IModule::getBluetooth)),
133 mBluetoothA2dp(retrieveSubInterface<IBluetoothA2dp>(module, &IModule::getBluetoothA2dp)),
134 mBluetoothLe(retrieveSubInterface<IBluetoothLe>(module, &IModule::getBluetoothLe)) {
Mikhail Naganov1fba38c2023-05-03 17:45:36 -0700135}
136
Mikhail Naganovf83b9742023-04-24 13:06:04 -0700137status_t DeviceHalAidl::getAudioPorts(std::vector<media::audio::common::AudioPort> *ports) {
Mikhail Naganov9e459d72023-05-05 17:36:39 -0700138 return ::aidl::android::convertContainer(mPorts, ports,
139 [](const Ports::value_type& pair) { return ndk2cpp_AudioPort(pair.second); });
Mikhail Naganovf83b9742023-04-24 13:06:04 -0700140}
141
142status_t DeviceHalAidl::getAudioRoutes(std::vector<media::AudioRoute> *routes) {
143 *routes = VALUE_OR_RETURN_STATUS(
144 ::aidl::android::convertContainer<std::vector<media::AudioRoute>>(
145 mRoutes, ndk2cpp_AudioRoute));
146 return OK;
147}
148
Mikhail Naganov1fba38c2023-05-03 17:45:36 -0700149status_t DeviceHalAidl::getSupportedModes(std::vector<media::audio::common::AudioMode> *modes) {
150 TIME_CHECK();
151 if (modes == nullptr) {
152 return BAD_VALUE;
153 }
154 if (mModule == nullptr) return NO_INIT;
155 if (mTelephony == nullptr) return INVALID_OPERATION;
156 std::vector<AudioMode> aidlModes;
157 RETURN_STATUS_IF_ERROR(
158 statusTFromBinderStatus(mTelephony->getSupportedAudioModes(&aidlModes)));
159 *modes = VALUE_OR_RETURN_STATUS(
160 ::aidl::android::convertContainer<std::vector<media::audio::common::AudioMode>>(
161 aidlModes, ndk2cpp_AudioMode));
162 return OK;
163}
164
Mikhail Naganov31d46652023-01-10 18:29:25 +0000165status_t DeviceHalAidl::getSupportedDevices(uint32_t*) {
166 // Obsolete.
167 return INVALID_OPERATION;
Shunkai Yao51202502022-12-12 06:11:46 +0000168}
169
170status_t DeviceHalAidl::initCheck() {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800171 TIME_CHECK();
Mikhail Naganov31d46652023-01-10 18:29:25 +0000172 if (mModule == nullptr) return NO_INIT;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800173 std::vector<AudioPort> ports;
Mikhail Naganovf83b9742023-04-24 13:06:04 -0700174 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->getAudioPorts(&ports)));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800175 ALOGW_IF(ports.empty(), "%s: module %s returned an empty list of audio ports",
176 __func__, mInstance.c_str());
177 std::transform(ports.begin(), ports.end(), std::inserter(mPorts, mPorts.end()),
178 [](const auto& p) { return std::make_pair(p.id, p); });
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800179 mDefaultInputPortId = mDefaultOutputPortId = -1;
180 const int defaultDeviceFlag = 1 << AudioPortDeviceExt::FLAG_INDEX_DEFAULT_DEVICE;
181 for (const auto& pair : mPorts) {
182 const auto& p = pair.second;
183 if (p.ext.getTag() == AudioPortExt::Tag::device &&
184 (p.ext.get<AudioPortExt::Tag::device>().flags & defaultDeviceFlag) != 0) {
185 if (p.flags.getTag() == AudioIoFlags::Tag::input) {
186 mDefaultInputPortId = p.id;
187 } else if (p.flags.getTag() == AudioIoFlags::Tag::output) {
188 mDefaultOutputPortId = p.id;
189 }
190 }
191 }
192 ALOGI("%s: module %s default port ids: input %d, output %d",
193 __func__, mInstance.c_str(), mDefaultInputPortId, mDefaultOutputPortId);
Mikhail Naganov289468a2023-03-29 10:06:15 -0700194 RETURN_STATUS_IF_ERROR(updateRoutes());
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800195 std::vector<AudioPortConfig> portConfigs;
196 RETURN_STATUS_IF_ERROR(
197 statusTFromBinderStatus(mModule->getAudioPortConfigs(&portConfigs))); // OK if empty
198 std::transform(portConfigs.begin(), portConfigs.end(),
199 std::inserter(mPortConfigs, mPortConfigs.end()),
200 [](const auto& p) { return std::make_pair(p.id, p); });
jiabin9c07faf2023-04-26 22:00:44 +0000201 std::transform(mPortConfigs.begin(), mPortConfigs.end(),
202 std::inserter(mInitialPortConfigIds, mInitialPortConfigIds.end()),
203 [](const auto& pcPair) { return pcPair.first; });
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800204 std::vector<AudioPatch> patches;
205 RETURN_STATUS_IF_ERROR(
206 statusTFromBinderStatus(mModule->getAudioPatches(&patches))); // OK if empty
207 std::transform(patches.begin(), patches.end(),
208 std::inserter(mPatches, mPatches.end()),
209 [](const auto& p) { return std::make_pair(p.id, p); });
Shunkai Yao51202502022-12-12 06:11:46 +0000210 return OK;
211}
212
213status_t DeviceHalAidl::setVoiceVolume(float volume) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000214 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000215 if (!mModule) return NO_INIT;
Mikhail Naganov1fba38c2023-05-03 17:45:36 -0700216 if (mTelephony == nullptr) return INVALID_OPERATION;
217 ITelephony::TelecomConfig inConfig{ .voiceVolume = Float{volume} }, outConfig;
218 RETURN_STATUS_IF_ERROR(
219 statusTFromBinderStatus(mTelephony->setTelecomConfig(inConfig, &outConfig)));
220 ALOGW_IF(outConfig.voiceVolume.has_value() && volume != outConfig.voiceVolume.value().value,
221 "%s: the resulting voice volume %f is not the same as requested %f",
222 __func__, outConfig.voiceVolume.value().value, volume);
223 return OK;
Shunkai Yao51202502022-12-12 06:11:46 +0000224}
225
226status_t DeviceHalAidl::setMasterVolume(float volume) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000227 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000228 if (!mModule) return NO_INIT;
229 return statusTFromBinderStatus(mModule->setMasterVolume(volume));
Shunkai Yao51202502022-12-12 06:11:46 +0000230}
231
232status_t DeviceHalAidl::getMasterVolume(float *volume) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000233 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000234 if (!mModule) return NO_INIT;
235 return statusTFromBinderStatus(mModule->getMasterVolume(volume));
Shunkai Yao51202502022-12-12 06:11:46 +0000236}
237
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000238status_t DeviceHalAidl::setMode(audio_mode_t mode) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000239 TIME_CHECK();
240 if (!mModule) return NO_INIT;
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000241 AudioMode audioMode = VALUE_OR_FATAL(::aidl::android::legacy2aidl_audio_mode_t_AudioMode(mode));
Mikhail Naganov1fba38c2023-05-03 17:45:36 -0700242 if (mTelephony != nullptr) {
243 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mTelephony->switchAudioMode(audioMode)));
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000244 }
245 return statusTFromBinderStatus(mModule->updateAudioMode(audioMode));
Shunkai Yao51202502022-12-12 06:11:46 +0000246}
247
248status_t DeviceHalAidl::setMicMute(bool state) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000249 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000250 if (!mModule) return NO_INIT;
251 return statusTFromBinderStatus(mModule->setMicMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000252}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000253
Shunkai Yao51202502022-12-12 06:11:46 +0000254status_t DeviceHalAidl::getMicMute(bool *state) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000255 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000256 if (!mModule) return NO_INIT;
257 return statusTFromBinderStatus(mModule->getMicMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000258}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000259
Shunkai Yao51202502022-12-12 06:11:46 +0000260status_t DeviceHalAidl::setMasterMute(bool state) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000261 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000262 if (!mModule) return NO_INIT;
263 return statusTFromBinderStatus(mModule->setMasterMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000264}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000265
Shunkai Yao51202502022-12-12 06:11:46 +0000266status_t DeviceHalAidl::getMasterMute(bool *state) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000267 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000268 if (!mModule) return NO_INIT;
269 return statusTFromBinderStatus(mModule->getMasterMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000270}
271
Mikhail Naganovccc82112023-04-27 18:14:15 -0700272status_t DeviceHalAidl::setParameters(const String8& kvPairs) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000273 if (!mModule) return NO_INIT;
Mikhail Naganovccc82112023-04-27 18:14:15 -0700274 AudioParameter parameters(kvPairs);
275 ALOGD("%s: parameters: \"%s\"", __func__, parameters.toString().c_str());
276
277 if (status_t status = filterAndUpdateBtA2dpParameters(parameters); status != OK) {
278 ALOGW("%s: filtering or updating BT A2DP parameters failed: %d", __func__, status);
279 }
280 if (status_t status = filterAndUpdateBtHfpParameters(parameters); status != OK) {
281 ALOGW("%s: filtering or updating BT HFP parameters failed: %d", __func__, status);
282 }
283 if (status_t status = filterAndUpdateBtLeParameters(parameters); status != OK) {
284 ALOGW("%s: filtering or updating BT LE parameters failed: %d", __func__, status);
285 }
286 if (status_t status = filterAndUpdateBtScoParameters(parameters); status != OK) {
287 ALOGW("%s: filtering or updating BT SCO parameters failed: %d", __func__, status);
288 }
Mikhail Naganove92c34b2023-05-31 14:24:48 -0700289 if (status_t status = filterAndUpdateScreenParameters(parameters); status != OK) {
290 ALOGW("%s: filtering or updating screen parameters failed: %d", __func__, status);
291 }
Mikhail Naganovccc82112023-04-27 18:14:15 -0700292
293 ALOGW_IF(parameters.size() != 0, "%s: unknown parameters, ignored: \"%s\"",
294 __func__, parameters.toString().c_str());
Shunkai Yao51202502022-12-12 06:11:46 +0000295 return OK;
296}
297
Mikhail Naganov31d46652023-01-10 18:29:25 +0000298status_t DeviceHalAidl::getParameters(const String8& keys __unused, String8 *values) {
299 TIME_CHECK();
Mikhail Naganovccc82112023-04-27 18:14:15 -0700300 // FIXME(b/278976019): Support keyReconfigA2dpSupported via vendor plugin
Mikhail Naganov31d46652023-01-10 18:29:25 +0000301 values->clear();
302 if (!mModule) return NO_INIT;
303 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000304 return OK;
305}
306
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800307namespace {
308
309class Cleanup {
310 public:
311 typedef void (DeviceHalAidl::*Cleaner)(int32_t);
312
313 Cleanup(DeviceHalAidl* device, Cleaner cleaner, int32_t id) :
314 mDevice(device), mCleaner(cleaner), mId(id) {}
315 ~Cleanup() { clean(); }
316 void clean() {
317 if (mDevice != nullptr) (mDevice->*mCleaner)(mId);
318 disarm();
319 }
320 void disarm() { mDevice = nullptr; }
321
322 private:
323 DeviceHalAidl* mDevice;
324 const Cleaner mCleaner;
325 const int32_t mId;
326};
327
328} // namespace
329
330// Since the order of container elements destruction is unspecified,
331// ensure that cleanups are performed from the most recent one and upwards.
332// This is the same as if there were individual Cleanup instances on the stack,
333// however the bonus is that we can disarm all of them with just one statement.
334class DeviceHalAidl::Cleanups : public std::forward_list<Cleanup> {
335 public:
336 ~Cleanups() { for (auto& c : *this) c.clean(); }
337 void disarmAll() { for (auto& c : *this) c.disarm(); }
338};
339
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800340status_t DeviceHalAidl::getInputBufferSize(const struct audio_config* config, size_t* size) {
341 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
342 if (size == nullptr) return BAD_VALUE;
343 TIME_CHECK();
344 if (!mModule) return NO_INIT;
345 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
346 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, true /*isInput*/));
347 AudioDevice aidlDevice;
348 aidlDevice.type.type = AudioDeviceType::IN_DEFAULT;
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800349 AudioSource aidlSource = AudioSource::DEFAULT;
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800350 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::input>(0);
351 AudioPortConfig mixPortConfig;
352 Cleanups cleanups;
353 audio_config writableConfig = *config;
Mikhail Naganove93a0862023-03-15 17:06:59 -0700354 AudioPatch aidlPatch;
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800355 RETURN_STATUS_IF_ERROR(prepareToOpenStream(0 /*handle*/, aidlDevice, aidlFlags, aidlSource,
Mikhail Naganove93a0862023-03-15 17:06:59 -0700356 &writableConfig, &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800357 *size = aidlConfig.frameCount *
358 getFrameSizeInBytes(aidlConfig.base.format, aidlConfig.base.channelMask);
359 // Do not disarm cleanups to release temporary port configs.
360 return OK;
361}
362
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800363status_t DeviceHalAidl::prepareToOpenStream(
364 int32_t aidlHandle, const AudioDevice& aidlDevice, const AudioIoFlags& aidlFlags,
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800365 AudioSource aidlSource, struct audio_config* config,
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800366 Cleanups* cleanups, AudioConfig* aidlConfig, AudioPortConfig* mixPortConfig,
Mikhail Naganove93a0862023-03-15 17:06:59 -0700367 AudioPatch* aidlPatch) {
368 ALOGD("%p %s::%s: handle %d, device %s, flags %s, source %s, config %s, mix port config %s",
369 this, getClassName().c_str(), __func__, aidlHandle, aidlDevice.toString().c_str(),
370 aidlFlags.toString().c_str(), toString(aidlSource).c_str(),
371 aidlConfig->toString().c_str(), mixPortConfig->toString().c_str());
jiabin9c07faf2023-04-26 22:00:44 +0000372 resetUnusedPatchesAndPortConfigs();
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800373 const bool isInput = aidlFlags.getTag() == AudioIoFlags::Tag::input;
374 // Find / create AudioPortConfigs for the device port and the mix port,
375 // then find / create a patch between them, and open a stream on the mix port.
376 AudioPortConfig devicePortConfig;
377 bool created = false;
jiabin9c07faf2023-04-26 22:00:44 +0000378 RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(aidlDevice, aidlConfig,
379 &devicePortConfig, &created));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800380 if (created) {
381 cleanups->emplace_front(this, &DeviceHalAidl::resetPortConfig, devicePortConfig.id);
382 }
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800383 RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(*aidlConfig, aidlFlags, aidlHandle, aidlSource,
Mikhail Naganov289468a2023-03-29 10:06:15 -0700384 std::set<int32_t>{devicePortConfig.portId}, mixPortConfig, &created));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800385 if (created) {
386 cleanups->emplace_front(this, &DeviceHalAidl::resetPortConfig, mixPortConfig->id);
387 }
388 setConfigFromPortConfig(aidlConfig, *mixPortConfig);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800389 if (isInput) {
390 RETURN_STATUS_IF_ERROR(findOrCreatePatch(
Mikhail Naganove93a0862023-03-15 17:06:59 -0700391 {devicePortConfig.id}, {mixPortConfig->id}, aidlPatch, &created));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800392 } else {
393 RETURN_STATUS_IF_ERROR(findOrCreatePatch(
Mikhail Naganove93a0862023-03-15 17:06:59 -0700394 {mixPortConfig->id}, {devicePortConfig.id}, aidlPatch, &created));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800395 }
396 if (created) {
Mikhail Naganove93a0862023-03-15 17:06:59 -0700397 cleanups->emplace_front(this, &DeviceHalAidl::resetPatch, aidlPatch->id);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800398 }
399 if (aidlConfig->frameCount <= 0) {
Mikhail Naganove93a0862023-03-15 17:06:59 -0700400 aidlConfig->frameCount = aidlPatch->minimumStreamBufferSizeFrames;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800401 }
402 *config = VALUE_OR_RETURN_STATUS(
403 ::aidl::android::aidl2legacy_AudioConfig_audio_config_t(*aidlConfig, isInput));
404 return OK;
405}
406
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800407namespace {
408
409class StreamCallbackBase {
410 protected:
411 explicit StreamCallbackBase(const sp<CallbackBroker>& broker) : mBroker(broker) {}
412 public:
413 void* getCookie() const { return mCookie; }
414 void setCookie(void* cookie) { mCookie = cookie; }
415 sp<CallbackBroker> getBroker() const {
416 if (void* cookie = mCookie; cookie != nullptr) return mBroker.promote();
417 return nullptr;
418 }
419 private:
420 const wp<CallbackBroker> mBroker;
421 std::atomic<void*> mCookie;
422};
423
424template<class C>
425class StreamCallbackBaseHelper {
426 protected:
427 explicit StreamCallbackBaseHelper(const StreamCallbackBase& base) : mBase(base) {}
428 sp<C> getCb(const sp<CallbackBroker>& broker, void* cookie);
429 using CbRef = const sp<C>&;
430 ndk::ScopedAStatus runCb(const std::function<void(CbRef cb)>& f) {
431 if (auto cb = getCb(mBase.getBroker(), mBase.getCookie()); cb != nullptr) f(cb);
432 return ndk::ScopedAStatus::ok();
433 }
434 private:
435 const StreamCallbackBase& mBase;
436};
437
438template<>
439sp<StreamOutHalInterfaceCallback> StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>::getCb(
440 const sp<CallbackBroker>& broker, void* cookie) {
441 if (broker != nullptr) return broker->getStreamOutCallback(cookie);
442 return nullptr;
443}
444
445template<>
446sp<StreamOutHalInterfaceEventCallback>
447StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>::getCb(
448 const sp<CallbackBroker>& broker, void* cookie) {
449 if (broker != nullptr) return broker->getStreamOutEventCallback(cookie);
450 return nullptr;
451}
452
453template<>
454sp<StreamOutHalInterfaceLatencyModeCallback>
455StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>::getCb(
456 const sp<CallbackBroker>& broker, void* cookie) {
457 if (broker != nullptr) return broker->getStreamOutLatencyModeCallback(cookie);
458 return nullptr;
459}
460
461/*
462Note on the callback ownership.
463
464In the Binder ownership model, the server implementation is kept alive
465as long as there is any client (proxy object) alive. This is done by
466incrementing the refcount of the server-side object by the Binder framework.
467When it detects that the last client is gone, it decrements the refcount back.
468
469Thus, it is not needed to keep any references to StreamCallback on our
470side (after we have sent an instance to the client), because we are
471the server-side. The callback object will be kept alive as long as the HAL server
472holds a strong ref to IStreamCallback proxy.
473*/
474
475class OutputStreamCallbackAidl : public StreamCallbackBase,
476 public StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>,
477 public ::aidl::android::hardware::audio::core::BnStreamCallback {
478 public:
479 explicit OutputStreamCallbackAidl(const sp<CallbackBroker>& broker)
480 : StreamCallbackBase(broker),
481 StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>(
482 *static_cast<StreamCallbackBase*>(this)) {}
483 ndk::ScopedAStatus onTransferReady() override {
484 return runCb([](CbRef cb) { cb->onWriteReady(); });
485 }
486 ndk::ScopedAStatus onError() override {
487 return runCb([](CbRef cb) { cb->onError(); });
488 }
489 ndk::ScopedAStatus onDrainReady() override {
490 return runCb([](CbRef cb) { cb->onDrainReady(); });
491 }
492};
493
494class OutputStreamEventCallbackAidl :
495 public StreamCallbackBase,
496 public StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>,
497 public StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>,
498 public ::aidl::android::hardware::audio::core::BnStreamOutEventCallback {
499 public:
500 explicit OutputStreamEventCallbackAidl(const sp<CallbackBroker>& broker)
501 : StreamCallbackBase(broker),
502 StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>(
503 *static_cast<StreamCallbackBase*>(this)),
504 StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>(
505 *static_cast<StreamCallbackBase*>(this)) {}
506 ndk::ScopedAStatus onCodecFormatChanged(const std::vector<uint8_t>& in_audioMetadata) override {
507 std::basic_string<uint8_t> halMetadata(in_audioMetadata.begin(), in_audioMetadata.end());
508 return StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>::runCb(
509 [&halMetadata](auto cb) { cb->onCodecFormatChanged(halMetadata); });
510 }
511 ndk::ScopedAStatus onRecommendedLatencyModeChanged(
512 const std::vector<AudioLatencyMode>& in_modes) override {
513 auto halModes = VALUE_OR_FATAL(
514 ::aidl::android::convertContainer<std::vector<audio_latency_mode_t>>(
515 in_modes,
516 ::aidl::android::aidl2legacy_AudioLatencyMode_audio_latency_mode_t));
517 return StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>::runCb(
518 [&halModes](auto cb) { cb->onRecommendedLatencyModeChanged(halModes); });
519 }
520};
521
522} // namespace
523
Mikhail Naganov31d46652023-01-10 18:29:25 +0000524status_t DeviceHalAidl::openOutputStream(
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800525 audio_io_handle_t handle, audio_devices_t devices,
526 audio_output_flags_t flags, struct audio_config* config,
527 const char* address,
Mikhail Naganov31d46652023-01-10 18:29:25 +0000528 sp<StreamOutHalInterface>* outStream) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800529 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000530 if (!outStream || !config) {
531 return BAD_VALUE;
532 }
533 TIME_CHECK();
534 if (!mModule) return NO_INIT;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800535 int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
536 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(handle));
537 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
538 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, false /*isInput*/));
539 AudioDevice aidlDevice = VALUE_OR_RETURN_STATUS(
540 ::aidl::android::legacy2aidl_audio_device_AudioDevice(devices, address));
541 int32_t aidlOutputFlags = VALUE_OR_RETURN_STATUS(
542 ::aidl::android::legacy2aidl_audio_output_flags_t_int32_t_mask(flags));
543 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::output>(aidlOutputFlags);
544 AudioPortConfig mixPortConfig;
545 Cleanups cleanups;
Mikhail Naganove93a0862023-03-15 17:06:59 -0700546 AudioPatch aidlPatch;
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800547 RETURN_STATUS_IF_ERROR(prepareToOpenStream(aidlHandle, aidlDevice, aidlFlags,
548 AudioSource::SYS_RESERVED_INVALID /*only needed for input*/,
Mikhail Naganove93a0862023-03-15 17:06:59 -0700549 config, &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800550 ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamArguments args;
551 args.portConfigId = mixPortConfig.id;
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800552 const bool isOffload = isBitPositionFlagSet(
553 aidlOutputFlags, AudioOutputFlags::COMPRESS_OFFLOAD);
554 std::shared_ptr<OutputStreamCallbackAidl> streamCb;
555 if (isOffload) {
556 streamCb = ndk::SharedRefBase::make<OutputStreamCallbackAidl>(this);
557 }
558 auto eventCb = ndk::SharedRefBase::make<OutputStreamEventCallbackAidl>(this);
559 if (isOffload) {
560 args.offloadInfo = aidlConfig.offloadInfo;
561 args.callback = streamCb;
562 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800563 args.bufferSizeFrames = aidlConfig.frameCount;
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800564 args.eventCallback = eventCb;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800565 ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamReturn ret;
566 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openOutputStream(args, &ret)));
Mikhail Naganov712d71b2023-02-23 17:57:16 -0800567 StreamContextAidl context(ret.desc, isOffload);
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800568 if (!context.isValid()) {
569 ALOGE("%s: Failed to created a valid stream context from the descriptor: %s",
570 __func__, ret.desc.toString().c_str());
571 return NO_INIT;
572 }
Mikhail Naganove93a0862023-03-15 17:06:59 -0700573 *outStream = sp<StreamOutHalAidl>::make(*config, std::move(context), aidlPatch.latenciesMs[0],
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800574 std::move(ret.stream), this /*callbackBroker*/);
Mikhail Naganove93a0862023-03-15 17:06:59 -0700575 mStreams.insert(std::pair(*outStream, aidlPatch.id));
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800576 void* cbCookie = (*outStream).get();
577 {
578 std::lock_guard l(mLock);
579 mCallbacks.emplace(cbCookie, Callbacks{});
580 }
581 if (streamCb) streamCb->setCookie(cbCookie);
582 eventCb->setCookie(cbCookie);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800583 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000584 return OK;
585}
586
Mikhail Naganov31d46652023-01-10 18:29:25 +0000587status_t DeviceHalAidl::openInputStream(
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800588 audio_io_handle_t handle, audio_devices_t devices,
589 struct audio_config* config, audio_input_flags_t flags,
590 const char* address, audio_source_t source,
591 audio_devices_t outputDevice, const char* outputDeviceAddress,
Mikhail Naganov31d46652023-01-10 18:29:25 +0000592 sp<StreamInHalInterface>* inStream) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800593 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000594 if (!inStream || !config) {
595 return BAD_VALUE;
596 }
597 TIME_CHECK();
598 if (!mModule) return NO_INIT;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800599 int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
600 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(handle));
601 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
602 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, true /*isInput*/));
603 AudioDevice aidlDevice = VALUE_OR_RETURN_STATUS(
604 ::aidl::android::legacy2aidl_audio_device_AudioDevice(devices, address));
605 int32_t aidlInputFlags = VALUE_OR_RETURN_STATUS(
606 ::aidl::android::legacy2aidl_audio_input_flags_t_int32_t_mask(flags));
607 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::input>(aidlInputFlags);
608 AudioSource aidlSource = VALUE_OR_RETURN_STATUS(
609 ::aidl::android::legacy2aidl_audio_source_t_AudioSource(source));
610 AudioPortConfig mixPortConfig;
611 Cleanups cleanups;
Mikhail Naganove93a0862023-03-15 17:06:59 -0700612 AudioPatch aidlPatch;
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800613 RETURN_STATUS_IF_ERROR(prepareToOpenStream(aidlHandle, aidlDevice, aidlFlags, aidlSource,
Mikhail Naganove93a0862023-03-15 17:06:59 -0700614 config, &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800615 ::aidl::android::hardware::audio::core::IModule::OpenInputStreamArguments args;
616 args.portConfigId = mixPortConfig.id;
617 RecordTrackMetadata aidlTrackMetadata{
618 .source = aidlSource, .gain = 1, .channelMask = aidlConfig.base.channelMask };
619 if (outputDevice != AUDIO_DEVICE_NONE) {
620 aidlTrackMetadata.destinationDevice = VALUE_OR_RETURN_STATUS(
621 ::aidl::android::legacy2aidl_audio_device_AudioDevice(
622 outputDevice, outputDeviceAddress));
623 }
624 args.sinkMetadata.tracks.push_back(std::move(aidlTrackMetadata));
625 args.bufferSizeFrames = aidlConfig.frameCount;
626 ::aidl::android::hardware::audio::core::IModule::OpenInputStreamReturn ret;
627 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openInputStream(args, &ret)));
Mikhail Naganov712d71b2023-02-23 17:57:16 -0800628 StreamContextAidl context(ret.desc, false /*isAsynchronous*/);
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800629 if (!context.isValid()) {
630 ALOGE("%s: Failed to created a valid stream context from the descriptor: %s",
631 __func__, ret.desc.toString().c_str());
632 return NO_INIT;
633 }
Mikhail Naganove93a0862023-03-15 17:06:59 -0700634 *inStream = sp<StreamInHalAidl>::make(*config, std::move(context), aidlPatch.latenciesMs[0],
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800635 std::move(ret.stream), this /*micInfoProvider*/);
Mikhail Naganove93a0862023-03-15 17:06:59 -0700636 mStreams.insert(std::pair(*inStream, aidlPatch.id));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800637 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000638 return OK;
639}
640
641status_t DeviceHalAidl::supportsAudioPatches(bool* supportsPatches) {
642 *supportsPatches = true;
643 return OK;
644}
645
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800646status_t DeviceHalAidl::createAudioPatch(unsigned int num_sources,
647 const struct audio_port_config* sources,
648 unsigned int num_sinks,
649 const struct audio_port_config* sinks,
650 audio_patch_handle_t* patch) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800651 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000652 TIME_CHECK();
653 if (!mModule) return NO_INIT;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800654 if (num_sinks > AUDIO_PATCH_PORTS_MAX || num_sources > AUDIO_PATCH_PORTS_MAX ||
655 sources == nullptr || sinks == nullptr || patch == nullptr) {
656 return BAD_VALUE;
657 }
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800658 // When the patch handle (*patch) is AUDIO_PATCH_HANDLE_NONE, it means
659 // the framework wants to create a new patch. The handle has to be generated
660 // by the HAL. Since handles generated this way can only be unique within
661 // a HAL module, the framework generates a globally unique handle, and maps
662 // it on the <HAL module, patch handle> pair.
663 // When the patch handle is set, it meant the framework intends to update
664 // an existing patch.
665 //
666 // This behavior corresponds to HAL module behavior, with the only difference
667 // that the HAL module uses `int32_t` for patch IDs. The following assert ensures
668 // that both the framework and the HAL use the same value for "no ID":
669 static_assert(AUDIO_PATCH_HANDLE_NONE == 0);
670 int32_t halPatchId = static_cast<int32_t>(*patch);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800671
672 // Upon conversion, mix port configs contain audio configuration, while
673 // device port configs contain device address. This data is used to find
674 // or create HAL configs.
675 std::vector<AudioPortConfig> aidlSources, aidlSinks;
676 for (unsigned int i = 0; i < num_sources; ++i) {
677 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
678 sources[i].role, sources[i].type)) ==
679 ::aidl::android::AudioPortDirection::INPUT;
680 aidlSources.push_back(VALUE_OR_RETURN_STATUS(
681 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
682 sources[i], isInput, 0)));
683 }
684 for (unsigned int i = 0; i < num_sinks; ++i) {
685 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
686 sinks[i].role, sinks[i].type)) ==
687 ::aidl::android::AudioPortDirection::INPUT;
688 aidlSinks.push_back(VALUE_OR_RETURN_STATUS(
689 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
690 sinks[i], isInput, 0)));
691 }
692 Cleanups cleanups;
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800693 auto existingPatchIt = halPatchId != 0 ? mPatches.find(halPatchId): mPatches.end();
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800694 AudioPatch aidlPatch;
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800695 if (existingPatchIt != mPatches.end()) {
696 aidlPatch = existingPatchIt->second;
697 aidlPatch.sourcePortConfigIds.clear();
698 aidlPatch.sinkPortConfigIds.clear();
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800699 }
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800700 ALOGD("%s: sources: %s, sinks: %s",
701 __func__, ::android::internal::ToString(aidlSources).c_str(),
702 ::android::internal::ToString(aidlSinks).c_str());
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800703 auto fillPortConfigs = [&](
Mikhail Naganov289468a2023-03-29 10:06:15 -0700704 const std::vector<AudioPortConfig>& configs,
705 const std::set<int32_t>& destinationPortIds,
706 std::vector<int32_t>* ids, std::set<int32_t>* portIds) -> status_t {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800707 for (const auto& s : configs) {
708 AudioPortConfig portConfig;
709 bool created = false;
Mikhail Naganov289468a2023-03-29 10:06:15 -0700710 RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(
711 s, destinationPortIds, &portConfig, &created));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800712 if (created) {
713 cleanups.emplace_front(this, &DeviceHalAidl::resetPortConfig, portConfig.id);
714 }
715 ids->push_back(portConfig.id);
Mikhail Naganov289468a2023-03-29 10:06:15 -0700716 if (portIds != nullptr) {
717 portIds->insert(portConfig.portId);
718 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800719 }
720 return OK;
721 };
Mikhail Naganov289468a2023-03-29 10:06:15 -0700722 // When looking up port configs, the destinationPortId is only used for mix ports.
723 // Thus, we process device port configs first, and look up the destination port ID from them.
724 bool sourceIsDevice = std::any_of(aidlSources.begin(), aidlSources.end(),
725 [](const auto& config) { return config.ext.getTag() == AudioPortExt::device; });
726 const std::vector<AudioPortConfig>& devicePortConfigs =
727 sourceIsDevice ? aidlSources : aidlSinks;
728 std::vector<int32_t>* devicePortConfigIds =
729 sourceIsDevice ? &aidlPatch.sourcePortConfigIds : &aidlPatch.sinkPortConfigIds;
730 const std::vector<AudioPortConfig>& mixPortConfigs =
731 sourceIsDevice ? aidlSinks : aidlSources;
732 std::vector<int32_t>* mixPortConfigIds =
733 sourceIsDevice ? &aidlPatch.sinkPortConfigIds : &aidlPatch.sourcePortConfigIds;
734 std::set<int32_t> devicePortIds;
735 RETURN_STATUS_IF_ERROR(fillPortConfigs(
736 devicePortConfigs, std::set<int32_t>(), devicePortConfigIds, &devicePortIds));
737 RETURN_STATUS_IF_ERROR(fillPortConfigs(
738 mixPortConfigs, devicePortIds, mixPortConfigIds, nullptr));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800739 if (existingPatchIt != mPatches.end()) {
740 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
741 mModule->setAudioPatch(aidlPatch, &aidlPatch)));
742 existingPatchIt->second = aidlPatch;
743 } else {
744 bool created = false;
745 RETURN_STATUS_IF_ERROR(findOrCreatePatch(aidlPatch, &aidlPatch, &created));
746 // Since no cleanup of the patch is needed, 'created' is ignored.
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800747 halPatchId = aidlPatch.id;
748 *patch = static_cast<audio_patch_handle_t>(halPatchId);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800749 }
750 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000751 return OK;
752}
753
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800754status_t DeviceHalAidl::releaseAudioPatch(audio_patch_handle_t patch) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800755 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000756 TIME_CHECK();
757 if (!mModule) return NO_INIT;
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800758 static_assert(AUDIO_PATCH_HANDLE_NONE == 0);
759 if (patch == AUDIO_PATCH_HANDLE_NONE) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800760 return BAD_VALUE;
761 }
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800762 int32_t halPatchId = static_cast<int32_t>(patch);
763 auto patchIt = mPatches.find(halPatchId);
764 if (patchIt == mPatches.end()) {
765 ALOGE("%s: patch with id %d not found", __func__, halPatchId);
766 return BAD_VALUE;
767 }
768 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->resetAudioPatch(halPatchId)));
769 mPatches.erase(patchIt);
Shunkai Yao51202502022-12-12 06:11:46 +0000770 return OK;
771}
772
Mikhail Naganove93a0862023-03-15 17:06:59 -0700773status_t DeviceHalAidl::getAudioPort(struct audio_port* port) {
774 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000775 TIME_CHECK();
776 if (!mModule) return NO_INIT;
Mikhail Naganove93a0862023-03-15 17:06:59 -0700777 if (port == nullptr) {
778 return BAD_VALUE;
779 }
780 audio_port_v7 portV7;
781 audio_populate_audio_port_v7(port, &portV7);
782 RETURN_STATUS_IF_ERROR(getAudioPort(&portV7));
783 return audio_populate_audio_port(&portV7, port) ? OK : BAD_VALUE;
784}
785
786status_t DeviceHalAidl::getAudioPort(struct audio_port_v7 *port) {
787 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
788 TIME_CHECK();
789 if (!mModule) return NO_INIT;
790 if (port == nullptr) {
791 return BAD_VALUE;
792 }
793 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(port->role, port->type)) ==
794 ::aidl::android::AudioPortDirection::INPUT;
795 auto aidlPort = VALUE_OR_RETURN_STATUS(
796 ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
797 if (aidlPort.ext.getTag() != AudioPortExt::device) {
798 ALOGE("%s: provided port is not a device port (module %s): %s",
799 __func__, mInstance.c_str(), aidlPort.toString().c_str());
800 return BAD_VALUE;
801 }
802 const auto& matchDevice = aidlPort.ext.get<AudioPortExt::device>().device;
803 // It seems that we don't have to call HAL since all valid ports have been added either
804 // during initialization, or while handling connection of an external device.
805 auto portsIt = findPort(matchDevice);
806 if (portsIt == mPorts.end()) {
807 ALOGE("%s: device port for device %s is not found in the module %s",
808 __func__, matchDevice.toString().c_str(), mInstance.c_str());
809 return BAD_VALUE;
810 }
811 const int32_t fwkId = aidlPort.id;
812 aidlPort = portsIt->second;
813 aidlPort.id = fwkId;
814 *port = VALUE_OR_RETURN_STATUS(::aidl::android::aidl2legacy_AudioPort_audio_port_v7(
815 aidlPort, isInput));
816 return OK;
817}
818
819status_t DeviceHalAidl::setAudioPortConfig(const struct audio_port_config* config) {
820 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
821 TIME_CHECK();
822 if (!mModule) return NO_INIT;
823 if (config == nullptr) {
824 return BAD_VALUE;
825 }
826 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
827 config->role, config->type)) == ::aidl::android::AudioPortDirection::INPUT;
828 AudioPortConfig requestedPortConfig = VALUE_OR_RETURN_STATUS(
829 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
830 *config, isInput, 0 /*portId*/));
831 AudioPortConfig portConfig;
832 bool created = false;
Mikhail Naganov289468a2023-03-29 10:06:15 -0700833 RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(
834 requestedPortConfig, std::set<int32_t>(), &portConfig, &created));
Shunkai Yao51202502022-12-12 06:11:46 +0000835 return OK;
836}
837
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800838MicrophoneInfoProvider::Info const* DeviceHalAidl::getMicrophoneInfo() {
839 if (mMicrophones.status == Microphones::Status::UNKNOWN) {
840 TIME_CHECK();
841 std::vector<MicrophoneInfo> aidlInfo;
842 status_t status = statusTFromBinderStatus(mModule->getMicrophones(&aidlInfo));
843 if (status == OK) {
844 mMicrophones.status = Microphones::Status::QUERIED;
845 mMicrophones.info = std::move(aidlInfo);
846 } else if (status == INVALID_OPERATION) {
847 mMicrophones.status = Microphones::Status::NOT_SUPPORTED;
848 } else {
849 ALOGE("%s: Unexpected status from 'IModule.getMicrophones': %d", __func__, status);
850 return {};
851 }
852 }
853 if (mMicrophones.status == Microphones::Status::QUERIED) {
854 return &mMicrophones.info;
855 }
856 return {}; // NOT_SUPPORTED
857}
858
Shunkai Yao51202502022-12-12 06:11:46 +0000859status_t DeviceHalAidl::getMicrophones(
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800860 std::vector<audio_microphone_characteristic_t>* microphones) {
861 if (!microphones) {
862 return BAD_VALUE;
863 }
Mikhail Naganov31d46652023-01-10 18:29:25 +0000864 TIME_CHECK();
865 if (!mModule) return NO_INIT;
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800866 auto staticInfo = getMicrophoneInfo();
867 if (!staticInfo) return INVALID_OPERATION;
868 std::vector<MicrophoneDynamicInfo> emptyDynamicInfo;
869 emptyDynamicInfo.reserve(staticInfo->size());
870 std::transform(staticInfo->begin(), staticInfo->end(), std::back_inserter(emptyDynamicInfo),
871 [](const auto& info) { return MicrophoneDynamicInfo{ .id = info.id }; });
872 *microphones = VALUE_OR_RETURN_STATUS(
873 ::aidl::android::convertContainers<std::vector<audio_microphone_characteristic_t>>(
874 *staticInfo, emptyDynamicInfo,
875 ::aidl::android::aidl2legacy_MicrophoneInfos_audio_microphone_characteristic_t)
876 );
Shunkai Yao51202502022-12-12 06:11:46 +0000877 return OK;
878}
879
Mikhail Naganov31d46652023-01-10 18:29:25 +0000880status_t DeviceHalAidl::addDeviceEffect(audio_port_handle_t device __unused,
881 sp<EffectHalInterface> effect) {
Shunkai Yao51202502022-12-12 06:11:46 +0000882 if (!effect) {
883 return BAD_VALUE;
884 }
Mikhail Naganov31d46652023-01-10 18:29:25 +0000885 TIME_CHECK();
886 if (!mModule) return NO_INIT;
887 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000888 return OK;
889}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000890status_t DeviceHalAidl::removeDeviceEffect(audio_port_handle_t device __unused,
Shunkai Yao51202502022-12-12 06:11:46 +0000891 sp<EffectHalInterface> effect) {
892 if (!effect) {
893 return BAD_VALUE;
894 }
Mikhail Naganov31d46652023-01-10 18:29:25 +0000895 TIME_CHECK();
896 if (!mModule) return NO_INIT;
897 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000898 return OK;
899}
900
901status_t DeviceHalAidl::getMmapPolicyInfos(
David Li9cf5e622023-03-21 00:51:10 +0800902 media::audio::common::AudioMMapPolicyType policyType,
903 std::vector<media::audio::common::AudioMMapPolicyInfo>* policyInfos) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000904 TIME_CHECK();
Mikhail Naganov25bc9a22023-04-21 18:48:16 -0700905 AudioMMapPolicyType mmapPolicyType = VALUE_OR_RETURN_STATUS(
906 cpp2ndk_AudioMMapPolicyType(policyType));
David Li9cf5e622023-03-21 00:51:10 +0800907
908 std::vector<AudioMMapPolicyInfo> mmapPolicyInfos;
909
910 if (status_t status = statusTFromBinderStatus(
911 mModule->getMmapPolicyInfos(mmapPolicyType, &mmapPolicyInfos)); status != OK) {
912 return status;
913 }
914
915 *policyInfos = VALUE_OR_RETURN_STATUS(
916 convertContainer<std::vector<media::audio::common::AudioMMapPolicyInfo>>(
917 mmapPolicyInfos, ndk2cpp_AudioMMapPolicyInfo));
Shunkai Yao51202502022-12-12 06:11:46 +0000918 return OK;
919}
920
921int32_t DeviceHalAidl::getAAudioMixerBurstCount() {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000922 TIME_CHECK();
David Li9cf5e622023-03-21 00:51:10 +0800923 int32_t mixerBurstCount = 0;
924 if (mModule->getAAudioMixerBurstCount(&mixerBurstCount).isOk()) {
925 return mixerBurstCount;
926 }
927 return 0;
Shunkai Yao51202502022-12-12 06:11:46 +0000928}
929
930int32_t DeviceHalAidl::getAAudioHardwareBurstMinUsec() {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000931 TIME_CHECK();
David Li9cf5e622023-03-21 00:51:10 +0800932 int32_t hardwareBurstMinUsec = 0;
933 if (mModule->getAAudioHardwareBurstMinUsec(&hardwareBurstMinUsec).isOk()) {
934 return hardwareBurstMinUsec;
935 }
936 return 0;
Shunkai Yao51202502022-12-12 06:11:46 +0000937}
938
939error::Result<audio_hw_sync_t> DeviceHalAidl::getHwAvSync() {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000940 TIME_CHECK();
Mikhail Naganov08a62ab2023-03-14 17:11:51 -0700941 if (!mModule) return NO_INIT;
942 int32_t aidlHwAvSync;
943 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->generateHwAvSyncId(&aidlHwAvSync)));
944 return VALUE_OR_RETURN_STATUS(
945 ::aidl::android::aidl2legacy_int32_t_audio_hw_sync_t(aidlHwAvSync));
Shunkai Yao51202502022-12-12 06:11:46 +0000946}
947
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000948status_t DeviceHalAidl::dump(int fd, const Vector<String16>& args) {
949 TIME_CHECK();
950 if (!mModule) return NO_INIT;
951 return mModule->dump(fd, Args(args).args(), args.size());
David Li9cf5e622023-03-21 00:51:10 +0800952}
Shunkai Yao51202502022-12-12 06:11:46 +0000953
Mikhail Naganov3ac95c92023-04-12 13:14:30 -0700954int32_t DeviceHalAidl::supportsBluetoothVariableLatency(bool* supports) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000955 TIME_CHECK();
Mikhail Naganov3ac95c92023-04-12 13:14:30 -0700956 if (!mModule) return NO_INIT;
957 if (supports == nullptr) {
958 return BAD_VALUE;
959 }
960 return statusTFromBinderStatus(mModule->supportsVariableLatency(supports));
Shunkai Yao51202502022-12-12 06:11:46 +0000961}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000962
jiabin872de702023-04-27 22:04:31 +0000963
964status_t DeviceHalAidl::prepareToDisconnectExternalDevice(const struct audio_port_v7* port) {
965 // There is not AIDL API defined for `prepareToDisconnectExternalDevice`.
966 // Call `setConnectedState` instead.
967 // TODO(b/279824103): call prepareToDisconnectExternalDevice when it is added.
968 const status_t status = setConnectedState(port, false /*connected*/);
969 if (status == NO_ERROR) {
970 mDeviceDisconnectionNotified.insert(port->id);
971 }
972 return status;
973}
974
Mikhail Naganove93a0862023-03-15 17:06:59 -0700975status_t DeviceHalAidl::setConnectedState(const struct audio_port_v7 *port, bool connected) {
976 TIME_CHECK();
977 if (!mModule) return NO_INIT;
978 if (port == nullptr) {
979 return BAD_VALUE;
980 }
jiabin872de702023-04-27 22:04:31 +0000981 if (!connected && mDeviceDisconnectionNotified.erase(port->id) > 0) {
982 // For device disconnection, APM will first call `prepareToDisconnectExternalDevice`
983 // and then call `setConnectedState`. However, there is no API for
984 // `prepareToDisconnectExternalDevice` yet. In that case, `setConnectedState` will be
985 // called when calling `prepareToDisconnectExternalDevice`. Do not call to the HAL if
986 // previous call is successful. Also remove the cache here to avoid a large cache after
987 // a long run.
988 return NO_ERROR;
989 }
Mikhail Naganove93a0862023-03-15 17:06:59 -0700990 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(port->role, port->type)) ==
991 ::aidl::android::AudioPortDirection::INPUT;
992 AudioPort aidlPort = VALUE_OR_RETURN_STATUS(
993 ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
994 if (aidlPort.ext.getTag() != AudioPortExt::device) {
995 ALOGE("%s: provided port is not a device port (module %s): %s",
996 __func__, mInstance.c_str(), aidlPort.toString().c_str());
997 return BAD_VALUE;
998 }
999 if (connected) {
1000 AudioDevice matchDevice = aidlPort.ext.get<AudioPortExt::device>().device;
1001 // Reset the device address to find the "template" port.
1002 matchDevice.address = AudioDeviceAddress::make<AudioDeviceAddress::id>();
1003 auto portsIt = findPort(matchDevice);
1004 if (portsIt == mPorts.end()) {
1005 ALOGW("%s: device port for device %s is not found in the module %s",
1006 __func__, matchDevice.toString().c_str(), mInstance.c_str());
1007 return BAD_VALUE;
1008 }
1009 // Use the ID of the "template" port, use all the information from the provided port.
1010 aidlPort.id = portsIt->first;
1011 AudioPort connectedPort;
1012 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->connectExternalDevice(
1013 aidlPort, &connectedPort)));
1014 const auto [it, inserted] = mPorts.insert(std::make_pair(connectedPort.id, connectedPort));
1015 LOG_ALWAYS_FATAL_IF(!inserted,
1016 "%s: module %s, duplicate port ID received from HAL: %s, existing port: %s",
1017 __func__, mInstance.c_str(), connectedPort.toString().c_str(),
1018 it->second.toString().c_str());
1019 } else { // !connected
1020 AudioDevice matchDevice = aidlPort.ext.get<AudioPortExt::device>().device;
1021 auto portsIt = findPort(matchDevice);
1022 if (portsIt == mPorts.end()) {
1023 ALOGW("%s: device port for device %s is not found in the module %s",
1024 __func__, matchDevice.toString().c_str(), mInstance.c_str());
1025 return BAD_VALUE;
1026 }
1027 // Any streams opened on the external device must be closed by this time,
1028 // thus we can clean up patches and port configs that were created for them.
1029 resetUnusedPatchesAndPortConfigs();
1030 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->disconnectExternalDevice(
1031 portsIt->second.id)));
1032 mPorts.erase(portsIt);
1033 }
Mikhail Naganov289468a2023-03-29 10:06:15 -07001034 return updateRoutes();
Mikhail Naganove93a0862023-03-15 17:06:59 -07001035}
1036
1037status_t DeviceHalAidl::setSimulateDeviceConnections(bool enabled) {
1038 TIME_CHECK();
1039 if (!mModule) return NO_INIT;
1040 ModuleDebug debug{ .simulateDeviceConnections = enabled };
1041 status_t status = statusTFromBinderStatus(mModule->setModuleDebug(debug));
1042 // This is important to log as it affects HAL behavior.
1043 if (status == OK) {
1044 ALOGI("%s: set enabled: %d", __func__, enabled);
1045 } else {
1046 ALOGW("%s: set enabled to %d failed: %d", __func__, enabled, status);
1047 }
1048 return status;
1049}
1050
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001051bool DeviceHalAidl::audioDeviceMatches(const AudioDevice& device, const AudioPort& p) {
1052 if (p.ext.getTag() != AudioPortExt::Tag::device) return false;
1053 return p.ext.get<AudioPortExt::Tag::device>().device == device;
1054}
1055
1056bool DeviceHalAidl::audioDeviceMatches(const AudioDevice& device, const AudioPortConfig& p) {
1057 if (p.ext.getTag() != AudioPortExt::Tag::device) return false;
1058 if (device.type.type == AudioDeviceType::IN_DEFAULT) {
1059 return p.portId == mDefaultInputPortId;
1060 } else if (device.type.type == AudioDeviceType::OUT_DEFAULT) {
1061 return p.portId == mDefaultOutputPortId;
1062 }
1063 return p.ext.get<AudioPortExt::Tag::device>().device == device;
1064}
1065
David Lia8675d42023-03-30 21:08:06 +08001066status_t DeviceHalAidl::createOrUpdatePortConfig(
1067 const AudioPortConfig& requestedPortConfig, PortConfigs::iterator* result, bool* created) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001068 TIME_CHECK();
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001069 AudioPortConfig appliedPortConfig;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001070 bool applied = false;
1071 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPortConfig(
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001072 requestedPortConfig, &appliedPortConfig, &applied)));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001073 if (!applied) {
1074 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPortConfig(
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001075 appliedPortConfig, &appliedPortConfig, &applied)));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001076 if (!applied) {
1077 ALOGE("%s: module %s did not apply suggested config %s",
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001078 __func__, mInstance.c_str(), appliedPortConfig.toString().c_str());
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001079 return NO_INIT;
1080 }
1081 }
David Lia8675d42023-03-30 21:08:06 +08001082
1083 int32_t id = appliedPortConfig.id;
1084 if (requestedPortConfig.id != 0 && requestedPortConfig.id != id) {
1085 LOG_ALWAYS_FATAL("%s: requested port config id %d changed to %d", __func__,
1086 requestedPortConfig.id, id);
1087 }
1088
1089 auto [it, inserted] = mPortConfigs.insert_or_assign(std::move(id),
1090 std::move(appliedPortConfig));
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001091 *result = it;
David Lia8675d42023-03-30 21:08:06 +08001092 *created = inserted;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001093 return OK;
1094}
1095
Mikhail Naganovccc82112023-04-27 18:14:15 -07001096status_t DeviceHalAidl::filterAndUpdateBtA2dpParameters(AudioParameter &parameters) {
1097 TIME_CHECK();
1098 std::optional<bool> a2dpEnabled;
1099 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1100 parameters, String8(AudioParameter::keyBtA2dpSuspended),
1101 [&a2dpEnabled](const String8& trueOrFalse) {
1102 if (trueOrFalse == AudioParameter::valueTrue) {
1103 a2dpEnabled = false; // 'suspended' == true
1104 return OK;
1105 } else if (trueOrFalse == AudioParameter::valueFalse) {
1106 a2dpEnabled = true; // 'suspended' == false
1107 return OK;
1108 }
1109 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1110 AudioParameter::keyBtA2dpSuspended, trueOrFalse.c_str());
1111 return BAD_VALUE;
1112 }));
1113 // FIXME(b/278976019): Support keyReconfigA2dp via vendor plugin
1114 if (mBluetoothA2dp != nullptr && a2dpEnabled.has_value()) {
1115 return statusTFromBinderStatus(mBluetoothA2dp->setEnabled(a2dpEnabled.value()));
1116 }
1117 return OK;
1118}
1119
1120status_t DeviceHalAidl::filterAndUpdateBtHfpParameters(AudioParameter &parameters) {
1121 TIME_CHECK();
1122 IBluetooth::HfpConfig hfpConfig;
1123 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1124 parameters, String8(AudioParameter::keyBtHfpEnable),
1125 [&hfpConfig](const String8& trueOrFalse) {
1126 if (trueOrFalse == AudioParameter::valueTrue) {
1127 hfpConfig.isEnabled = Boolean{ .value = true };
1128 return OK;
1129 } else if (trueOrFalse == AudioParameter::valueFalse) {
1130 hfpConfig.isEnabled = Boolean{ .value = false };
1131 return OK;
1132 }
1133 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1134 AudioParameter::keyBtHfpEnable, trueOrFalse.c_str());
1135 return BAD_VALUE;
1136 }));
1137 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
1138 parameters, String8(AudioParameter::keyBtHfpSamplingRate),
1139 [&hfpConfig](int sampleRate) {
1140 return sampleRate > 0 ?
1141 hfpConfig.sampleRate = Int{ .value = sampleRate }, OK : BAD_VALUE;
1142 }));
1143 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
1144 parameters, String8(AudioParameter::keyBtHfpVolume),
1145 [&hfpConfig](int volume0to15) {
1146 if (volume0to15 >= 0 && volume0to15 <= 15) {
1147 hfpConfig.volume = Float{ .value = volume0to15 / 15.0f };
1148 return OK;
1149 }
1150 return BAD_VALUE;
1151 }));
1152 if (mBluetooth != nullptr && hfpConfig != IBluetooth::HfpConfig{}) {
1153 IBluetooth::HfpConfig newHfpConfig;
1154 return statusTFromBinderStatus(mBluetooth->setHfpConfig(hfpConfig, &newHfpConfig));
1155 }
1156 return OK;
1157}
1158
1159status_t DeviceHalAidl::filterAndUpdateBtLeParameters(AudioParameter &parameters) {
1160 TIME_CHECK();
1161 std::optional<bool> leEnabled;
1162 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1163 parameters, String8(AudioParameter::keyBtLeSuspended),
1164 [&leEnabled](const String8& trueOrFalse) {
1165 if (trueOrFalse == AudioParameter::valueTrue) {
1166 leEnabled = false; // 'suspended' == true
1167 return OK;
1168 } else if (trueOrFalse == AudioParameter::valueFalse) {
1169 leEnabled = true; // 'suspended' == false
1170 return OK;
1171 }
1172 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1173 AudioParameter::keyBtLeSuspended, trueOrFalse.c_str());
1174 return BAD_VALUE;
1175 }));
1176 if (mBluetoothLe != nullptr && leEnabled.has_value()) {
1177 return statusTFromBinderStatus(mBluetoothLe->setEnabled(leEnabled.value()));
1178 }
1179 return OK;
1180}
1181
1182status_t DeviceHalAidl::filterAndUpdateBtScoParameters(AudioParameter &parameters) {
1183 TIME_CHECK();
1184 IBluetooth::ScoConfig scoConfig;
1185 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1186 parameters, String8(AudioParameter::keyBtSco),
1187 [&scoConfig](const String8& onOrOff) {
1188 if (onOrOff == AudioParameter::valueOn) {
1189 scoConfig.isEnabled = Boolean{ .value = true };
1190 return OK;
1191 } else if (onOrOff == AudioParameter::valueOff) {
1192 scoConfig.isEnabled = Boolean{ .value = false };
1193 return OK;
1194 }
1195 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1196 AudioParameter::keyBtSco, onOrOff.c_str());
1197 return BAD_VALUE;
1198 }));
1199 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1200 parameters, String8(AudioParameter::keyBtScoHeadsetName),
1201 [&scoConfig](const String8& name) {
1202 scoConfig.debugName = name;
1203 return OK;
1204 }));
1205 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1206 parameters, String8(AudioParameter::keyBtNrec),
1207 [&scoConfig](const String8& onOrOff) {
1208 if (onOrOff == AudioParameter::valueOn) {
1209 scoConfig.isNrecEnabled = Boolean{ .value = true };
1210 return OK;
1211 } else if (onOrOff == AudioParameter::valueOff) {
1212 scoConfig.isNrecEnabled = Boolean{ .value = false };
1213 return OK;
1214 }
1215 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1216 AudioParameter::keyBtNrec, onOrOff.c_str());
1217 return BAD_VALUE;
1218 }));
1219 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1220 parameters, String8(AudioParameter::keyBtScoWb),
1221 [&scoConfig](const String8& onOrOff) {
1222 if (onOrOff == AudioParameter::valueOn) {
1223 scoConfig.mode = IBluetooth::ScoConfig::Mode::SCO_WB;
1224 return OK;
1225 } else if (onOrOff == AudioParameter::valueOff) {
1226 scoConfig.mode = IBluetooth::ScoConfig::Mode::SCO;
1227 return OK;
1228 }
1229 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1230 AudioParameter::keyBtScoWb, onOrOff.c_str());
1231 return BAD_VALUE;
1232 }));
1233 if (mBluetooth != nullptr && scoConfig != IBluetooth::ScoConfig{}) {
1234 IBluetooth::ScoConfig newScoConfig;
1235 return statusTFromBinderStatus(mBluetooth->setScoConfig(scoConfig, &newScoConfig));
1236 }
1237 return OK;
1238}
1239
Mikhail Naganove92c34b2023-05-31 14:24:48 -07001240status_t DeviceHalAidl::filterAndUpdateScreenParameters(AudioParameter &parameters) {
1241 TIME_CHECK();
1242 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1243 parameters, String8(AudioParameter::keyScreenState),
1244 [&](const String8& onOrOff) -> status_t {
1245 std::optional<bool> isTurnedOn;
1246 if (onOrOff == AudioParameter::valueOn) {
1247 isTurnedOn = true;
1248 } else if (onOrOff == AudioParameter::valueOff) {
1249 isTurnedOn = false;
1250 }
1251 if (!isTurnedOn.has_value()) {
1252 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1253 AudioParameter::keyScreenState, onOrOff.c_str());
1254 return BAD_VALUE;
1255 }
1256 return statusTFromBinderStatus(
1257 mModule->updateScreenState(isTurnedOn.value()));
1258 }));
1259 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
1260 parameters, String8(AudioParameter::keyScreenRotation),
1261 [&](int rotationDegrees) -> status_t {
1262 IModule::ScreenRotation rotation;
1263 switch (rotationDegrees) {
1264 case 0: rotation = IModule::ScreenRotation::DEG_0; break;
1265 case 90: rotation = IModule::ScreenRotation::DEG_90; break;
1266 case 180: rotation = IModule::ScreenRotation::DEG_180; break;
1267 case 270: rotation = IModule::ScreenRotation::DEG_270; break;
1268 default:
1269 ALOGE("setParameters: parameter key \"%s\" has invalid value %d",
1270 AudioParameter::keyScreenRotation, rotationDegrees);
1271 return BAD_VALUE;
1272 }
1273 return statusTFromBinderStatus(mModule->updateScreenRotation(rotation));
1274 }));
1275 return OK;
1276}
1277
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001278status_t DeviceHalAidl::findOrCreatePatch(
1279 const AudioPatch& requestedPatch, AudioPatch* patch, bool* created) {
1280 std::set<int32_t> sourcePortConfigIds(requestedPatch.sourcePortConfigIds.begin(),
1281 requestedPatch.sourcePortConfigIds.end());
1282 std::set<int32_t> sinkPortConfigIds(requestedPatch.sinkPortConfigIds.begin(),
1283 requestedPatch.sinkPortConfigIds.end());
1284 return findOrCreatePatch(sourcePortConfigIds, sinkPortConfigIds, patch, created);
1285}
1286
1287status_t DeviceHalAidl::findOrCreatePatch(
1288 const std::set<int32_t>& sourcePortConfigIds, const std::set<int32_t>& sinkPortConfigIds,
1289 AudioPatch* patch, bool* created) {
1290 auto patchIt = findPatch(sourcePortConfigIds, sinkPortConfigIds);
1291 if (patchIt == mPatches.end()) {
1292 TIME_CHECK();
1293 AudioPatch requestedPatch, appliedPatch;
1294 requestedPatch.sourcePortConfigIds.insert(requestedPatch.sourcePortConfigIds.end(),
1295 sourcePortConfigIds.begin(), sourcePortConfigIds.end());
1296 requestedPatch.sinkPortConfigIds.insert(requestedPatch.sinkPortConfigIds.end(),
1297 sinkPortConfigIds.begin(), sinkPortConfigIds.end());
1298 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPatch(
1299 requestedPatch, &appliedPatch)));
1300 patchIt = mPatches.insert(mPatches.end(), std::make_pair(appliedPatch.id, appliedPatch));
1301 *created = true;
1302 } else {
1303 *created = false;
1304 }
1305 *patch = patchIt->second;
1306 return OK;
1307}
1308
jiabin9c07faf2023-04-26 22:00:44 +00001309status_t DeviceHalAidl::findOrCreatePortConfig(const AudioDevice& device, const AudioConfig* config,
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001310 AudioPortConfig* portConfig, bool* created) {
1311 auto portConfigIt = findPortConfig(device);
1312 if (portConfigIt == mPortConfigs.end()) {
1313 auto portsIt = findPort(device);
1314 if (portsIt == mPorts.end()) {
1315 ALOGE("%s: device port for device %s is not found in the module %s",
1316 __func__, device.toString().c_str(), mInstance.c_str());
1317 return BAD_VALUE;
1318 }
1319 AudioPortConfig requestedPortConfig;
1320 requestedPortConfig.portId = portsIt->first;
jiabin9c07faf2023-04-26 22:00:44 +00001321 if (config != nullptr) {
1322 setPortConfigFromConfig(&requestedPortConfig, *config);
1323 }
David Lia8675d42023-03-30 21:08:06 +08001324 RETURN_STATUS_IF_ERROR(createOrUpdatePortConfig(requestedPortConfig, &portConfigIt,
1325 created));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001326 } else {
1327 *created = false;
1328 }
1329 *portConfig = portConfigIt->second;
1330 return OK;
1331}
1332
1333status_t DeviceHalAidl::findOrCreatePortConfig(
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001334 const AudioConfig& config, const std::optional<AudioIoFlags>& flags, int32_t ioHandle,
Mikhail Naganov289468a2023-03-29 10:06:15 -07001335 AudioSource source, const std::set<int32_t>& destinationPortIds,
1336 AudioPortConfig* portConfig, bool* created) {
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001337 // These flags get removed one by one in this order when retrying port finding.
1338 static const std::vector<AudioInputFlags> kOptionalInputFlags{
1339 AudioInputFlags::FAST, AudioInputFlags::RAW };
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001340 auto portConfigIt = findPortConfig(config, flags, ioHandle);
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001341 if (portConfigIt == mPortConfigs.end() && flags.has_value()) {
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001342 auto optionalInputFlagsIt = kOptionalInputFlags.begin();
1343 AudioIoFlags matchFlags = flags.value();
Mikhail Naganov289468a2023-03-29 10:06:15 -07001344 auto portsIt = findPort(config, matchFlags, destinationPortIds);
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001345 while (portsIt == mPorts.end() && matchFlags.getTag() == AudioIoFlags::Tag::input
1346 && optionalInputFlagsIt != kOptionalInputFlags.end()) {
1347 if (!isBitPositionFlagSet(
1348 matchFlags.get<AudioIoFlags::Tag::input>(), *optionalInputFlagsIt)) {
1349 ++optionalInputFlagsIt;
1350 continue;
1351 }
1352 matchFlags.set<AudioIoFlags::Tag::input>(matchFlags.get<AudioIoFlags::Tag::input>() &
1353 ~makeBitPositionFlagMask(*optionalInputFlagsIt++));
Mikhail Naganov289468a2023-03-29 10:06:15 -07001354 portsIt = findPort(config, matchFlags, destinationPortIds);
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001355 ALOGI("%s: mix port for config %s, flags %s was not found in the module %s, "
1356 "retried with flags %s", __func__, config.toString().c_str(),
1357 flags.value().toString().c_str(), mInstance.c_str(),
1358 matchFlags.toString().c_str());
1359 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001360 if (portsIt == mPorts.end()) {
1361 ALOGE("%s: mix port for config %s, flags %s is not found in the module %s",
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001362 __func__, config.toString().c_str(), matchFlags.toString().c_str(),
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001363 mInstance.c_str());
1364 return BAD_VALUE;
1365 }
1366 AudioPortConfig requestedPortConfig;
1367 requestedPortConfig.portId = portsIt->first;
1368 setPortConfigFromConfig(&requestedPortConfig, config);
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001369 requestedPortConfig.ext = AudioPortMixExt{ .handle = ioHandle };
Mikhail Naganovd8d01f72023-03-09 16:24:40 -08001370 if (matchFlags.getTag() == AudioIoFlags::Tag::input
1371 && source != AudioSource::SYS_RESERVED_INVALID) {
1372 requestedPortConfig.ext.get<AudioPortExt::Tag::mix>().usecase =
1373 AudioPortMixExtUseCase::make<AudioPortMixExtUseCase::Tag::source>(source);
1374 }
David Lia8675d42023-03-30 21:08:06 +08001375 RETURN_STATUS_IF_ERROR(createOrUpdatePortConfig(requestedPortConfig, &portConfigIt,
1376 created));
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001377 } else if (!flags.has_value()) {
1378 ALOGW("%s: mix port config for %s, handle %d not found in the module %s, "
1379 "and was not created as flags are not specified",
1380 __func__, config.toString().c_str(), ioHandle, mInstance.c_str());
1381 return BAD_VALUE;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001382 } else {
David Lia8675d42023-03-30 21:08:06 +08001383 AudioPortConfig requestedPortConfig = portConfigIt->second;
1384 if (requestedPortConfig.ext.getTag() == AudioPortExt::Tag::mix) {
1385 AudioPortMixExt& mixExt = requestedPortConfig.ext.get<AudioPortExt::Tag::mix>();
1386 if (mixExt.usecase.getTag() == AudioPortMixExtUseCase::Tag::source &&
1387 source != AudioSource::SYS_RESERVED_INVALID) {
1388 mixExt.usecase.get<AudioPortMixExtUseCase::Tag::source>() = source;
1389 }
1390 }
1391
1392 if (requestedPortConfig != portConfigIt->second) {
1393 RETURN_STATUS_IF_ERROR(createOrUpdatePortConfig(requestedPortConfig, &portConfigIt,
1394 created));
1395 } else {
1396 *created = false;
1397 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001398 }
1399 *portConfig = portConfigIt->second;
1400 return OK;
1401}
1402
1403status_t DeviceHalAidl::findOrCreatePortConfig(
Mikhail Naganov289468a2023-03-29 10:06:15 -07001404 const AudioPortConfig& requestedPortConfig, const std::set<int32_t>& destinationPortIds,
1405 AudioPortConfig* portConfig, bool* created) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001406 using Tag = AudioPortExt::Tag;
1407 if (requestedPortConfig.ext.getTag() == Tag::mix) {
1408 if (const auto& p = requestedPortConfig;
1409 !p.sampleRate.has_value() || !p.channelMask.has_value() ||
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001410 !p.format.has_value()) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001411 ALOGW("%s: provided mix port config is not fully specified: %s",
1412 __func__, p.toString().c_str());
1413 return BAD_VALUE;
1414 }
1415 AudioConfig config;
1416 setConfigFromPortConfig(&config, requestedPortConfig);
Mikhail Naganovd8d01f72023-03-09 16:24:40 -08001417 AudioSource source = requestedPortConfig.ext.get<Tag::mix>().usecase.getTag() ==
1418 AudioPortMixExtUseCase::Tag::source ?
1419 requestedPortConfig.ext.get<Tag::mix>().usecase.
1420 get<AudioPortMixExtUseCase::Tag::source>() : AudioSource::SYS_RESERVED_INVALID;
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001421 return findOrCreatePortConfig(config, requestedPortConfig.flags,
Mikhail Naganov289468a2023-03-29 10:06:15 -07001422 requestedPortConfig.ext.get<Tag::mix>().handle, source, destinationPortIds,
1423 portConfig, created);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001424 } else if (requestedPortConfig.ext.getTag() == Tag::device) {
1425 return findOrCreatePortConfig(
jiabin9c07faf2023-04-26 22:00:44 +00001426 requestedPortConfig.ext.get<Tag::device>().device, nullptr /*config*/,
1427 portConfig, created);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001428 }
1429 ALOGW("%s: unsupported audio port config: %s",
1430 __func__, requestedPortConfig.toString().c_str());
1431 return BAD_VALUE;
1432}
1433
1434DeviceHalAidl::Patches::iterator DeviceHalAidl::findPatch(
1435 const std::set<int32_t>& sourcePortConfigIds, const std::set<int32_t>& sinkPortConfigIds) {
1436 return std::find_if(mPatches.begin(), mPatches.end(),
1437 [&](const auto& pair) {
1438 const auto& p = pair.second;
1439 std::set<int32_t> patchSrcs(
1440 p.sourcePortConfigIds.begin(), p.sourcePortConfigIds.end());
1441 std::set<int32_t> patchSinks(
1442 p.sinkPortConfigIds.begin(), p.sinkPortConfigIds.end());
1443 return sourcePortConfigIds == patchSrcs && sinkPortConfigIds == patchSinks; });
1444}
1445
1446DeviceHalAidl::Ports::iterator DeviceHalAidl::findPort(const AudioDevice& device) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001447 if (device.type.type == AudioDeviceType::IN_DEFAULT) {
1448 return mPorts.find(mDefaultInputPortId);
1449 } else if (device.type.type == AudioDeviceType::OUT_DEFAULT) {
1450 return mPorts.find(mDefaultOutputPortId);
1451 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001452 return std::find_if(mPorts.begin(), mPorts.end(),
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001453 [&](const auto& pair) { return audioDeviceMatches(device, pair.second); });
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001454}
1455
1456DeviceHalAidl::Ports::iterator DeviceHalAidl::findPort(
Mikhail Naganov289468a2023-03-29 10:06:15 -07001457 const AudioConfig& config, const AudioIoFlags& flags,
1458 const std::set<int32_t>& destinationPortIds) {
Mikhail Naganove93a0862023-03-15 17:06:59 -07001459 auto belongsToProfile = [&config](const AudioProfile& prof) {
1460 return (isDefaultAudioFormat(config.base.format) || prof.format == config.base.format) &&
1461 (config.base.channelMask.getTag() == AudioChannelLayout::none ||
1462 std::find(prof.channelMasks.begin(), prof.channelMasks.end(),
1463 config.base.channelMask) != prof.channelMasks.end()) &&
1464 (config.base.sampleRate == 0 ||
1465 std::find(prof.sampleRates.begin(), prof.sampleRates.end(),
1466 config.base.sampleRate) != prof.sampleRates.end());
1467 };
jiabin9c07faf2023-04-26 22:00:44 +00001468 static const std::vector<AudioOutputFlags> kOptionalOutputFlags{AudioOutputFlags::BIT_PERFECT};
1469 int optionalFlags = 0;
1470 auto flagMatches = [&flags, &optionalFlags](const AudioIoFlags& portFlags) {
1471 // Ports should be able to match if the optional flags are not requested.
1472 return portFlags == flags ||
1473 (portFlags.getTag() == AudioIoFlags::Tag::output &&
1474 AudioIoFlags::make<AudioIoFlags::Tag::output>(
1475 portFlags.get<AudioIoFlags::Tag::output>() &
1476 ~optionalFlags) == flags);
1477 };
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001478 auto matcher = [&](const auto& pair) {
1479 const auto& p = pair.second;
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001480 return p.ext.getTag() == AudioPortExt::Tag::mix &&
jiabin9c07faf2023-04-26 22:00:44 +00001481 flagMatches(p.flags) &&
Mikhail Naganov289468a2023-03-29 10:06:15 -07001482 (destinationPortIds.empty() ||
1483 std::any_of(destinationPortIds.begin(), destinationPortIds.end(),
1484 [&](const int32_t destId) { return mRoutingMatrix.count(
1485 std::make_pair(p.id, destId)) != 0; })) &&
Mikhail Naganove93a0862023-03-15 17:06:59 -07001486 (p.profiles.empty() ||
1487 std::find_if(p.profiles.begin(), p.profiles.end(), belongsToProfile) !=
1488 p.profiles.end()); };
jiabin9c07faf2023-04-26 22:00:44 +00001489 auto result = std::find_if(mPorts.begin(), mPorts.end(), matcher);
1490 if (result == mPorts.end() && flags.getTag() == AudioIoFlags::Tag::output) {
1491 auto optionalOutputFlagsIt = kOptionalOutputFlags.begin();
1492 while (result == mPorts.end() && optionalOutputFlagsIt != kOptionalOutputFlags.end()) {
1493 if (isBitPositionFlagSet(
1494 flags.get<AudioIoFlags::Tag::output>(), *optionalOutputFlagsIt)) {
1495 // If the flag is set by the request, it must be matched.
1496 ++optionalOutputFlagsIt;
1497 continue;
1498 }
1499 optionalFlags |= makeBitPositionFlagMask(*optionalOutputFlagsIt++);
1500 result = std::find_if(mPorts.begin(), mPorts.end(), matcher);
1501 ALOGI("%s: port for config %s, flags %s was not found in the module %s, "
1502 "retried with excluding optional flags %#x", __func__, config.toString().c_str(),
1503 flags.toString().c_str(), mInstance.c_str(), optionalFlags);
1504 }
1505 }
1506 return result;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001507}
1508
1509DeviceHalAidl::PortConfigs::iterator DeviceHalAidl::findPortConfig(const AudioDevice& device) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001510 return std::find_if(mPortConfigs.begin(), mPortConfigs.end(),
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001511 [&](const auto& pair) { return audioDeviceMatches(device, pair.second); });
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001512}
1513
1514DeviceHalAidl::PortConfigs::iterator DeviceHalAidl::findPortConfig(
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001515 const AudioConfig& config, const std::optional<AudioIoFlags>& flags, int32_t ioHandle) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001516 using Tag = AudioPortExt::Tag;
1517 return std::find_if(mPortConfigs.begin(), mPortConfigs.end(),
1518 [&](const auto& pair) {
1519 const auto& p = pair.second;
1520 LOG_ALWAYS_FATAL_IF(p.ext.getTag() == Tag::mix &&
1521 !p.sampleRate.has_value() || !p.channelMask.has_value() ||
1522 !p.format.has_value() || !p.flags.has_value(),
1523 "%s: stored mix port config is not fully specified: %s",
1524 __func__, p.toString().c_str());
1525 return p.ext.getTag() == Tag::mix &&
1526 isConfigEqualToPortConfig(config, p) &&
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001527 (!flags.has_value() || p.flags.value() == flags.value()) &&
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001528 p.ext.template get<Tag::mix>().handle == ioHandle; });
1529}
Mikhail Naganove93a0862023-03-15 17:06:59 -07001530
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001531void DeviceHalAidl::resetPatch(int32_t patchId) {
1532 if (auto it = mPatches.find(patchId); it != mPatches.end()) {
1533 mPatches.erase(it);
1534 TIME_CHECK();
1535 if (ndk::ScopedAStatus status = mModule->resetAudioPatch(patchId); !status.isOk()) {
1536 ALOGE("%s: error while resetting patch %d: %s",
1537 __func__, patchId, status.getDescription().c_str());
1538 }
1539 return;
1540 }
1541 ALOGE("%s: patch id %d not found", __func__, patchId);
1542}
1543
1544void DeviceHalAidl::resetPortConfig(int32_t portConfigId) {
1545 if (auto it = mPortConfigs.find(portConfigId); it != mPortConfigs.end()) {
1546 mPortConfigs.erase(it);
1547 TIME_CHECK();
1548 if (ndk::ScopedAStatus status = mModule->resetAudioPortConfig(portConfigId);
1549 !status.isOk()) {
1550 ALOGE("%s: error while resetting port config %d: %s",
1551 __func__, portConfigId, status.getDescription().c_str());
1552 }
1553 return;
1554 }
1555 ALOGE("%s: port config id %d not found", __func__, portConfigId);
1556}
1557
Mikhail Naganove93a0862023-03-15 17:06:59 -07001558void DeviceHalAidl::resetUnusedPatches() {
1559 // Since patches can be created independently of streams via 'createAudioPatch',
1560 // here we only clean up patches for released streams.
1561 for (auto it = mStreams.begin(); it != mStreams.end(); ) {
1562 if (auto streamSp = it->first.promote(); streamSp) {
1563 ++it;
1564 } else {
1565 resetPatch(it->second);
1566 it = mStreams.erase(it);
1567 }
1568 }
1569}
1570
1571void DeviceHalAidl::resetUnusedPatchesAndPortConfigs() {
1572 resetUnusedPatches();
1573 resetUnusedPortConfigs();
1574}
1575
1576void DeviceHalAidl::resetUnusedPortConfigs() {
1577 // The assumption is that port configs are used to create patches
1578 // (or to open streams, but that involves creation of patches, too). Thus,
1579 // orphaned port configs can and should be reset.
1580 std::set<int32_t> portConfigIds;
1581 std::transform(mPortConfigs.begin(), mPortConfigs.end(),
1582 std::inserter(portConfigIds, portConfigIds.end()),
1583 [](const auto& pcPair) { return pcPair.first; });
1584 for (const auto& p : mPatches) {
1585 for (int32_t id : p.second.sourcePortConfigIds) portConfigIds.erase(id);
1586 for (int32_t id : p.second.sinkPortConfigIds) portConfigIds.erase(id);
1587 }
jiabin9c07faf2023-04-26 22:00:44 +00001588 for (int32_t id : mInitialPortConfigIds) {
1589 portConfigIds.erase(id);
1590 }
Mikhail Naganove93a0862023-03-15 17:06:59 -07001591 for (int32_t id : portConfigIds) resetPortConfig(id);
1592}
1593
Mikhail Naganov289468a2023-03-29 10:06:15 -07001594status_t DeviceHalAidl::updateRoutes() {
1595 TIME_CHECK();
Mikhail Naganov289468a2023-03-29 10:06:15 -07001596 RETURN_STATUS_IF_ERROR(
Mikhail Naganovf83b9742023-04-24 13:06:04 -07001597 statusTFromBinderStatus(mModule->getAudioRoutes(&mRoutes)));
1598 ALOGW_IF(mRoutes.empty(), "%s: module %s returned an empty list of audio routes",
Mikhail Naganov289468a2023-03-29 10:06:15 -07001599 __func__, mInstance.c_str());
1600 mRoutingMatrix.clear();
Mikhail Naganovf83b9742023-04-24 13:06:04 -07001601 for (const auto& r : mRoutes) {
Mikhail Naganov289468a2023-03-29 10:06:15 -07001602 for (auto portId : r.sourcePortIds) {
1603 mRoutingMatrix.emplace(r.sinkPortId, portId);
1604 mRoutingMatrix.emplace(portId, r.sinkPortId);
1605 }
1606 }
1607 return OK;
1608}
1609
Mikhail Naganovdfd594e2023-02-08 16:59:41 -08001610void DeviceHalAidl::clearCallbacks(void* cookie) {
1611 std::lock_guard l(mLock);
1612 mCallbacks.erase(cookie);
1613}
1614
1615sp<StreamOutHalInterfaceCallback> DeviceHalAidl::getStreamOutCallback(void* cookie) {
1616 return getCallbackImpl(cookie, &Callbacks::out);
1617}
1618
1619void DeviceHalAidl::setStreamOutCallback(
1620 void* cookie, const sp<StreamOutHalInterfaceCallback>& cb) {
1621 setCallbackImpl(cookie, &Callbacks::out, cb);
1622}
1623
1624sp<StreamOutHalInterfaceEventCallback> DeviceHalAidl::getStreamOutEventCallback(
1625 void* cookie) {
1626 return getCallbackImpl(cookie, &Callbacks::event);
1627}
1628
1629void DeviceHalAidl::setStreamOutEventCallback(
1630 void* cookie, const sp<StreamOutHalInterfaceEventCallback>& cb) {
1631 setCallbackImpl(cookie, &Callbacks::event, cb);
1632}
1633
1634sp<StreamOutHalInterfaceLatencyModeCallback> DeviceHalAidl::getStreamOutLatencyModeCallback(
1635 void* cookie) {
1636 return getCallbackImpl(cookie, &Callbacks::latency);
1637}
1638
1639void DeviceHalAidl::setStreamOutLatencyModeCallback(
1640 void* cookie, const sp<StreamOutHalInterfaceLatencyModeCallback>& cb) {
1641 setCallbackImpl(cookie, &Callbacks::latency, cb);
1642}
1643
1644template<class C>
1645sp<C> DeviceHalAidl::getCallbackImpl(void* cookie, wp<C> DeviceHalAidl::Callbacks::* field) {
1646 std::lock_guard l(mLock);
1647 if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
1648 return ((it->second).*field).promote();
1649 }
1650 return nullptr;
1651}
1652template<class C>
1653void DeviceHalAidl::setCallbackImpl(
1654 void* cookie, wp<C> DeviceHalAidl::Callbacks::* field, const sp<C>& cb) {
1655 std::lock_guard l(mLock);
1656 if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
1657 (it->second).*field = cb;
1658 }
1659}
1660
Mikhail Naganov31d46652023-01-10 18:29:25 +00001661} // namespace android