blob: 0a131fa9583e5869f33360fc25a34a5b109fdf61 [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>
Mikhail Naganov5b1eed12023-01-25 11:29:11 -080021
Mikhail Naganovdfd594e2023-02-08 16:59:41 -080022#include <aidl/android/hardware/audio/core/BnStreamCallback.h>
23#include <aidl/android/hardware/audio/core/BnStreamOutEventCallback.h>
Mikhail Naganovfab697c2023-01-11 19:33:13 +000024#include <aidl/android/hardware/audio/core/StreamDescriptor.h>
Andy Hungab659d62024-09-24 20:51:07 -070025#include <android/binder_ibinder_platform.h>
Mikhail Naganovfab697c2023-01-11 19:33:13 +000026#include <error/expected_utils.h>
27#include <media/AidlConversionCppNdk.h>
Haofan Wangbf44e092024-07-07 15:29:38 -070028#include <media/AidlConversionNdk.h>
Mikhail Naganov25bc9a22023-04-21 18:48:16 -070029#include <media/AidlConversionNdkCpp.h>
Mikhail Naganovfab697c2023-01-11 19:33:13 +000030#include <media/AidlConversionUtil.h>
Mikhail Naganov31d46652023-01-10 18:29:25 +000031#include <mediautils/TimeCheck.h>
Mikhail Naganovae9063d2023-11-07 16:43:51 -080032#include <system/audio.h>
Andy Hungab659d62024-09-24 20:51:07 -070033#include <system/thread_defs.h>
34
Mikhail Naganov89a9f742023-01-30 12:33:18 -080035#include <Utils.h>
Mikhail Naganov31d46652023-01-10 18:29:25 +000036#include <utils/Log.h>
Shunkai Yao51202502022-12-12 06:11:46 +000037
Jaideep Sharma145313e2024-08-14 14:51:24 +053038#include "AidlUtils.h"
Mikhail Naganov31d46652023-01-10 18:29:25 +000039#include "DeviceHalAidl.h"
Mikhail Naganova82a69d2023-06-14 16:31:32 -070040#include "EffectHalAidl.h"
Mikhail Naganov31d46652023-01-10 18:29:25 +000041#include "StreamHalAidl.h"
42
Mikhail Naganovfab697c2023-01-11 19:33:13 +000043using aidl::android::aidl_utils::statusTFromBinderStatus;
Mikhail Naganovccc82112023-04-27 18:14:15 -070044using aidl::android::media::audio::common::Boolean;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -080045using aidl::android::media::audio::common::AudioConfig;
46using aidl::android::media::audio::common::AudioDevice;
Mikhail Naganov89a9f742023-01-30 12:33:18 -080047using aidl::android::media::audio::common::AudioDeviceType;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -080048using aidl::android::media::audio::common::AudioIoFlags;
Mikhail Naganovdfd594e2023-02-08 16:59:41 -080049using aidl::android::media::audio::common::AudioLatencyMode;
David Li9cf5e622023-03-21 00:51:10 +080050using aidl::android::media::audio::common::AudioMMapPolicy;
51using aidl::android::media::audio::common::AudioMMapPolicyInfo;
52using aidl::android::media::audio::common::AudioMMapPolicyType;
Mikhail Naganovfab697c2023-01-11 19:33:13 +000053using aidl::android::media::audio::common::AudioMode;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -080054using aidl::android::media::audio::common::AudioOutputFlags;
55using aidl::android::media::audio::common::AudioPort;
56using aidl::android::media::audio::common::AudioPortConfig;
David Li9cf5e622023-03-21 00:51:10 +080057using aidl::android::media::audio::common::AudioPortExt;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -080058using aidl::android::media::audio::common::AudioSource;
Mikhail Naganovfab697c2023-01-11 19:33:13 +000059using aidl::android::media::audio::common::Float;
David Li9cf5e622023-03-21 00:51:10 +080060using aidl::android::media::audio::common::Int;
61using aidl::android::media::audio::common::MicrophoneDynamicInfo;
62using aidl::android::media::audio::common::MicrophoneInfo;
Mikhail Naganove7a26ad2023-05-25 17:36:48 -070063using aidl::android::media::audio::IHalAdapterVendorExtension;
Mikhail Naganov6352e822023-03-09 18:22:36 -080064using aidl::android::hardware::audio::common::getFrameSizeInBytes;
65using aidl::android::hardware::audio::common::isBitPositionFlagSet;
David Li21289462024-04-17 01:09:23 +080066using aidl::android::hardware::audio::common::kDumpFromAudioServerArgument;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -080067using aidl::android::hardware::audio::common::RecordTrackMetadata;
Haofan Wangbf44e092024-07-07 15:29:38 -070068using aidl::android::hardware::audio::common::PlaybackTrackMetadata;
69using aidl::android::hardware::audio::common::SourceMetadata;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -070070using aidl::android::hardware::audio::core::sounddose::ISoundDose;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -080071using aidl::android::hardware::audio::core::AudioPatch;
Mikhail Naganov289468a2023-03-29 10:06:15 -070072using aidl::android::hardware::audio::core::AudioRoute;
Mikhail Naganovccc82112023-04-27 18:14:15 -070073using aidl::android::hardware::audio::core::IBluetooth;
74using aidl::android::hardware::audio::core::IBluetoothA2dp;
75using aidl::android::hardware::audio::core::IBluetoothLe;
Mikhail Naganovfab697c2023-01-11 19:33:13 +000076using aidl::android::hardware::audio::core::IModule;
77using aidl::android::hardware::audio::core::ITelephony;
Mikhail Naganove93a0862023-03-15 17:06:59 -070078using aidl::android::hardware::audio::core::ModuleDebug;
Mikhail Naganove7a26ad2023-05-25 17:36:48 -070079using aidl::android::hardware::audio::core::VendorParameter;
Mikhail Naganov31d46652023-01-10 18:29:25 +000080
Jaideep Sharma145313e2024-08-14 14:51:24 +053081#define RETURN_IF_MODULE_NOT_INIT(retVal) \
Mikhail Naganov3ecc9eb2024-12-06 11:34:26 -080082 if (!isModuleInitialized()) { \
Jaideep Sharma145313e2024-08-14 14:51:24 +053083 AUGMENT_LOG(E, "module not initialized"); \
84 return retVal; \
85 }
86
87#define RETURN_IF_TELEPHONY_NOT_INIT(retVal) \
Mikhail Naganov3ecc9eb2024-12-06 11:34:26 -080088 if (!isTelephonyInitialized()) { \
Jaideep Sharma145313e2024-08-14 14:51:24 +053089 AUGMENT_LOG(E, "telephony not initialized"); \
90 return retVal; \
91 }
92
Mikhail Naganov31d46652023-01-10 18:29:25 +000093namespace android {
94
Mikhail Naganov5b1eed12023-01-25 11:29:11 -080095namespace {
96
Mikhail Naganovf83b9742023-04-24 13:06:04 -070097// Note: these converters are for types defined in different AIDL files. Although these
98// AIDL files are copies of each other, however formally these are different types
99// thus we don't use a conversion via a parcelable.
100ConversionResult<media::AudioRoute> ndk2cpp_AudioRoute(const AudioRoute& ndk) {
101 media::AudioRoute cpp;
102 cpp.sourcePortIds.insert(
103 cpp.sourcePortIds.end(), ndk.sourcePortIds.begin(), ndk.sourcePortIds.end());
104 cpp.sinkPortId = ndk.sinkPortId;
105 cpp.isExclusive = ndk.isExclusive;
David Li9cf5e622023-03-21 00:51:10 +0800106 return cpp;
107}
108
Mikhail Naganov1fba38c2023-05-03 17:45:36 -0700109template<typename T>
110std::shared_ptr<T> retrieveSubInterface(const std::shared_ptr<IModule>& module,
111 ::ndk::ScopedAStatus (IModule::*getT)(std::shared_ptr<T>*)) {
112 if (module != nullptr) {
113 std::shared_ptr<T> instance;
114 if (auto status = (module.get()->*getT)(&instance); status.isOk()) {
115 return instance;
116 }
117 }
118 return nullptr;
119}
120
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800121} // namespace
122
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700123DeviceHalAidl::DeviceHalAidl(const std::string& instance, const std::shared_ptr<IModule>& module,
124 const std::shared_ptr<IHalAdapterVendorExtension>& vext)
Jaideep Sharma145313e2024-08-14 14:51:24 +0530125 : ConversionHelperAidl("DeviceHalAidl", instance),
126 mModule(module),
Jaideep Sharma145313e2024-08-14 14:51:24 +0530127 mTelephony(retrieveSubInterface<ITelephony>(module, &IModule::getTelephony)),
128 mBluetooth(retrieveSubInterface<IBluetooth>(module, &IModule::getBluetooth)),
129 mBluetoothA2dp(retrieveSubInterface<IBluetoothA2dp>(module, &IModule::getBluetoothA2dp)),
130 mBluetoothLe(retrieveSubInterface<IBluetoothLe>(module, &IModule::getBluetoothLe)),
131 mSoundDose(retrieveSubInterface<ISoundDose>(module, &IModule::getSoundDose)),
Mikhail Naganov3ecc9eb2024-12-06 11:34:26 -0800132 mVendorExt(vext),
Jaideep Sharma145313e2024-08-14 14:51:24 +0530133 mMapper(instance, module),
134 mMapperAccessor(mMapper, mLock) {}
Mikhail Naganov1fba38c2023-05-03 17:45:36 -0700135
Mikhail Naganovf83b9742023-04-24 13:06:04 -0700136status_t DeviceHalAidl::getAudioPorts(std::vector<media::audio::common::AudioPort> *ports) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700137 std::lock_guard l(mLock);
138 return mMapper.getAudioPorts(ports, ndk2cpp_AudioPort);
Mikhail Naganovf83b9742023-04-24 13:06:04 -0700139}
140
141status_t DeviceHalAidl::getAudioRoutes(std::vector<media::AudioRoute> *routes) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700142 std::lock_guard l(mLock);
143 return mMapper.getAudioRoutes(routes, ndk2cpp_AudioRoute);
Mikhail Naganovf83b9742023-04-24 13:06:04 -0700144}
145
Mikhail Naganov1fba38c2023-05-03 17:45:36 -0700146status_t DeviceHalAidl::getSupportedModes(std::vector<media::audio::common::AudioMode> *modes) {
Shunkai Yao35665b12024-08-21 00:30:54 +0000147 AUGMENT_LOG(D);
Mikhail Naganov1fba38c2023-05-03 17:45:36 -0700148 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530149 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
150 RETURN_IF_TELEPHONY_NOT_INIT(INVALID_OPERATION);
151
Mikhail Naganov1fba38c2023-05-03 17:45:36 -0700152 if (modes == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530153 AUGMENT_LOG(E, "uninitialized modes");
Mikhail Naganov1fba38c2023-05-03 17:45:36 -0700154 return BAD_VALUE;
155 }
Mikhail Naganov1fba38c2023-05-03 17:45:36 -0700156 std::vector<AudioMode> aidlModes;
Mikhail Naganov3ecc9eb2024-12-06 11:34:26 -0800157 {
158 std::lock_guard l(mLock);
159 RETURN_STATUS_IF_ERROR(
160 statusTFromBinderStatus(mTelephony->getSupportedAudioModes(&aidlModes)));
161 }
Mikhail Naganov1fba38c2023-05-03 17:45:36 -0700162 *modes = VALUE_OR_RETURN_STATUS(
163 ::aidl::android::convertContainer<std::vector<media::audio::common::AudioMode>>(
164 aidlModes, ndk2cpp_AudioMode));
165 return OK;
166}
167
Mikhail Naganov31d46652023-01-10 18:29:25 +0000168status_t DeviceHalAidl::getSupportedDevices(uint32_t*) {
169 // Obsolete.
170 return INVALID_OPERATION;
Shunkai Yao51202502022-12-12 06:11:46 +0000171}
172
173status_t DeviceHalAidl::initCheck() {
Shunkai Yao35665b12024-08-21 00:30:54 +0000174 AUGMENT_LOG(D);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800175 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530176 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700177 std::lock_guard l(mLock);
178 return mMapper.initialize();
Shunkai Yao51202502022-12-12 06:11:46 +0000179}
180
181status_t DeviceHalAidl::setVoiceVolume(float volume) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530182 AUGMENT_LOG(D, "volume %f", volume);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000183 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530184 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
185 RETURN_IF_TELEPHONY_NOT_INIT(INVALID_OPERATION);
186
187 ITelephony::TelecomConfig inConfig{.voiceVolume = Float{volume}}, outConfig;
Mikhail Naganov3ecc9eb2024-12-06 11:34:26 -0800188 {
189 std::lock_guard l(mLock);
190 RETURN_STATUS_IF_ERROR(
191 statusTFromBinderStatus(mTelephony->setTelecomConfig(inConfig, &outConfig)));
192 }
Jaideep Sharma145313e2024-08-14 14:51:24 +0530193 AUGMENT_LOG_IF(
194 W, outConfig.voiceVolume.has_value() && volume != outConfig.voiceVolume.value().value,
195 "the resulting voice volume %f is not the same as requested %f",
196 outConfig.voiceVolume.value().value, volume);
Mikhail Naganov1fba38c2023-05-03 17:45:36 -0700197 return OK;
Shunkai Yao51202502022-12-12 06:11:46 +0000198}
199
200status_t DeviceHalAidl::setMasterVolume(float volume) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530201 AUGMENT_LOG(D, "volume %f", volume);
202
Mikhail Naganov31d46652023-01-10 18:29:25 +0000203 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530204 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganov3ecc9eb2024-12-06 11:34:26 -0800205 std::lock_guard l(mLock);
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000206 return statusTFromBinderStatus(mModule->setMasterVolume(volume));
Shunkai Yao51202502022-12-12 06:11:46 +0000207}
208
209status_t DeviceHalAidl::getMasterVolume(float *volume) {
Shunkai Yao35665b12024-08-21 00:30:54 +0000210 AUGMENT_LOG(D);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000211 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530212 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700213 if (volume == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530214 AUGMENT_LOG(E, "uninitialized volumes");
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700215 return BAD_VALUE;
216 }
Mikhail Naganov3ecc9eb2024-12-06 11:34:26 -0800217 std::lock_guard l(mLock);
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000218 return statusTFromBinderStatus(mModule->getMasterVolume(volume));
Shunkai Yao51202502022-12-12 06:11:46 +0000219}
220
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000221status_t DeviceHalAidl::setMode(audio_mode_t mode) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530222 AUGMENT_LOG(D, "mode %d", mode);
223
Mikhail Naganov31d46652023-01-10 18:29:25 +0000224 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530225 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000226 AudioMode audioMode = VALUE_OR_FATAL(::aidl::android::legacy2aidl_audio_mode_t_AudioMode(mode));
Mikhail Naganov3ecc9eb2024-12-06 11:34:26 -0800227 std::lock_guard l(mLock);
Mikhail Naganov1fba38c2023-05-03 17:45:36 -0700228 if (mTelephony != nullptr) {
229 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mTelephony->switchAudioMode(audioMode)));
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000230 }
231 return statusTFromBinderStatus(mModule->updateAudioMode(audioMode));
Shunkai Yao51202502022-12-12 06:11:46 +0000232}
233
234status_t DeviceHalAidl::setMicMute(bool state) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530235 AUGMENT_LOG(D, "mute %d", state);
236
Mikhail Naganov31d46652023-01-10 18:29:25 +0000237 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530238 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganov3ecc9eb2024-12-06 11:34:26 -0800239 std::lock_guard l(mLock);
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000240 return statusTFromBinderStatus(mModule->setMicMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000241}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000242
Shunkai Yao51202502022-12-12 06:11:46 +0000243status_t DeviceHalAidl::getMicMute(bool *state) {
Shunkai Yao35665b12024-08-21 00:30:54 +0000244 AUGMENT_LOG(D);
Jaideep Sharma145313e2024-08-14 14:51:24 +0530245
Mikhail Naganov31d46652023-01-10 18:29:25 +0000246 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530247 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700248 if (state == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530249 AUGMENT_LOG(E, "uninitialized mute state");
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700250 return BAD_VALUE;
251 }
Mikhail Naganov3ecc9eb2024-12-06 11:34:26 -0800252 std::lock_guard l(mLock);
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000253 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) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530257 AUGMENT_LOG(D, "mute %d", state);
258
Mikhail Naganov31d46652023-01-10 18:29:25 +0000259 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530260 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganov3ecc9eb2024-12-06 11:34:26 -0800261 std::lock_guard l(mLock);
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000262 return statusTFromBinderStatus(mModule->setMasterMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000263}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000264
Shunkai Yao51202502022-12-12 06:11:46 +0000265status_t DeviceHalAidl::getMasterMute(bool *state) {
Shunkai Yao35665b12024-08-21 00:30:54 +0000266 AUGMENT_LOG(D);
Jaideep Sharma145313e2024-08-14 14:51:24 +0530267
Mikhail Naganov31d46652023-01-10 18:29:25 +0000268 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530269 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700270 if (state == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530271 AUGMENT_LOG(E, "uninitialized mute state");
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700272 return BAD_VALUE;
273 }
Mikhail Naganov3ecc9eb2024-12-06 11:34:26 -0800274 std::lock_guard l(mLock);
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000275 return statusTFromBinderStatus(mModule->getMasterMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000276}
277
Mikhail Naganovccc82112023-04-27 18:14:15 -0700278status_t DeviceHalAidl::setParameters(const String8& kvPairs) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700279 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530280 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovccc82112023-04-27 18:14:15 -0700281 AudioParameter parameters(kvPairs);
Jaideep Sharma145313e2024-08-14 14:51:24 +0530282 AUGMENT_LOG(D, "parameters: \"%s\"", parameters.toString().c_str());
Mikhail Naganovccc82112023-04-27 18:14:15 -0700283
284 if (status_t status = filterAndUpdateBtA2dpParameters(parameters); status != OK) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530285 AUGMENT_LOG(W, "filterAndUpdateBtA2dpParameters failed: %d", status);
Mikhail Naganovccc82112023-04-27 18:14:15 -0700286 }
287 if (status_t status = filterAndUpdateBtHfpParameters(parameters); status != OK) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530288 AUGMENT_LOG(W, "filterAndUpdateBtHfpParameters failed: %d", status);
Mikhail Naganovccc82112023-04-27 18:14:15 -0700289 }
290 if (status_t status = filterAndUpdateBtLeParameters(parameters); status != OK) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530291 AUGMENT_LOG(W, "filterAndUpdateBtLeParameters failed: %d", status);
Mikhail Naganovccc82112023-04-27 18:14:15 -0700292 }
293 if (status_t status = filterAndUpdateBtScoParameters(parameters); status != OK) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530294 AUGMENT_LOG(W, "filterAndUpdateBtScoParameters failed: %d", status);
Mikhail Naganovccc82112023-04-27 18:14:15 -0700295 }
Mikhail Naganove92c34b2023-05-31 14:24:48 -0700296 if (status_t status = filterAndUpdateScreenParameters(parameters); status != OK) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530297 AUGMENT_LOG(W, "filterAndUpdateScreenParameters failed: %d", status);
Mikhail Naganove92c34b2023-05-31 14:24:48 -0700298 }
Mikhail Naganovb9a81312023-07-18 13:55:34 -0700299 if (status_t status = filterAndUpdateTelephonyParameters(parameters); status != OK) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530300 AUGMENT_LOG(W, "filterAndUpdateTelephonyParameters failed: %d", status);
Mikhail Naganovb9a81312023-07-18 13:55:34 -0700301 }
Mikhail Naganov3ecc9eb2024-12-06 11:34:26 -0800302 std::lock_guard l(mLock);
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700303 return parseAndSetVendorParameters(mVendorExt, mModule, parameters);
Shunkai Yao51202502022-12-12 06:11:46 +0000304}
305
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700306status_t DeviceHalAidl::getParameters(const String8& keys, String8 *values) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530307 AUGMENT_LOG(D, "keys: \"%s\"", keys.c_str());
308
Mikhail Naganov31d46652023-01-10 18:29:25 +0000309 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530310 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700311 if (values == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530312 AUGMENT_LOG(E, "invalid values");
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700313 return BAD_VALUE;
314 }
315 AudioParameter parameterKeys(keys), result;
316 if (status_t status = filterAndRetrieveBtA2dpParameters(parameterKeys, &result); status != OK) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530317 AUGMENT_LOG(W, "filterAndRetrieveBtA2dpParameters failed: %d", status);
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700318 }
Eric Laurent7e3c0832023-11-30 15:04:50 +0100319 if (status_t status = filterAndRetrieveBtLeParameters(parameterKeys, &result); status != OK) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530320 AUGMENT_LOG(W, "filterAndRetrieveBtLeParameters failed: %d", status);
Eric Laurent7e3c0832023-11-30 15:04:50 +0100321 }
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700322 *values = result.toString();
Mikhail Naganov3ecc9eb2024-12-06 11:34:26 -0800323 std::lock_guard l(mLock);
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700324 return parseAndGetVendorParameters(mVendorExt, mModule, parameterKeys, values);
Shunkai Yao51202502022-12-12 06:11:46 +0000325}
326
Mikhail Naganovd5b643f2024-02-15 11:51:26 -0800327status_t DeviceHalAidl::getInputBufferSize(struct audio_config* config, size_t* size) {
Shunkai Yao35665b12024-08-21 00:30:54 +0000328 AUGMENT_LOG(D);
Jaideep Sharma145313e2024-08-14 14:51:24 +0530329
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800330 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530331 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700332 if (config == nullptr || size == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530333 AUGMENT_LOG(E, "invalid config or size");
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700334 return BAD_VALUE;
335 }
Mikhail Naganovd5b643f2024-02-15 11:51:26 -0800336 constexpr bool isInput = true;
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800337 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
Mikhail Naganovd5b643f2024-02-15 11:51:26 -0800338 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, isInput));
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800339 AudioDevice aidlDevice;
340 aidlDevice.type.type = AudioDeviceType::IN_DEFAULT;
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800341 AudioSource aidlSource = AudioSource::DEFAULT;
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800342 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::input>(0);
343 AudioPortConfig mixPortConfig;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700344 Hal2AidlMapper::Cleanups cleanups(mMapperAccessor);
Mikhail Naganove93a0862023-03-15 17:06:59 -0700345 AudioPatch aidlPatch;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700346 {
347 std::lock_guard l(mLock);
348 RETURN_STATUS_IF_ERROR(mMapper.prepareToOpenStream(
349 0 /*handle*/, aidlDevice, aidlFlags, aidlSource,
350 &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
351 }
Mikhail Naganovd5b643f2024-02-15 11:51:26 -0800352 *config = VALUE_OR_RETURN_STATUS(
353 ::aidl::android::aidl2legacy_AudioConfig_audio_config_t(aidlConfig, isInput));
354 if (mixPortConfig.id == 0) return BAD_VALUE; // HAL suggests a different config.
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800355 *size = aidlConfig.frameCount *
356 getFrameSizeInBytes(aidlConfig.base.format, aidlConfig.base.channelMask);
357 // Do not disarm cleanups to release temporary port configs.
358 return OK;
359}
360
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800361namespace {
362
363class StreamCallbackBase {
364 protected:
365 explicit StreamCallbackBase(const sp<CallbackBroker>& broker) : mBroker(broker) {}
366 public:
367 void* getCookie() const { return mCookie; }
368 void setCookie(void* cookie) { mCookie = cookie; }
369 sp<CallbackBroker> getBroker() const {
370 if (void* cookie = mCookie; cookie != nullptr) return mBroker.promote();
371 return nullptr;
372 }
373 private:
374 const wp<CallbackBroker> mBroker;
375 std::atomic<void*> mCookie;
376};
377
378template<class C>
379class StreamCallbackBaseHelper {
380 protected:
381 explicit StreamCallbackBaseHelper(const StreamCallbackBase& base) : mBase(base) {}
382 sp<C> getCb(const sp<CallbackBroker>& broker, void* cookie);
383 using CbRef = const sp<C>&;
384 ndk::ScopedAStatus runCb(const std::function<void(CbRef cb)>& f) {
385 if (auto cb = getCb(mBase.getBroker(), mBase.getCookie()); cb != nullptr) f(cb);
386 return ndk::ScopedAStatus::ok();
387 }
388 private:
389 const StreamCallbackBase& mBase;
390};
391
392template<>
393sp<StreamOutHalInterfaceCallback> StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>::getCb(
394 const sp<CallbackBroker>& broker, void* cookie) {
395 if (broker != nullptr) return broker->getStreamOutCallback(cookie);
396 return nullptr;
397}
398
399template<>
400sp<StreamOutHalInterfaceEventCallback>
401StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>::getCb(
402 const sp<CallbackBroker>& broker, void* cookie) {
403 if (broker != nullptr) return broker->getStreamOutEventCallback(cookie);
404 return nullptr;
405}
406
407template<>
408sp<StreamOutHalInterfaceLatencyModeCallback>
409StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>::getCb(
410 const sp<CallbackBroker>& broker, void* cookie) {
411 if (broker != nullptr) return broker->getStreamOutLatencyModeCallback(cookie);
412 return nullptr;
413}
414
415/*
416Note on the callback ownership.
417
418In the Binder ownership model, the server implementation is kept alive
419as long as there is any client (proxy object) alive. This is done by
420incrementing the refcount of the server-side object by the Binder framework.
421When it detects that the last client is gone, it decrements the refcount back.
422
423Thus, it is not needed to keep any references to StreamCallback on our
424side (after we have sent an instance to the client), because we are
425the server-side. The callback object will be kept alive as long as the HAL server
426holds a strong ref to IStreamCallback proxy.
427*/
428
429class OutputStreamCallbackAidl : public StreamCallbackBase,
430 public StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>,
431 public ::aidl::android::hardware::audio::core::BnStreamCallback {
432 public:
433 explicit OutputStreamCallbackAidl(const sp<CallbackBroker>& broker)
434 : StreamCallbackBase(broker),
435 StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>(
436 *static_cast<StreamCallbackBase*>(this)) {}
437 ndk::ScopedAStatus onTransferReady() override {
438 return runCb([](CbRef cb) { cb->onWriteReady(); });
439 }
440 ndk::ScopedAStatus onError() override {
Mikhail Naganovbf203ce2024-05-23 16:27:59 -0700441 return runCb([](CbRef cb) { cb->onError(true /*isHardError*/); });
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800442 }
443 ndk::ScopedAStatus onDrainReady() override {
444 return runCb([](CbRef cb) { cb->onDrainReady(); });
445 }
446};
447
448class OutputStreamEventCallbackAidl :
449 public StreamCallbackBase,
450 public StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>,
451 public StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>,
452 public ::aidl::android::hardware::audio::core::BnStreamOutEventCallback {
453 public:
454 explicit OutputStreamEventCallbackAidl(const sp<CallbackBroker>& broker)
455 : StreamCallbackBase(broker),
456 StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>(
457 *static_cast<StreamCallbackBase*>(this)),
458 StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>(
459 *static_cast<StreamCallbackBase*>(this)) {}
Ryan Prichard78c5e452024-02-08 16:16:57 -0800460 ndk::ScopedAStatus onCodecFormatChanged(const std::vector<uint8_t>& halMetadata) override {
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800461 return StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>::runCb(
462 [&halMetadata](auto cb) { cb->onCodecFormatChanged(halMetadata); });
463 }
464 ndk::ScopedAStatus onRecommendedLatencyModeChanged(
465 const std::vector<AudioLatencyMode>& in_modes) override {
466 auto halModes = VALUE_OR_FATAL(
467 ::aidl::android::convertContainer<std::vector<audio_latency_mode_t>>(
468 in_modes,
469 ::aidl::android::aidl2legacy_AudioLatencyMode_audio_latency_mode_t));
470 return StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>::runCb(
471 [&halModes](auto cb) { cb->onRecommendedLatencyModeChanged(halModes); });
472 }
473};
474
475} // namespace
476
Mikhail Naganov31d46652023-01-10 18:29:25 +0000477status_t DeviceHalAidl::openOutputStream(
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800478 audio_io_handle_t handle, audio_devices_t devices,
479 audio_output_flags_t flags, struct audio_config* config,
480 const char* address,
Haofan Wangbf44e092024-07-07 15:29:38 -0700481 sp<StreamOutHalInterface>* outStream,
482 const std::vector<playback_track_metadata_v7_t>& sourceMetadata) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530483 AUGMENT_LOG(D, "handle: %d devices %0x flags %0x", handle, devices, flags);
Shunkai Yao35665b12024-08-21 00:30:54 +0000484
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700485 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530486 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700487 if (outStream == nullptr || config == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530488 AUGMENT_LOG(E, "invalid outStream or config");
Mikhail Naganov31d46652023-01-10 18:29:25 +0000489 return BAD_VALUE;
490 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700491 constexpr bool isInput = false;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800492 int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
493 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(handle));
494 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700495 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, isInput));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800496 AudioDevice aidlDevice = VALUE_OR_RETURN_STATUS(
497 ::aidl::android::legacy2aidl_audio_device_AudioDevice(devices, address));
498 int32_t aidlOutputFlags = VALUE_OR_RETURN_STATUS(
499 ::aidl::android::legacy2aidl_audio_output_flags_t_int32_t_mask(flags));
Haofan Wangbf44e092024-07-07 15:29:38 -0700500 SourceMetadata aidlMetadata = VALUE_OR_RETURN_STATUS(
Haofan Wang9b390862024-08-22 17:44:59 +0000501 ::aidl::android::legacy2aidl_playback_track_metadata_v7_SourceMetadata(sourceMetadata));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800502 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::output>(aidlOutputFlags);
503 AudioPortConfig mixPortConfig;
Mikhail Naganove93a0862023-03-15 17:06:59 -0700504 AudioPatch aidlPatch;
Haofan Wangbf44e092024-07-07 15:29:38 -0700505
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700506 Hal2AidlMapper::Cleanups cleanups(mMapperAccessor);
507 {
508 std::lock_guard l(mLock);
509 RETURN_STATUS_IF_ERROR(mMapper.prepareToOpenStream(aidlHandle, aidlDevice, aidlFlags,
510 AudioSource::SYS_RESERVED_INVALID /*only needed for input*/,
511 &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
512 }
513 *config = VALUE_OR_RETURN_STATUS(
514 ::aidl::android::aidl2legacy_AudioConfig_audio_config_t(aidlConfig, isInput));
Mikhail Naganovca92a5c2023-12-07 14:00:48 -0800515 if (mixPortConfig.id == 0) return BAD_VALUE; // HAL suggests a different config.
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800516 ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamArguments args;
517 args.portConfigId = mixPortConfig.id;
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800518 const bool isOffload = isBitPositionFlagSet(
519 aidlOutputFlags, AudioOutputFlags::COMPRESS_OFFLOAD);
Kuowei Li3b9a69d2024-06-07 17:54:32 +0800520 const bool isHwAvSync = isBitPositionFlagSet(
521 aidlOutputFlags, AudioOutputFlags::HW_AV_SYNC);
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800522 std::shared_ptr<OutputStreamCallbackAidl> streamCb;
523 if (isOffload) {
524 streamCb = ndk::SharedRefBase::make<OutputStreamCallbackAidl>(this);
Andy Hungab659d62024-09-24 20:51:07 -0700525 ndk::SpAIBinder binder = streamCb->asBinder();
526 AIBinder_setMinSchedulerPolicy(binder.get(), SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
527 AIBinder_setInheritRt(binder.get(), true);
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800528 }
529 auto eventCb = ndk::SharedRefBase::make<OutputStreamEventCallbackAidl>(this);
Andy Hungab659d62024-09-24 20:51:07 -0700530 ndk::SpAIBinder binder = eventCb->asBinder();
531 AIBinder_setMinSchedulerPolicy(binder.get(), SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
532 AIBinder_setInheritRt(binder.get(), true);
533
Kuowei Li3b9a69d2024-06-07 17:54:32 +0800534 if (isOffload || isHwAvSync) {
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800535 args.offloadInfo = aidlConfig.offloadInfo;
Kuowei Li3b9a69d2024-06-07 17:54:32 +0800536 }
537 if (isOffload) {
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800538 args.callback = streamCb;
539 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800540 args.bufferSizeFrames = aidlConfig.frameCount;
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800541 args.eventCallback = eventCb;
Haofan Wangbf44e092024-07-07 15:29:38 -0700542 args.sourceMetadata = aidlMetadata;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800543 ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamReturn ret;
Mikhail Naganov3ecc9eb2024-12-06 11:34:26 -0800544 {
545 std::lock_guard l(mLock);
546 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openOutputStream(args, &ret)));
547 }
Jaideep Sharma145313e2024-08-14 14:51:24 +0530548 StreamContextAidl context(ret.desc, isOffload, aidlHandle);
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800549 if (!context.isValid()) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530550 AUGMENT_LOG(E, "Failed to created a valid stream context from the descriptor: %s",
551 ret.desc.toString().c_str());
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800552 return NO_INIT;
553 }
Mikhail Naganov8065bfd2024-03-25 14:59:49 -0700554 auto stream = sp<StreamOutHalAidl>::make(*config, std::move(context), aidlPatch.latenciesMs[0],
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700555 std::move(ret.stream), mVendorExt, this /*callbackBroker*/);
Mikhail Naganov8065bfd2024-03-25 14:59:49 -0700556 *outStream = stream;
557 /* StreamOutHalInterface* */ void* cbCookie = (*outStream).get();
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800558 {
Mikhail Naganov22578412024-08-16 16:50:34 -0700559 std::lock_guard l(mCallbacksLock);
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800560 mCallbacks.emplace(cbCookie, Callbacks{});
Mikhail Naganov22578412024-08-16 16:50:34 -0700561 }
562 {
563 std::lock_guard l(mLock);
Mikhail Naganov78f7f9a2023-11-16 15:49:23 -0800564 mMapper.addStream(*outStream, mixPortConfig.id, aidlPatch.id);
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800565 }
Mikhail Naganov8065bfd2024-03-25 14:59:49 -0700566 if (streamCb) {
567 streamCb->setCookie(cbCookie);
568 // Although StreamOutHalAidl implements StreamOutHalInterfaceCallback,
569 // we always go via the CallbackBroker for consistency.
570 setStreamOutCallback(cbCookie, stream);
571 }
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800572 eventCb->setCookie(cbCookie);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800573 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000574 return OK;
575}
576
Mikhail Naganov31d46652023-01-10 18:29:25 +0000577status_t DeviceHalAidl::openInputStream(
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800578 audio_io_handle_t handle, audio_devices_t devices,
579 struct audio_config* config, audio_input_flags_t flags,
580 const char* address, audio_source_t source,
581 audio_devices_t outputDevice, const char* outputDeviceAddress,
Mikhail Naganov31d46652023-01-10 18:29:25 +0000582 sp<StreamInHalInterface>* inStream) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530583 AUGMENT_LOG(D, "handle: %d devices %0x flags %0x", handle, devices, flags);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700584 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530585 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700586 if (inStream == nullptr || config == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530587 AUGMENT_LOG(E, "invalid inStream or config");
Mikhail Naganov31d46652023-01-10 18:29:25 +0000588 return BAD_VALUE;
589 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700590 constexpr bool isInput = true;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800591 int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
592 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(handle));
593 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700594 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, isInput));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800595 AudioDevice aidlDevice = VALUE_OR_RETURN_STATUS(
596 ::aidl::android::legacy2aidl_audio_device_AudioDevice(devices, address));
597 int32_t aidlInputFlags = VALUE_OR_RETURN_STATUS(
598 ::aidl::android::legacy2aidl_audio_input_flags_t_int32_t_mask(flags));
599 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::input>(aidlInputFlags);
600 AudioSource aidlSource = VALUE_OR_RETURN_STATUS(
601 ::aidl::android::legacy2aidl_audio_source_t_AudioSource(source));
602 AudioPortConfig mixPortConfig;
Mikhail Naganove93a0862023-03-15 17:06:59 -0700603 AudioPatch aidlPatch;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700604 Hal2AidlMapper::Cleanups cleanups(mMapperAccessor);
605 {
606 std::lock_guard l(mLock);
607 RETURN_STATUS_IF_ERROR(mMapper.prepareToOpenStream(
608 aidlHandle, aidlDevice, aidlFlags, aidlSource,
609 &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
610 }
611 *config = VALUE_OR_RETURN_STATUS(
612 ::aidl::android::aidl2legacy_AudioConfig_audio_config_t(aidlConfig, isInput));
Mikhail Naganovca92a5c2023-12-07 14:00:48 -0800613 if (mixPortConfig.id == 0) return BAD_VALUE; // HAL suggests a different config.
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800614 ::aidl::android::hardware::audio::core::IModule::OpenInputStreamArguments args;
615 args.portConfigId = mixPortConfig.id;
616 RecordTrackMetadata aidlTrackMetadata{
617 .source = aidlSource, .gain = 1, .channelMask = aidlConfig.base.channelMask };
618 if (outputDevice != AUDIO_DEVICE_NONE) {
619 aidlTrackMetadata.destinationDevice = VALUE_OR_RETURN_STATUS(
620 ::aidl::android::legacy2aidl_audio_device_AudioDevice(
621 outputDevice, outputDeviceAddress));
622 }
623 args.sinkMetadata.tracks.push_back(std::move(aidlTrackMetadata));
624 args.bufferSizeFrames = aidlConfig.frameCount;
625 ::aidl::android::hardware::audio::core::IModule::OpenInputStreamReturn ret;
Mikhail Naganov3ecc9eb2024-12-06 11:34:26 -0800626 {
627 std::lock_guard l(mLock);
628 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openInputStream(args, &ret)));
629 }
Jaideep Sharma145313e2024-08-14 14:51:24 +0530630 StreamContextAidl context(ret.desc, false /*isAsynchronous*/, aidlHandle);
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800631 if (!context.isValid()) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530632 AUGMENT_LOG(E, "Failed to created a valid stream context from the descriptor: %s",
633 ret.desc.toString().c_str());
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800634 return NO_INIT;
635 }
Mikhail Naganove93a0862023-03-15 17:06:59 -0700636 *inStream = sp<StreamInHalAidl>::make(*config, std::move(context), aidlPatch.latenciesMs[0],
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700637 std::move(ret.stream), mVendorExt, this /*micInfoProvider*/);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700638 {
639 std::lock_guard l(mLock);
Mikhail Naganov78f7f9a2023-11-16 15:49:23 -0800640 mMapper.addStream(*inStream, mixPortConfig.id, aidlPatch.id);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700641 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800642 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000643 return OK;
644}
645
646status_t DeviceHalAidl::supportsAudioPatches(bool* supportsPatches) {
Shunkai Yao35665b12024-08-21 00:30:54 +0000647 AUGMENT_LOG(V);
Jaideep Sharma145313e2024-08-14 14:51:24 +0530648 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700649 if (supportsPatches == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530650 AUGMENT_LOG(E, "uninitialized supportsPatches");
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700651 return BAD_VALUE;
652 }
Shunkai Yao51202502022-12-12 06:11:46 +0000653 *supportsPatches = true;
654 return OK;
655}
656
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800657status_t DeviceHalAidl::createAudioPatch(unsigned int num_sources,
658 const struct audio_port_config* sources,
659 unsigned int num_sinks,
660 const struct audio_port_config* sinks,
661 audio_patch_handle_t* patch) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530662 AUGMENT_LOG(D, "sources: %d sinks %d", num_sources, num_sinks);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000663 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530664 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
665 if (num_sinks > AUDIO_PATCH_PORTS_MAX || num_sources > AUDIO_PATCH_PORTS_MAX) {
666 AUGMENT_LOG(E, "invalid sources %d or sinks %d ", num_sources, num_sinks);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800667 return BAD_VALUE;
668 }
Jaideep Sharma145313e2024-08-14 14:51:24 +0530669
670 if (sources == nullptr || sinks == nullptr || patch == nullptr) {
671 AUGMENT_LOG(E, "uninitialized sources %d or sinks %d or patches %d", (sources == nullptr),
672 (sinks == nullptr), (patch == nullptr));
673 return BAD_VALUE;
674 }
675
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800676 // When the patch handle (*patch) is AUDIO_PATCH_HANDLE_NONE, it means
677 // the framework wants to create a new patch. The handle has to be generated
678 // by the HAL. Since handles generated this way can only be unique within
679 // a HAL module, the framework generates a globally unique handle, and maps
680 // it on the <HAL module, patch handle> pair.
681 // When the patch handle is set, it meant the framework intends to update
682 // an existing patch.
683 //
684 // This behavior corresponds to HAL module behavior, with the only difference
685 // that the HAL module uses `int32_t` for patch IDs. The following assert ensures
686 // that both the framework and the HAL use the same value for "no ID":
687 static_assert(AUDIO_PATCH_HANDLE_NONE == 0);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800688
689 // Upon conversion, mix port configs contain audio configuration, while
690 // device port configs contain device address. This data is used to find
691 // or create HAL configs.
692 std::vector<AudioPortConfig> aidlSources, aidlSinks;
693 for (unsigned int i = 0; i < num_sources; ++i) {
694 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
695 sources[i].role, sources[i].type)) ==
696 ::aidl::android::AudioPortDirection::INPUT;
697 aidlSources.push_back(VALUE_OR_RETURN_STATUS(
698 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
699 sources[i], isInput, 0)));
700 }
701 for (unsigned int i = 0; i < num_sinks; ++i) {
702 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
703 sinks[i].role, sinks[i].type)) ==
704 ::aidl::android::AudioPortDirection::INPUT;
705 aidlSinks.push_back(VALUE_OR_RETURN_STATUS(
706 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
707 sinks[i], isInput, 0)));
708 }
Mikhail Naganov6b5da722024-03-14 12:59:32 -0700709 int32_t aidlPatchId = static_cast<int32_t>(*patch);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700710 Hal2AidlMapper::Cleanups cleanups(mMapperAccessor);
711 {
712 std::lock_guard l(mLock);
Mikhail Naganov6b5da722024-03-14 12:59:32 -0700713 // Check for patches that only exist for the framework, or have different HAL patch ID.
714 if (int32_t aidlHalPatchId = mMapper.findFwkPatch(aidlPatchId); aidlHalPatchId != 0) {
715 if (aidlHalPatchId == aidlPatchId) {
716 // This patch was previously released by the HAL. Thus we need to pass '0'
717 // to the HAL to obtain a new patch.
718 int32_t newAidlPatchId = 0;
719 RETURN_STATUS_IF_ERROR(mMapper.createOrUpdatePatch(
720 aidlSources, aidlSinks, &newAidlPatchId, &cleanups));
721 mMapper.updateFwkPatch(aidlPatchId, newAidlPatchId);
722 } else {
723 RETURN_STATUS_IF_ERROR(mMapper.createOrUpdatePatch(
724 aidlSources, aidlSinks, &aidlHalPatchId, &cleanups));
725 }
726 } else {
727 RETURN_STATUS_IF_ERROR(mMapper.createOrUpdatePatch(
728 aidlSources, aidlSinks, &aidlPatchId, &cleanups));
729 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800730 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700731 *patch = static_cast<audio_patch_handle_t>(aidlPatchId);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800732 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000733 return OK;
734}
735
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800736status_t DeviceHalAidl::releaseAudioPatch(audio_patch_handle_t patch) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530737 AUGMENT_LOG(D, "patch: %d", patch);
738
Mikhail Naganov31d46652023-01-10 18:29:25 +0000739 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530740 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800741 static_assert(AUDIO_PATCH_HANDLE_NONE == 0);
742 if (patch == AUDIO_PATCH_HANDLE_NONE) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800743 return BAD_VALUE;
744 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700745 std::lock_guard l(mLock);
Mikhail Naganov6b5da722024-03-14 12:59:32 -0700746 // Check for patches that only exist for the framework, or have different HAL patch ID.
747 int32_t aidlPatchId = static_cast<int32_t>(patch);
748 if (int32_t aidlHalPatchId = mMapper.findFwkPatch(aidlPatchId); aidlHalPatchId != 0) {
749 if (aidlHalPatchId == aidlPatchId) {
750 // This patch was previously released by the HAL, just need to finish its removal.
751 mMapper.eraseFwkPatch(aidlPatchId);
752 return OK;
753 } else {
754 // This patch has a HAL patch ID which is different
755 aidlPatchId = aidlHalPatchId;
756 }
757 }
758 RETURN_STATUS_IF_ERROR(mMapper.releaseAudioPatch(aidlPatchId));
Shunkai Yao51202502022-12-12 06:11:46 +0000759 return OK;
760}
761
Mikhail Naganove93a0862023-03-15 17:06:59 -0700762status_t DeviceHalAidl::getAudioPort(struct audio_port* port) {
Shunkai Yao35665b12024-08-21 00:30:54 +0000763 AUGMENT_LOG(V);
Jaideep Sharma145313e2024-08-14 14:51:24 +0530764 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganove93a0862023-03-15 17:06:59 -0700765 if (port == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530766 AUGMENT_LOG(E, "port not initialized");
Mikhail Naganove93a0862023-03-15 17:06:59 -0700767 return BAD_VALUE;
768 }
769 audio_port_v7 portV7;
770 audio_populate_audio_port_v7(port, &portV7);
771 RETURN_STATUS_IF_ERROR(getAudioPort(&portV7));
772 return audio_populate_audio_port(&portV7, port) ? OK : BAD_VALUE;
773}
774
775status_t DeviceHalAidl::getAudioPort(struct audio_port_v7 *port) {
Shunkai Yao35665b12024-08-21 00:30:54 +0000776 AUGMENT_LOG(D);
Jaideep Sharma145313e2024-08-14 14:51:24 +0530777
Mikhail Naganove93a0862023-03-15 17:06:59 -0700778 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530779 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganove93a0862023-03-15 17:06:59 -0700780 if (port == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530781 AUGMENT_LOG(E, "port not initialized");
Mikhail Naganove93a0862023-03-15 17:06:59 -0700782 return BAD_VALUE;
783 }
784 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(port->role, port->type)) ==
785 ::aidl::android::AudioPortDirection::INPUT;
786 auto aidlPort = VALUE_OR_RETURN_STATUS(
787 ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
788 if (aidlPort.ext.getTag() != AudioPortExt::device) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530789 AUGMENT_LOG(E, "provided port is not a device port %s", aidlPort.toString().c_str());
Mikhail Naganove93a0862023-03-15 17:06:59 -0700790 return BAD_VALUE;
791 }
792 const auto& matchDevice = aidlPort.ext.get<AudioPortExt::device>().device;
793 // It seems that we don't have to call HAL since all valid ports have been added either
794 // during initialization, or while handling connection of an external device.
Mikhail Naganove93a0862023-03-15 17:06:59 -0700795 const int32_t fwkId = aidlPort.id;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700796 {
797 std::lock_guard l(mLock);
798 RETURN_STATUS_IF_ERROR(mMapper.getAudioPortCached(matchDevice, &aidlPort));
799 }
Mikhail Naganove93a0862023-03-15 17:06:59 -0700800 aidlPort.id = fwkId;
801 *port = VALUE_OR_RETURN_STATUS(::aidl::android::aidl2legacy_AudioPort_audio_port_v7(
802 aidlPort, isInput));
803 return OK;
804}
805
jiabin12537fc2023-10-12 17:56:08 +0000806status_t DeviceHalAidl::getAudioMixPort(const struct audio_port_v7 *devicePort,
807 struct audio_port_v7 *mixPort) {
Shunkai Yao35665b12024-08-21 00:30:54 +0000808 AUGMENT_LOG(D);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700809 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530810 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
811
812 if (devicePort == nullptr || mixPort == nullptr || devicePort->type != AUDIO_PORT_TYPE_DEVICE ||
813 mixPort->type != AUDIO_PORT_TYPE_MIX) {
814 AUGMENT_LOG(E, "invalid device or mix port");
jiabin12537fc2023-10-12 17:56:08 +0000815 return BAD_VALUE;
816 }
817 const int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
818 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(mixPort->ext.mix.handle));
jiabin12537fc2023-10-12 17:56:08 +0000819 AudioPort port;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700820 {
821 std::lock_guard l(mLock);
822 RETURN_STATUS_IF_ERROR(mMapper.getAudioMixPort(aidlHandle, &port));
jiabin12537fc2023-10-12 17:56:08 +0000823 }
824 const bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
825 mixPort->role, mixPort->type)) == ::aidl::android::AudioPortDirection::INPUT;
826 *mixPort = VALUE_OR_RETURN_STATUS(::aidl::android::aidl2legacy_AudioPort_audio_port_v7(
827 port, isInput));
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700828 return OK;
jiabin12537fc2023-10-12 17:56:08 +0000829}
830
Mikhail Naganove93a0862023-03-15 17:06:59 -0700831status_t DeviceHalAidl::setAudioPortConfig(const struct audio_port_config* config) {
Shunkai Yao35665b12024-08-21 00:30:54 +0000832 AUGMENT_LOG(D);
Jaideep Sharma145313e2024-08-14 14:51:24 +0530833
Mikhail Naganove93a0862023-03-15 17:06:59 -0700834 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530835 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganove93a0862023-03-15 17:06:59 -0700836 if (config == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530837 AUGMENT_LOG(E, "config not initialized");
Mikhail Naganove93a0862023-03-15 17:06:59 -0700838 return BAD_VALUE;
839 }
840 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
841 config->role, config->type)) == ::aidl::android::AudioPortDirection::INPUT;
842 AudioPortConfig requestedPortConfig = VALUE_OR_RETURN_STATUS(
843 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
844 *config, isInput, 0 /*portId*/));
845 AudioPortConfig portConfig;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700846 std::lock_guard l(mLock);
Mikhail Naganovca92a5c2023-12-07 14:00:48 -0800847 return mMapper.setPortConfig(requestedPortConfig, std::set<int32_t>(), &portConfig);
Shunkai Yao51202502022-12-12 06:11:46 +0000848}
849
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800850MicrophoneInfoProvider::Info const* DeviceHalAidl::getMicrophoneInfo() {
Shunkai Yao35665b12024-08-21 00:30:54 +0000851 AUGMENT_LOG(D);
Jaideep Sharma145313e2024-08-14 14:51:24 +0530852
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700853 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530854 RETURN_IF_MODULE_NOT_INIT({});
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700855 std::lock_guard l(mLock);
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800856 if (mMicrophones.status == Microphones::Status::UNKNOWN) {
857 TIME_CHECK();
858 std::vector<MicrophoneInfo> aidlInfo;
859 status_t status = statusTFromBinderStatus(mModule->getMicrophones(&aidlInfo));
860 if (status == OK) {
861 mMicrophones.status = Microphones::Status::QUERIED;
862 mMicrophones.info = std::move(aidlInfo);
863 } else if (status == INVALID_OPERATION) {
864 mMicrophones.status = Microphones::Status::NOT_SUPPORTED;
865 } else {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530866 AUGMENT_LOG(E, "Unexpected status from HAL: %d", status);
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800867 return {};
868 }
869 }
870 if (mMicrophones.status == Microphones::Status::QUERIED) {
871 return &mMicrophones.info;
872 }
873 return {}; // NOT_SUPPORTED
874}
875
Shunkai Yao51202502022-12-12 06:11:46 +0000876status_t DeviceHalAidl::getMicrophones(
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800877 std::vector<audio_microphone_characteristic_t>* microphones) {
Shunkai Yao35665b12024-08-21 00:30:54 +0000878 AUGMENT_LOG(D);
Jaideep Sharma145313e2024-08-14 14:51:24 +0530879
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700880 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530881 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700882 if (microphones == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530883 AUGMENT_LOG(E, "microphones not initialized");
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800884 return BAD_VALUE;
885 }
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800886 auto staticInfo = getMicrophoneInfo();
887 if (!staticInfo) return INVALID_OPERATION;
888 std::vector<MicrophoneDynamicInfo> emptyDynamicInfo;
889 emptyDynamicInfo.reserve(staticInfo->size());
890 std::transform(staticInfo->begin(), staticInfo->end(), std::back_inserter(emptyDynamicInfo),
891 [](const auto& info) { return MicrophoneDynamicInfo{ .id = info.id }; });
892 *microphones = VALUE_OR_RETURN_STATUS(
893 ::aidl::android::convertContainers<std::vector<audio_microphone_characteristic_t>>(
894 *staticInfo, emptyDynamicInfo,
895 ::aidl::android::aidl2legacy_MicrophoneInfos_audio_microphone_characteristic_t)
896 );
Shunkai Yao51202502022-12-12 06:11:46 +0000897 return OK;
898}
899
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700900status_t DeviceHalAidl::addDeviceEffect(
901 const struct audio_port_config *device, sp<EffectHalInterface> effect) {
Shunkai Yao35665b12024-08-21 00:30:54 +0000902 AUGMENT_LOG(D);
Jaideep Sharma145313e2024-08-14 14:51:24 +0530903
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700904 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530905 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700906 if (device == nullptr || effect == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530907 AUGMENT_LOG(E, "device or effect not initialized");
Shunkai Yao51202502022-12-12 06:11:46 +0000908 return BAD_VALUE;
909 }
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700910 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
911 device->role, device->type)) == ::aidl::android::AudioPortDirection::INPUT;
912 auto requestedPortConfig = VALUE_OR_RETURN_STATUS(
913 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
914 *device, isInput, 0));
915 if (requestedPortConfig.ext.getTag() != AudioPortExt::Tag::device) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530916 AUGMENT_LOG(E, "provided port config is not a device port config: %s",
917 requestedPortConfig.toString().c_str());
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700918 return BAD_VALUE;
919 }
920 AudioPortConfig devicePortConfig;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700921 Hal2AidlMapper::Cleanups cleanups(mMapperAccessor);
922 {
923 std::lock_guard l(mLock);
Mikhail Naganovca92a5c2023-12-07 14:00:48 -0800924 RETURN_STATUS_IF_ERROR(mMapper.setPortConfig(
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700925 requestedPortConfig, {} /*destinationPortIds*/, &devicePortConfig, &cleanups));
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700926 }
927 auto aidlEffect = sp<effect::EffectHalAidl>::cast(effect);
Mikhail Naganov3ecc9eb2024-12-06 11:34:26 -0800928 {
929 std::lock_guard l(mLock);
930 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
931 mModule->addDeviceEffect(devicePortConfig.id, aidlEffect->getIEffect())));
932 }
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700933 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000934 return OK;
935}
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700936status_t DeviceHalAidl::removeDeviceEffect(
937 const struct audio_port_config *device, sp<EffectHalInterface> effect) {
Shunkai Yao35665b12024-08-21 00:30:54 +0000938 AUGMENT_LOG(D);
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700939 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530940 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700941 if (device == nullptr || effect == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530942 AUGMENT_LOG(E, "device or effect not initialized");
Shunkai Yao51202502022-12-12 06:11:46 +0000943 return BAD_VALUE;
944 }
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700945 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
946 device->role, device->type)) == ::aidl::android::AudioPortDirection::INPUT;
947 auto requestedPortConfig = VALUE_OR_RETURN_STATUS(
948 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
949 *device, isInput, 0));
950 if (requestedPortConfig.ext.getTag() != AudioPortExt::Tag::device) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530951 AUGMENT_LOG(E, "provided port config is not a device port config: %s",
952 requestedPortConfig.toString().c_str());
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700953 return BAD_VALUE;
954 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700955 AudioPortConfig devicePortConfig;
956 {
957 std::lock_guard l(mLock);
958 RETURN_STATUS_IF_ERROR(mMapper.findPortConfig(
959 requestedPortConfig.ext.get<AudioPortExt::Tag::device>().device,
960 &devicePortConfig));
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700961 }
962 auto aidlEffect = sp<effect::EffectHalAidl>::cast(effect);
Mikhail Naganov3ecc9eb2024-12-06 11:34:26 -0800963 std::lock_guard l(mLock);
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700964 return statusTFromBinderStatus(mModule->removeDeviceEffect(
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700965 devicePortConfig.id, aidlEffect->getIEffect()));
Shunkai Yao51202502022-12-12 06:11:46 +0000966}
967
968status_t DeviceHalAidl::getMmapPolicyInfos(
David Li9cf5e622023-03-21 00:51:10 +0800969 media::audio::common::AudioMMapPolicyType policyType,
970 std::vector<media::audio::common::AudioMMapPolicyInfo>* policyInfos) {
Shunkai Yao35665b12024-08-21 00:30:54 +0000971 AUGMENT_LOG(D);
Jaideep Sharma145313e2024-08-14 14:51:24 +0530972
Mikhail Naganov31d46652023-01-10 18:29:25 +0000973 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530974 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
975
976 AudioMMapPolicyType mmapPolicyType =
977 VALUE_OR_RETURN_STATUS(cpp2ndk_AudioMMapPolicyType(policyType));
David Li9cf5e622023-03-21 00:51:10 +0800978
979 std::vector<AudioMMapPolicyInfo> mmapPolicyInfos;
980
Mikhail Naganov3ecc9eb2024-12-06 11:34:26 -0800981 {
982 std::lock_guard l(mLock);
983 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
984 mModule->getMmapPolicyInfos(mmapPolicyType, &mmapPolicyInfos)));
David Li9cf5e622023-03-21 00:51:10 +0800985 }
986
987 *policyInfos = VALUE_OR_RETURN_STATUS(
988 convertContainer<std::vector<media::audio::common::AudioMMapPolicyInfo>>(
989 mmapPolicyInfos, ndk2cpp_AudioMMapPolicyInfo));
Shunkai Yao51202502022-12-12 06:11:46 +0000990 return OK;
991}
992
993int32_t DeviceHalAidl::getAAudioMixerBurstCount() {
Shunkai Yao35665b12024-08-21 00:30:54 +0000994 AUGMENT_LOG(D);
Jaideep Sharma145313e2024-08-14 14:51:24 +0530995
Mikhail Naganov31d46652023-01-10 18:29:25 +0000996 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530997 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
David Li9cf5e622023-03-21 00:51:10 +0800998 int32_t mixerBurstCount = 0;
Mikhail Naganov3ecc9eb2024-12-06 11:34:26 -0800999 std::lock_guard l(mLock);
1000 return mModule->getAAudioMixerBurstCount(&mixerBurstCount).isOk() ? mixerBurstCount : 0;
Shunkai Yao51202502022-12-12 06:11:46 +00001001}
1002
1003int32_t DeviceHalAidl::getAAudioHardwareBurstMinUsec() {
Shunkai Yao35665b12024-08-21 00:30:54 +00001004 AUGMENT_LOG(D);
Jaideep Sharma145313e2024-08-14 14:51:24 +05301005
Mikhail Naganov31d46652023-01-10 18:29:25 +00001006 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +05301007 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
David Li9cf5e622023-03-21 00:51:10 +08001008 int32_t hardwareBurstMinUsec = 0;
Mikhail Naganov3ecc9eb2024-12-06 11:34:26 -08001009 std::lock_guard l(mLock);
1010 return mModule->getAAudioHardwareBurstMinUsec(&hardwareBurstMinUsec).isOk() ?
1011 hardwareBurstMinUsec : 0;
Shunkai Yao51202502022-12-12 06:11:46 +00001012}
1013
1014error::Result<audio_hw_sync_t> DeviceHalAidl::getHwAvSync() {
Shunkai Yao35665b12024-08-21 00:30:54 +00001015 AUGMENT_LOG(D);
Jaideep Sharma145313e2024-08-14 14:51:24 +05301016
Mikhail Naganov31d46652023-01-10 18:29:25 +00001017 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +05301018 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganov08a62ab2023-03-14 17:11:51 -07001019 int32_t aidlHwAvSync;
Mikhail Naganov3ecc9eb2024-12-06 11:34:26 -08001020 std::lock_guard l(mLock);
Mikhail Naganov08a62ab2023-03-14 17:11:51 -07001021 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->generateHwAvSyncId(&aidlHwAvSync)));
1022 return VALUE_OR_RETURN_STATUS(
1023 ::aidl::android::aidl2legacy_int32_t_audio_hw_sync_t(aidlHwAvSync));
Shunkai Yao51202502022-12-12 06:11:46 +00001024}
1025
Mikhail Naganovfab697c2023-01-11 19:33:13 +00001026status_t DeviceHalAidl::dump(int fd, const Vector<String16>& args) {
1027 TIME_CHECK();
Mikhail Naganov3ecc9eb2024-12-06 11:34:26 -08001028 if (!isModuleInitialized()) return NO_INIT;
David Li21289462024-04-17 01:09:23 +08001029 Vector<String16> newArgs = args;
1030 newArgs.push(String16(kDumpFromAudioServerArgument));
Mikhail Naganov3ecc9eb2024-12-06 11:34:26 -08001031 std::lock_guard l(mLock);
David Li21289462024-04-17 01:09:23 +08001032 return mModule->dump(fd, Args(newArgs).args(), newArgs.size());
David Li9cf5e622023-03-21 00:51:10 +08001033}
Shunkai Yao51202502022-12-12 06:11:46 +00001034
Eric Laurent7af6ee72023-06-29 11:44:54 +02001035status_t DeviceHalAidl::supportsBluetoothVariableLatency(bool* supports) {
Shunkai Yao35665b12024-08-21 00:30:54 +00001036 AUGMENT_LOG(D);
Jaideep Sharma145313e2024-08-14 14:51:24 +05301037
Mikhail Naganov31d46652023-01-10 18:29:25 +00001038 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +05301039 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganov3ac95c92023-04-12 13:14:30 -07001040 if (supports == nullptr) {
1041 return BAD_VALUE;
1042 }
Mikhail Naganov3ecc9eb2024-12-06 11:34:26 -08001043 std::lock_guard l(mLock);
Mikhail Naganov3ac95c92023-04-12 13:14:30 -07001044 return statusTFromBinderStatus(mModule->supportsVariableLatency(supports));
Shunkai Yao51202502022-12-12 06:11:46 +00001045}
Mikhail Naganov31d46652023-01-10 18:29:25 +00001046
Jaideep Sharma145313e2024-08-14 14:51:24 +05301047status_t DeviceHalAidl::getSoundDoseInterface([[maybe_unused]] const std::string& module,
1048 ::ndk::SpAIBinder* soundDoseBinder) {
Shunkai Yao35665b12024-08-21 00:30:54 +00001049 AUGMENT_LOG(V);
Jaideep Sharma145313e2024-08-14 14:51:24 +05301050 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
1051
Mikhail Naganovac9d4e72023-10-23 12:00:09 -07001052 if (soundDoseBinder == nullptr) {
1053 return BAD_VALUE;
1054 }
Vlad Popa03bd5bc2023-01-17 16:16:51 +01001055 if (mSoundDose == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +05301056 AUGMENT_LOG(E, "failed to retrieve the sound dose interface");
Vlad Popae1f33902023-10-30 19:48:25 -07001057 return NO_INIT;
1058 }
1059
Vlad Popa03bd5bc2023-01-17 16:16:51 +01001060 *soundDoseBinder = mSoundDose->asBinder();
Mikhail Naganov3ecc9eb2024-12-06 11:34:26 -08001061 if (soundDoseBinder == nullptr) {
1062 AUGMENT_LOG(E, "failed to return the sound dose interface not implemented");
1063 return NO_INIT;
1064 }
1065
Jaideep Sharma145313e2024-08-14 14:51:24 +05301066 AUGMENT_LOG(I, "using audio AIDL HAL sound dose interface");
Vlad Popa03bd5bc2023-01-17 16:16:51 +01001067 return OK;
1068}
jiabin872de702023-04-27 22:04:31 +00001069
1070status_t DeviceHalAidl::prepareToDisconnectExternalDevice(const struct audio_port_v7* port) {
Shunkai Yao35665b12024-08-21 00:30:54 +00001071 AUGMENT_LOG(V);
jiabin62750c22023-12-21 22:06:07 +00001072 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +05301073 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
jiabin62750c22023-12-21 22:06:07 +00001074 if (port == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +05301075 AUGMENT_LOG(E, "port not initialized");
jiabin62750c22023-12-21 22:06:07 +00001076 return BAD_VALUE;
1077 }
Jaideep Sharma145313e2024-08-14 14:51:24 +05301078 const bool isInput =
1079 VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(port->role, port->type)) ==
1080 ::aidl::android::AudioPortDirection::INPUT;
jiabin62750c22023-12-21 22:06:07 +00001081 AudioPort aidlPort = VALUE_OR_RETURN_STATUS(
1082 ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
1083 if (aidlPort.ext.getTag() != AudioPortExt::device) {
Jaideep Sharma145313e2024-08-14 14:51:24 +05301084 AUGMENT_LOG(E, "provided port is not a device port: %s", aidlPort.toString().c_str());
jiabin62750c22023-12-21 22:06:07 +00001085 return BAD_VALUE;
1086 }
Jaideep Sharma145313e2024-08-14 14:51:24 +05301087
1088 AUGMENT_LOG(D, "device %s", aidlPort.toString().c_str());
1089
jiabin62750c22023-12-21 22:06:07 +00001090 status_t status = NO_ERROR;
1091 {
1092 std::lock_guard l(mLock);
1093 status = mMapper.prepareToDisconnectExternalDevice(aidlPort);
1094 }
1095 if (status == UNKNOWN_TRANSACTION) {
1096 // If there is not AIDL API defined for `prepareToDisconnectExternalDevice`.
1097 // Call `setConnectedState` instead.
1098 RETURN_STATUS_IF_ERROR(setConnectedState(port, false /*connected*/));
1099 std::lock_guard l(mLock);
1100 mDeviceDisconnectionNotified.insert(port->id);
1101 // Return that there was no error as otherwise the disconnection procedure will not be
1102 // considered complete for upper layers, and 'setConnectedState' will not be called again
1103 return OK;
1104 } else {
1105 return status;
1106 }
jiabin872de702023-04-27 22:04:31 +00001107}
1108
Mikhail Naganove93a0862023-03-15 17:06:59 -07001109status_t DeviceHalAidl::setConnectedState(const struct audio_port_v7 *port, bool connected) {
Shunkai Yao35665b12024-08-21 00:30:54 +00001110 AUGMENT_LOG(V);
Mikhail Naganove93a0862023-03-15 17:06:59 -07001111 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +05301112 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganove93a0862023-03-15 17:06:59 -07001113 if (port == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +05301114 AUGMENT_LOG(E, "port not initialized");
Mikhail Naganove93a0862023-03-15 17:06:59 -07001115 return BAD_VALUE;
1116 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -07001117 if (!connected) {
1118 std::lock_guard l(mLock);
1119 if (mDeviceDisconnectionNotified.erase(port->id) > 0) {
1120 // For device disconnection, APM will first call `prepareToDisconnectExternalDevice`
jiabin62750c22023-12-21 22:06:07 +00001121 // and then call `setConnectedState`. If `prepareToDisconnectExternalDevice` doesn't
1122 // exit, `setConnectedState` will be called when calling
1123 // `prepareToDisconnectExternalDevice`. Do not call to the HAL if previous call is
1124 // successful. Also remove the cache here to avoid a large cache after a long run.
Mikhail Naganovac9d4e72023-10-23 12:00:09 -07001125 return OK;
1126 }
jiabin872de702023-04-27 22:04:31 +00001127 }
Mikhail Naganove93a0862023-03-15 17:06:59 -07001128 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(port->role, port->type)) ==
1129 ::aidl::android::AudioPortDirection::INPUT;
1130 AudioPort aidlPort = VALUE_OR_RETURN_STATUS(
1131 ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
1132 if (aidlPort.ext.getTag() != AudioPortExt::device) {
Jaideep Sharma145313e2024-08-14 14:51:24 +05301133 AUGMENT_LOG(E, "provided port is not a device port: %s", aidlPort.toString().c_str());
Mikhail Naganove93a0862023-03-15 17:06:59 -07001134 return BAD_VALUE;
1135 }
Jaideep Sharma145313e2024-08-14 14:51:24 +05301136 AUGMENT_LOG(D, "connected %d port: %s", connected, aidlPort.toString().c_str());
Mikhail Naganovac9d4e72023-10-23 12:00:09 -07001137 std::lock_guard l(mLock);
1138 return mMapper.setDevicePortConnectedState(aidlPort, connected);
Mikhail Naganove93a0862023-03-15 17:06:59 -07001139}
1140
1141status_t DeviceHalAidl::setSimulateDeviceConnections(bool enabled) {
Shunkai Yao35665b12024-08-21 00:30:54 +00001142 AUGMENT_LOG(V);
Mikhail Naganove93a0862023-03-15 17:06:59 -07001143 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +05301144 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganov3ecc9eb2024-12-06 11:34:26 -08001145 std::lock_guard l(mLock);
1146 mMapper.resetUnusedPatchesAndPortConfigs();
Mikhail Naganove93a0862023-03-15 17:06:59 -07001147 ModuleDebug debug{ .simulateDeviceConnections = enabled };
1148 status_t status = statusTFromBinderStatus(mModule->setModuleDebug(debug));
1149 // This is important to log as it affects HAL behavior.
1150 if (status == OK) {
Jaideep Sharma145313e2024-08-14 14:51:24 +05301151 AUGMENT_LOG(I, "set enabled: %d", enabled);
Mikhail Naganove93a0862023-03-15 17:06:59 -07001152 } else {
Jaideep Sharma145313e2024-08-14 14:51:24 +05301153 AUGMENT_LOG(W, "set enabled to %d failed: %d", enabled, status);
Mikhail Naganove93a0862023-03-15 17:06:59 -07001154 }
1155 return status;
1156}
1157
Mikhail Naganove7a26ad2023-05-25 17:36:48 -07001158status_t DeviceHalAidl::filterAndRetrieveBtA2dpParameters(
1159 AudioParameter &keys, AudioParameter *result) {
Mikhail Naganove7a26ad2023-05-25 17:36:48 -07001160 if (String8 key = String8(AudioParameter::keyReconfigA2dpSupported); keys.containsKey(key)) {
1161 keys.remove(key);
Mikhail Naganov3ecc9eb2024-12-06 11:34:26 -08001162 std::lock_guard l(mLock);
David Lia7761ed2023-11-03 17:22:07 +00001163 if (mBluetoothA2dp != nullptr) {
1164 bool supports;
1165 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
1166 mBluetoothA2dp->supportsOffloadReconfiguration(&supports)));
1167 result->addInt(key, supports ? 1 : 0);
1168 } else {
Jaideep Sharma145313e2024-08-14 14:51:24 +05301169 AUGMENT_LOG(I, "no IBluetoothA2dp");
David Lia7761ed2023-11-03 17:22:07 +00001170 result->addInt(key, 0);
1171 }
Mikhail Naganove7a26ad2023-05-25 17:36:48 -07001172 }
1173 return OK;
1174}
1175
Eric Laurent7e3c0832023-11-30 15:04:50 +01001176status_t DeviceHalAidl::filterAndRetrieveBtLeParameters(
1177 AudioParameter &keys, AudioParameter *result) {
1178 if (String8 key = String8(AudioParameter::keyReconfigLeSupported); keys.containsKey(key)) {
1179 keys.remove(key);
Mikhail Naganov3ecc9eb2024-12-06 11:34:26 -08001180 std::lock_guard l(mLock);
Eric Laurent7e3c0832023-11-30 15:04:50 +01001181 if (mBluetoothLe != nullptr) {
1182 bool supports;
1183 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
1184 mBluetoothLe->supportsOffloadReconfiguration(&supports)));
1185 result->addInt(key, supports ? 1 : 0);
1186 } else {
Jaideep Sharma145313e2024-08-14 14:51:24 +05301187 AUGMENT_LOG(I, "no mBluetoothLe");
Eric Laurent7e3c0832023-11-30 15:04:50 +01001188 result->addInt(key, 0);
1189 }
1190 }
1191 return OK;
1192}
1193
Mikhail Naganovccc82112023-04-27 18:14:15 -07001194status_t DeviceHalAidl::filterAndUpdateBtA2dpParameters(AudioParameter &parameters) {
Mikhail Naganovccc82112023-04-27 18:14:15 -07001195 std::optional<bool> a2dpEnabled;
Mikhail Naganove7a26ad2023-05-25 17:36:48 -07001196 std::optional<std::vector<VendorParameter>> reconfigureOffload;
Mikhail Naganovccc82112023-04-27 18:14:15 -07001197 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301198 parameters, String8(AudioParameter::keyBtA2dpSuspended),
1199 [&a2dpEnabled, this](const String8& trueOrFalse) {
1200 if (trueOrFalse == AudioParameter::valueTrue) {
1201 a2dpEnabled = false; // 'suspended' == true
1202 return OK;
1203 } else if (trueOrFalse == AudioParameter::valueFalse) {
1204 a2dpEnabled = true; // 'suspended' == false
1205 return OK;
1206 }
1207 AUGMENT_LOG(E, "setParameters: parameter key \"%s\" has invalid value \"%s\"",
1208 AudioParameter::keyBtA2dpSuspended, trueOrFalse.c_str());
1209 return BAD_VALUE;
1210 }));
Mikhail Naganove7a26ad2023-05-25 17:36:48 -07001211 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301212 parameters, String8(AudioParameter::keyReconfigA2dp),
1213 [&](const String8& value) -> status_t {
1214 std::vector<VendorParameter> result;
1215 RETURN_STATUS_IF_ERROR(
1216 statusTFromBinderStatus(mVendorExt->parseBluetoothA2dpReconfigureOffload(
1217 std::string(value.c_str()), &result)));
1218 reconfigureOffload = std::move(result);
1219 return OK;
1220 }));
Mikhail Naganov3ecc9eb2024-12-06 11:34:26 -08001221 std::lock_guard l(mLock);
Mikhail Naganovccc82112023-04-27 18:14:15 -07001222 if (mBluetoothA2dp != nullptr && a2dpEnabled.has_value()) {
1223 return statusTFromBinderStatus(mBluetoothA2dp->setEnabled(a2dpEnabled.value()));
1224 }
Mikhail Naganove7a26ad2023-05-25 17:36:48 -07001225 if (mBluetoothA2dp != nullptr && reconfigureOffload.has_value()) {
1226 return statusTFromBinderStatus(mBluetoothA2dp->reconfigureOffload(
1227 reconfigureOffload.value()));
1228 }
Mikhail Naganovccc82112023-04-27 18:14:15 -07001229 return OK;
1230}
1231
1232status_t DeviceHalAidl::filterAndUpdateBtHfpParameters(AudioParameter &parameters) {
Mikhail Naganovccc82112023-04-27 18:14:15 -07001233 IBluetooth::HfpConfig hfpConfig;
1234 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301235 parameters, String8(AudioParameter::keyBtHfpEnable),
1236 [&hfpConfig, this](const String8& trueOrFalse) {
1237 if (trueOrFalse == AudioParameter::valueTrue) {
1238 hfpConfig.isEnabled = Boolean{.value = true};
1239 return OK;
1240 } else if (trueOrFalse == AudioParameter::valueFalse) {
1241 hfpConfig.isEnabled = Boolean{.value = false};
1242 return OK;
1243 }
1244 AUGMENT_LOG(E, "setParameters: parameter key \"%s\" has invalid value \"%s\"",
1245 AudioParameter::keyBtHfpEnable, trueOrFalse.c_str());
1246 return BAD_VALUE;
1247 }));
Mikhail Naganovccc82112023-04-27 18:14:15 -07001248 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301249 parameters, String8(AudioParameter::keyBtHfpSamplingRate),
1250 [&hfpConfig](int sampleRate) {
1251 return sampleRate > 0 ? hfpConfig.sampleRate = Int{.value = sampleRate},
1252 OK : BAD_VALUE;
1253 }));
Mikhail Naganovccc82112023-04-27 18:14:15 -07001254 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301255 parameters, String8(AudioParameter::keyBtHfpVolume), [&hfpConfig](int volume0to15) {
1256 if (volume0to15 >= 0 && volume0to15 <= 15) {
1257 hfpConfig.volume = Float{.value = volume0to15 / 15.0f};
1258 return OK;
1259 }
1260 return BAD_VALUE;
1261 }));
Mikhail Naganov3ecc9eb2024-12-06 11:34:26 -08001262 std::lock_guard l(mLock);
Mikhail Naganovccc82112023-04-27 18:14:15 -07001263 if (mBluetooth != nullptr && hfpConfig != IBluetooth::HfpConfig{}) {
1264 IBluetooth::HfpConfig newHfpConfig;
1265 return statusTFromBinderStatus(mBluetooth->setHfpConfig(hfpConfig, &newHfpConfig));
1266 }
1267 return OK;
1268}
1269
1270status_t DeviceHalAidl::filterAndUpdateBtLeParameters(AudioParameter &parameters) {
Mikhail Naganovccc82112023-04-27 18:14:15 -07001271 std::optional<bool> leEnabled;
Eric Laurent7e3c0832023-11-30 15:04:50 +01001272 std::optional<std::vector<VendorParameter>> reconfigureOffload;
Mikhail Naganovccc82112023-04-27 18:14:15 -07001273 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301274 parameters, String8(AudioParameter::keyBtLeSuspended),
1275 [&leEnabled, this](const String8& trueOrFalse) {
1276 if (trueOrFalse == AudioParameter::valueTrue) {
1277 leEnabled = false; // 'suspended' == true
1278 return OK;
1279 } else if (trueOrFalse == AudioParameter::valueFalse) {
1280 leEnabled = true; // 'suspended' == false
1281 return OK;
1282 }
1283 AUGMENT_LOG(E, "setParameters: parameter key \"%s\" has invalid value \"%s\"",
1284 AudioParameter::keyBtLeSuspended, trueOrFalse.c_str());
1285 return BAD_VALUE;
1286 }));
Eric Laurent7e3c0832023-11-30 15:04:50 +01001287 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301288 parameters, String8(AudioParameter::keyReconfigLe),
1289 [&](const String8& value) -> status_t {
1290 if (mVendorExt != nullptr) {
1291 std::vector<VendorParameter> result;
1292 RETURN_STATUS_IF_ERROR(
1293 statusTFromBinderStatus(mVendorExt->parseBluetoothLeReconfigureOffload(
1294 std::string(value.c_str()), &result)));
1295 reconfigureOffload = std::move(result);
1296 } else {
1297 reconfigureOffload = std::vector<VendorParameter>();
1298 }
1299 return OK;
1300 }));
Mikhail Naganov3ecc9eb2024-12-06 11:34:26 -08001301 std::lock_guard l(mLock);
Mikhail Naganovccc82112023-04-27 18:14:15 -07001302 if (mBluetoothLe != nullptr && leEnabled.has_value()) {
1303 return statusTFromBinderStatus(mBluetoothLe->setEnabled(leEnabled.value()));
1304 }
Eric Laurent7e3c0832023-11-30 15:04:50 +01001305 if (mBluetoothLe != nullptr && reconfigureOffload.has_value()) {
Jaideep Sharma145313e2024-08-14 14:51:24 +05301306 return statusTFromBinderStatus(
1307 mBluetoothLe->reconfigureOffload(reconfigureOffload.value()));
Eric Laurent7e3c0832023-11-30 15:04:50 +01001308 }
Mikhail Naganovccc82112023-04-27 18:14:15 -07001309 return OK;
1310}
1311
1312status_t DeviceHalAidl::filterAndUpdateBtScoParameters(AudioParameter &parameters) {
Mikhail Naganovccc82112023-04-27 18:14:15 -07001313 IBluetooth::ScoConfig scoConfig;
1314 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301315 parameters, String8(AudioParameter::keyBtSco),
1316 [&scoConfig, this](const String8& onOrOff) {
1317 if (onOrOff == AudioParameter::valueOn) {
1318 scoConfig.isEnabled = Boolean{.value = true};
1319 return OK;
1320 } else if (onOrOff == AudioParameter::valueOff) {
1321 scoConfig.isEnabled = Boolean{.value = false};
1322 return OK;
1323 }
1324 AUGMENT_LOG(E, "setParameters: parameter key \"%s\" has invalid value \"%s\"",
1325 AudioParameter::keyBtSco, onOrOff.c_str());
1326 return BAD_VALUE;
1327 }));
Mikhail Naganovccc82112023-04-27 18:14:15 -07001328 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301329 parameters, String8(AudioParameter::keyBtScoHeadsetName),
1330 [&scoConfig](const String8& name) {
1331 scoConfig.debugName = name;
1332 return OK;
1333 }));
Mikhail Naganovccc82112023-04-27 18:14:15 -07001334 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301335 parameters, String8(AudioParameter::keyBtNrec),
1336 [&scoConfig, this](const String8& onOrOff) {
1337 if (onOrOff == AudioParameter::valueOn) {
1338 scoConfig.isNrecEnabled = Boolean{.value = true};
1339 return OK;
1340 } else if (onOrOff == AudioParameter::valueOff) {
1341 scoConfig.isNrecEnabled = Boolean{.value = false};
1342 return OK;
1343 }
1344 AUGMENT_LOG(E, "setParameters: parameter key \"%s\" has invalid value \"%s\"",
1345 AudioParameter::keyBtNrec, onOrOff.c_str());
1346 return BAD_VALUE;
1347 }));
Mikhail Naganovccc82112023-04-27 18:14:15 -07001348 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301349 parameters, String8(AudioParameter::keyBtScoWb),
1350 [&scoConfig, this](const String8& onOrOff) {
1351 if (onOrOff == AudioParameter::valueOn) {
1352 scoConfig.mode = IBluetooth::ScoConfig::Mode::SCO_WB;
1353 return OK;
1354 } else if (onOrOff == AudioParameter::valueOff) {
1355 scoConfig.mode = IBluetooth::ScoConfig::Mode::SCO;
1356 return OK;
1357 }
1358 AUGMENT_LOG(E, "setParameters: parameter key \"%s\" has invalid value \"%s\"",
1359 AudioParameter::keyBtScoWb, onOrOff.c_str());
1360 return BAD_VALUE;
1361 }));
Mikhail Naganov3ecc9eb2024-12-06 11:34:26 -08001362 std::lock_guard l(mLock);
Mikhail Naganovccc82112023-04-27 18:14:15 -07001363 if (mBluetooth != nullptr && scoConfig != IBluetooth::ScoConfig{}) {
1364 IBluetooth::ScoConfig newScoConfig;
1365 return statusTFromBinderStatus(mBluetooth->setScoConfig(scoConfig, &newScoConfig));
1366 }
1367 return OK;
1368}
1369
Mikhail Naganove92c34b2023-05-31 14:24:48 -07001370status_t DeviceHalAidl::filterAndUpdateScreenParameters(AudioParameter &parameters) {
Mikhail Naganove92c34b2023-05-31 14:24:48 -07001371 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301372 parameters, String8(AudioParameter::keyScreenState),
1373 [&, this](const String8& onOrOff) -> status_t {
1374 std::optional<bool> isTurnedOn;
1375 if (onOrOff == AudioParameter::valueOn) {
1376 isTurnedOn = true;
1377 } else if (onOrOff == AudioParameter::valueOff) {
1378 isTurnedOn = false;
1379 }
1380 if (!isTurnedOn.has_value()) {
1381 AUGMENT_LOG(E, "setParameters: parameter key \"%s\" has invalid value \"%s\"",
1382 AudioParameter::keyScreenState, onOrOff.c_str());
1383 return BAD_VALUE;
1384 }
Mikhail Naganov3ecc9eb2024-12-06 11:34:26 -08001385 std::lock_guard l(mLock);
Jaideep Sharma145313e2024-08-14 14:51:24 +05301386 return statusTFromBinderStatus(mModule->updateScreenState(isTurnedOn.value()));
1387 }));
Mikhail Naganove92c34b2023-05-31 14:24:48 -07001388 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301389 parameters, String8(AudioParameter::keyScreenRotation),
1390 [&, this](int rotationDegrees) -> status_t {
Mikhail Naganove92c34b2023-05-31 14:24:48 -07001391 IModule::ScreenRotation rotation;
1392 switch (rotationDegrees) {
Jaideep Sharma145313e2024-08-14 14:51:24 +05301393 case 0:
1394 rotation = IModule::ScreenRotation::DEG_0;
1395 break;
1396 case 90:
1397 rotation = IModule::ScreenRotation::DEG_90;
1398 break;
1399 case 180:
1400 rotation = IModule::ScreenRotation::DEG_180;
1401 break;
1402 case 270:
1403 rotation = IModule::ScreenRotation::DEG_270;
1404 break;
Mikhail Naganove92c34b2023-05-31 14:24:48 -07001405 default:
Jaideep Sharma145313e2024-08-14 14:51:24 +05301406 AUGMENT_LOG(E, "setParameters: parameter key \"%s\" has invalid value %d",
1407 AudioParameter::keyScreenRotation, rotationDegrees);
Mikhail Naganove92c34b2023-05-31 14:24:48 -07001408 return BAD_VALUE;
1409 }
Mikhail Naganov3ecc9eb2024-12-06 11:34:26 -08001410 std::lock_guard l(mLock);
Mikhail Naganove92c34b2023-05-31 14:24:48 -07001411 return statusTFromBinderStatus(mModule->updateScreenRotation(rotation));
1412 }));
1413 return OK;
1414}
1415
Mikhail Naganovb9a81312023-07-18 13:55:34 -07001416status_t DeviceHalAidl::filterAndUpdateTelephonyParameters(AudioParameter &parameters) {
Mikhail Naganovb9a81312023-07-18 13:55:34 -07001417 using TtyMode = ITelephony::TelecomConfig::TtyMode;
1418 ITelephony::TelecomConfig telConfig;
1419 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301420 parameters, String8(AudioParameter::keyTtyMode),
1421 [&telConfig, this](const String8& mode) {
1422 if (mode == AudioParameter::valueTtyModeOff) {
1423 telConfig.ttyMode = TtyMode::OFF;
1424 return OK;
1425 } else if (mode == AudioParameter::valueTtyModeFull) {
1426 telConfig.ttyMode = TtyMode::FULL;
1427 return OK;
1428 } else if (mode == AudioParameter::valueTtyModeHco) {
1429 telConfig.ttyMode = TtyMode::HCO;
1430 return OK;
1431 } else if (mode == AudioParameter::valueTtyModeVco) {
1432 telConfig.ttyMode = TtyMode::VCO;
1433 return OK;
1434 }
1435 AUGMENT_LOG(E, "setParameters: parameter key \"%s\" has invalid value \"%s\"",
1436 AudioParameter::keyTtyMode, mode.c_str());
1437 return BAD_VALUE;
1438 }));
Mikhail Naganovb9a81312023-07-18 13:55:34 -07001439 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301440 parameters, String8(AudioParameter::keyHacSetting),
1441 [&telConfig, this](const String8& onOrOff) {
1442 if (onOrOff == AudioParameter::valueHacOn) {
1443 telConfig.isHacEnabled = Boolean{.value = true};
1444 return OK;
1445 } else if (onOrOff == AudioParameter::valueHacOff) {
1446 telConfig.isHacEnabled = Boolean{.value = false};
1447 return OK;
1448 }
1449 AUGMENT_LOG(E, "setParameters: parameter key \"%s\" has invalid value \"%s\"",
1450 AudioParameter::keyHacSetting, onOrOff.c_str());
1451 return BAD_VALUE;
1452 }));
Mikhail Naganov3ecc9eb2024-12-06 11:34:26 -08001453 std::lock_guard l(mLock);
Mikhail Naganovb9a81312023-07-18 13:55:34 -07001454 if (mTelephony != nullptr && telConfig != ITelephony::TelecomConfig{}) {
1455 ITelephony::TelecomConfig newTelConfig;
Jaideep Sharma145313e2024-08-14 14:51:24 +05301456 return statusTFromBinderStatus(mTelephony->setTelecomConfig(telConfig, &newTelConfig));
Mikhail Naganovb9a81312023-07-18 13:55:34 -07001457 }
1458 return OK;
1459}
1460
Mikhail Naganovdfd594e2023-02-08 16:59:41 -08001461void DeviceHalAidl::clearCallbacks(void* cookie) {
Mikhail Naganov22578412024-08-16 16:50:34 -07001462 std::lock_guard l(mCallbacksLock);
Mikhail Naganovdfd594e2023-02-08 16:59:41 -08001463 mCallbacks.erase(cookie);
1464}
1465
1466sp<StreamOutHalInterfaceCallback> DeviceHalAidl::getStreamOutCallback(void* cookie) {
1467 return getCallbackImpl(cookie, &Callbacks::out);
1468}
1469
1470void DeviceHalAidl::setStreamOutCallback(
1471 void* cookie, const sp<StreamOutHalInterfaceCallback>& cb) {
1472 setCallbackImpl(cookie, &Callbacks::out, cb);
1473}
1474
1475sp<StreamOutHalInterfaceEventCallback> DeviceHalAidl::getStreamOutEventCallback(
1476 void* cookie) {
1477 return getCallbackImpl(cookie, &Callbacks::event);
1478}
1479
1480void DeviceHalAidl::setStreamOutEventCallback(
1481 void* cookie, const sp<StreamOutHalInterfaceEventCallback>& cb) {
1482 setCallbackImpl(cookie, &Callbacks::event, cb);
1483}
1484
1485sp<StreamOutHalInterfaceLatencyModeCallback> DeviceHalAidl::getStreamOutLatencyModeCallback(
1486 void* cookie) {
1487 return getCallbackImpl(cookie, &Callbacks::latency);
1488}
1489
1490void DeviceHalAidl::setStreamOutLatencyModeCallback(
1491 void* cookie, const sp<StreamOutHalInterfaceLatencyModeCallback>& cb) {
1492 setCallbackImpl(cookie, &Callbacks::latency, cb);
1493}
1494
Mikhail Naganov22578412024-08-16 16:50:34 -07001495template <class C>
Mikhail Naganovdfd594e2023-02-08 16:59:41 -08001496sp<C> DeviceHalAidl::getCallbackImpl(void* cookie, wp<C> DeviceHalAidl::Callbacks::* field) {
Mikhail Naganov22578412024-08-16 16:50:34 -07001497 wp<C> result;
1498 {
1499 std::lock_guard l(mCallbacksLock);
1500 if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
1501 result = (it->second).*field;
1502 }
Mikhail Naganovdfd594e2023-02-08 16:59:41 -08001503 }
Mikhail Naganov22578412024-08-16 16:50:34 -07001504 return result.promote();
Mikhail Naganovdfd594e2023-02-08 16:59:41 -08001505}
1506template<class C>
1507void DeviceHalAidl::setCallbackImpl(
1508 void* cookie, wp<C> DeviceHalAidl::Callbacks::* field, const sp<C>& cb) {
Mikhail Naganov22578412024-08-16 16:50:34 -07001509 std::lock_guard l(mCallbacksLock);
Mikhail Naganovdfd594e2023-02-08 16:59:41 -08001510 if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
1511 (it->second).*field = cb;
1512 }
1513}
1514
Mikhail Naganov31d46652023-01-10 18:29:25 +00001515} // namespace android