blob: 629cd7cf5d5a2b62fd1c0aa9d374a29d99f2221b [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) \
82 if (mModule == nullptr) { \
83 AUGMENT_LOG(E, "module not initialized"); \
84 return retVal; \
85 }
86
87#define RETURN_IF_TELEPHONY_NOT_INIT(retVal) \
88 if (mTelephony == nullptr) { \
89 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),
127 mVendorExt(vext),
128 mTelephony(retrieveSubInterface<ITelephony>(module, &IModule::getTelephony)),
129 mBluetooth(retrieveSubInterface<IBluetooth>(module, &IModule::getBluetooth)),
130 mBluetoothA2dp(retrieveSubInterface<IBluetoothA2dp>(module, &IModule::getBluetoothA2dp)),
131 mBluetoothLe(retrieveSubInterface<IBluetoothLe>(module, &IModule::getBluetoothLe)),
132 mSoundDose(retrieveSubInterface<ISoundDose>(module, &IModule::getSoundDose)),
133 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;
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() {
Shunkai Yao35665b12024-08-21 00:30:54 +0000171 AUGMENT_LOG(D);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800172 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530173 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700174 std::lock_guard l(mLock);
175 return mMapper.initialize();
Shunkai Yao51202502022-12-12 06:11:46 +0000176}
177
178status_t DeviceHalAidl::setVoiceVolume(float volume) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530179 AUGMENT_LOG(D, "volume %f", volume);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000180 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530181 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
182 RETURN_IF_TELEPHONY_NOT_INIT(INVALID_OPERATION);
183
184 ITelephony::TelecomConfig inConfig{.voiceVolume = Float{volume}}, outConfig;
Mikhail Naganov1fba38c2023-05-03 17:45:36 -0700185 RETURN_STATUS_IF_ERROR(
186 statusTFromBinderStatus(mTelephony->setTelecomConfig(inConfig, &outConfig)));
Jaideep Sharma145313e2024-08-14 14:51:24 +0530187 AUGMENT_LOG_IF(
188 W, outConfig.voiceVolume.has_value() && volume != outConfig.voiceVolume.value().value,
189 "the resulting voice volume %f is not the same as requested %f",
190 outConfig.voiceVolume.value().value, volume);
Mikhail Naganov1fba38c2023-05-03 17:45:36 -0700191 return OK;
Shunkai Yao51202502022-12-12 06:11:46 +0000192}
193
194status_t DeviceHalAidl::setMasterVolume(float volume) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530195 AUGMENT_LOG(D, "volume %f", volume);
196
Mikhail Naganov31d46652023-01-10 18:29:25 +0000197 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530198 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000199 return statusTFromBinderStatus(mModule->setMasterVolume(volume));
Shunkai Yao51202502022-12-12 06:11:46 +0000200}
201
202status_t DeviceHalAidl::getMasterVolume(float *volume) {
Shunkai Yao35665b12024-08-21 00:30:54 +0000203 AUGMENT_LOG(D);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000204 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530205 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700206 if (volume == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530207 AUGMENT_LOG(E, "uninitialized volumes");
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700208 return BAD_VALUE;
209 }
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000210 return statusTFromBinderStatus(mModule->getMasterVolume(volume));
Shunkai Yao51202502022-12-12 06:11:46 +0000211}
212
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000213status_t DeviceHalAidl::setMode(audio_mode_t mode) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530214 AUGMENT_LOG(D, "mode %d", mode);
215
Mikhail Naganov31d46652023-01-10 18:29:25 +0000216 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530217 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000218 AudioMode audioMode = VALUE_OR_FATAL(::aidl::android::legacy2aidl_audio_mode_t_AudioMode(mode));
Mikhail Naganov1fba38c2023-05-03 17:45:36 -0700219 if (mTelephony != nullptr) {
220 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mTelephony->switchAudioMode(audioMode)));
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000221 }
222 return statusTFromBinderStatus(mModule->updateAudioMode(audioMode));
Shunkai Yao51202502022-12-12 06:11:46 +0000223}
224
225status_t DeviceHalAidl::setMicMute(bool state) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530226 AUGMENT_LOG(D, "mute %d", state);
227
Mikhail Naganov31d46652023-01-10 18:29:25 +0000228 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530229 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000230 return statusTFromBinderStatus(mModule->setMicMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000231}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000232
Shunkai Yao51202502022-12-12 06:11:46 +0000233status_t DeviceHalAidl::getMicMute(bool *state) {
Shunkai Yao35665b12024-08-21 00:30:54 +0000234 AUGMENT_LOG(D);
Jaideep Sharma145313e2024-08-14 14:51:24 +0530235
Mikhail Naganov31d46652023-01-10 18:29:25 +0000236 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530237 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700238 if (state == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530239 AUGMENT_LOG(E, "uninitialized mute state");
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700240 return BAD_VALUE;
241 }
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000242 return statusTFromBinderStatus(mModule->getMicMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000243}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000244
Shunkai Yao51202502022-12-12 06:11:46 +0000245status_t DeviceHalAidl::setMasterMute(bool state) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530246 AUGMENT_LOG(D, "mute %d", state);
247
Mikhail Naganov31d46652023-01-10 18:29:25 +0000248 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530249 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000250 return statusTFromBinderStatus(mModule->setMasterMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000251}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000252
Shunkai Yao51202502022-12-12 06:11:46 +0000253status_t DeviceHalAidl::getMasterMute(bool *state) {
Shunkai Yao35665b12024-08-21 00:30:54 +0000254 AUGMENT_LOG(D);
Jaideep Sharma145313e2024-08-14 14:51:24 +0530255
Mikhail Naganov31d46652023-01-10 18:29:25 +0000256 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530257 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700258 if (state == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530259 AUGMENT_LOG(E, "uninitialized mute state");
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700260 return BAD_VALUE;
261 }
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000262 return statusTFromBinderStatus(mModule->getMasterMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000263}
264
Mikhail Naganovccc82112023-04-27 18:14:15 -0700265status_t DeviceHalAidl::setParameters(const String8& kvPairs) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700266 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530267 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovccc82112023-04-27 18:14:15 -0700268 AudioParameter parameters(kvPairs);
Jaideep Sharma145313e2024-08-14 14:51:24 +0530269 AUGMENT_LOG(D, "parameters: \"%s\"", parameters.toString().c_str());
Mikhail Naganovccc82112023-04-27 18:14:15 -0700270
271 if (status_t status = filterAndUpdateBtA2dpParameters(parameters); status != OK) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530272 AUGMENT_LOG(W, "filterAndUpdateBtA2dpParameters failed: %d", status);
Mikhail Naganovccc82112023-04-27 18:14:15 -0700273 }
274 if (status_t status = filterAndUpdateBtHfpParameters(parameters); status != OK) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530275 AUGMENT_LOG(W, "filterAndUpdateBtHfpParameters failed: %d", status);
Mikhail Naganovccc82112023-04-27 18:14:15 -0700276 }
277 if (status_t status = filterAndUpdateBtLeParameters(parameters); status != OK) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530278 AUGMENT_LOG(W, "filterAndUpdateBtLeParameters failed: %d", status);
Mikhail Naganovccc82112023-04-27 18:14:15 -0700279 }
280 if (status_t status = filterAndUpdateBtScoParameters(parameters); status != OK) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530281 AUGMENT_LOG(W, "filterAndUpdateBtScoParameters failed: %d", status);
Mikhail Naganovccc82112023-04-27 18:14:15 -0700282 }
Mikhail Naganove92c34b2023-05-31 14:24:48 -0700283 if (status_t status = filterAndUpdateScreenParameters(parameters); status != OK) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530284 AUGMENT_LOG(W, "filterAndUpdateScreenParameters failed: %d", status);
Mikhail Naganove92c34b2023-05-31 14:24:48 -0700285 }
Mikhail Naganovb9a81312023-07-18 13:55:34 -0700286 if (status_t status = filterAndUpdateTelephonyParameters(parameters); status != OK) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530287 AUGMENT_LOG(W, "filterAndUpdateTelephonyParameters failed: %d", status);
Mikhail Naganovb9a81312023-07-18 13:55:34 -0700288 }
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700289 return parseAndSetVendorParameters(mVendorExt, mModule, parameters);
Shunkai Yao51202502022-12-12 06:11:46 +0000290}
291
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700292status_t DeviceHalAidl::getParameters(const String8& keys, String8 *values) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530293 AUGMENT_LOG(D, "keys: \"%s\"", keys.c_str());
294
Mikhail Naganov31d46652023-01-10 18:29:25 +0000295 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530296 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700297 if (values == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530298 AUGMENT_LOG(E, "invalid values");
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700299 return BAD_VALUE;
300 }
301 AudioParameter parameterKeys(keys), result;
302 if (status_t status = filterAndRetrieveBtA2dpParameters(parameterKeys, &result); status != OK) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530303 AUGMENT_LOG(W, "filterAndRetrieveBtA2dpParameters failed: %d", status);
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700304 }
Eric Laurent7e3c0832023-11-30 15:04:50 +0100305 if (status_t status = filterAndRetrieveBtLeParameters(parameterKeys, &result); status != OK) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530306 AUGMENT_LOG(W, "filterAndRetrieveBtLeParameters failed: %d", status);
Eric Laurent7e3c0832023-11-30 15:04:50 +0100307 }
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700308 *values = result.toString();
309 return parseAndGetVendorParameters(mVendorExt, mModule, parameterKeys, values);
Shunkai Yao51202502022-12-12 06:11:46 +0000310}
311
Mikhail Naganovd5b643f2024-02-15 11:51:26 -0800312status_t DeviceHalAidl::getInputBufferSize(struct audio_config* config, size_t* size) {
Shunkai Yao35665b12024-08-21 00:30:54 +0000313 AUGMENT_LOG(D);
Jaideep Sharma145313e2024-08-14 14:51:24 +0530314
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800315 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530316 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700317 if (config == nullptr || size == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530318 AUGMENT_LOG(E, "invalid config or size");
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700319 return BAD_VALUE;
320 }
Mikhail Naganovd5b643f2024-02-15 11:51:26 -0800321 constexpr bool isInput = true;
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800322 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
Mikhail Naganovd5b643f2024-02-15 11:51:26 -0800323 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, isInput));
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800324 AudioDevice aidlDevice;
325 aidlDevice.type.type = AudioDeviceType::IN_DEFAULT;
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800326 AudioSource aidlSource = AudioSource::DEFAULT;
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800327 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::input>(0);
328 AudioPortConfig mixPortConfig;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700329 Hal2AidlMapper::Cleanups cleanups(mMapperAccessor);
Mikhail Naganove93a0862023-03-15 17:06:59 -0700330 AudioPatch aidlPatch;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700331 {
332 std::lock_guard l(mLock);
333 RETURN_STATUS_IF_ERROR(mMapper.prepareToOpenStream(
334 0 /*handle*/, aidlDevice, aidlFlags, aidlSource,
335 &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
336 }
Mikhail Naganovd5b643f2024-02-15 11:51:26 -0800337 *config = VALUE_OR_RETURN_STATUS(
338 ::aidl::android::aidl2legacy_AudioConfig_audio_config_t(aidlConfig, isInput));
339 if (mixPortConfig.id == 0) return BAD_VALUE; // HAL suggests a different config.
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800340 *size = aidlConfig.frameCount *
341 getFrameSizeInBytes(aidlConfig.base.format, aidlConfig.base.channelMask);
342 // Do not disarm cleanups to release temporary port configs.
343 return OK;
344}
345
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800346namespace {
347
348class StreamCallbackBase {
349 protected:
350 explicit StreamCallbackBase(const sp<CallbackBroker>& broker) : mBroker(broker) {}
351 public:
352 void* getCookie() const { return mCookie; }
353 void setCookie(void* cookie) { mCookie = cookie; }
354 sp<CallbackBroker> getBroker() const {
355 if (void* cookie = mCookie; cookie != nullptr) return mBroker.promote();
356 return nullptr;
357 }
358 private:
359 const wp<CallbackBroker> mBroker;
360 std::atomic<void*> mCookie;
361};
362
363template<class C>
364class StreamCallbackBaseHelper {
365 protected:
366 explicit StreamCallbackBaseHelper(const StreamCallbackBase& base) : mBase(base) {}
367 sp<C> getCb(const sp<CallbackBroker>& broker, void* cookie);
368 using CbRef = const sp<C>&;
369 ndk::ScopedAStatus runCb(const std::function<void(CbRef cb)>& f) {
370 if (auto cb = getCb(mBase.getBroker(), mBase.getCookie()); cb != nullptr) f(cb);
371 return ndk::ScopedAStatus::ok();
372 }
373 private:
374 const StreamCallbackBase& mBase;
375};
376
377template<>
378sp<StreamOutHalInterfaceCallback> StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>::getCb(
379 const sp<CallbackBroker>& broker, void* cookie) {
380 if (broker != nullptr) return broker->getStreamOutCallback(cookie);
381 return nullptr;
382}
383
384template<>
385sp<StreamOutHalInterfaceEventCallback>
386StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>::getCb(
387 const sp<CallbackBroker>& broker, void* cookie) {
388 if (broker != nullptr) return broker->getStreamOutEventCallback(cookie);
389 return nullptr;
390}
391
392template<>
393sp<StreamOutHalInterfaceLatencyModeCallback>
394StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>::getCb(
395 const sp<CallbackBroker>& broker, void* cookie) {
396 if (broker != nullptr) return broker->getStreamOutLatencyModeCallback(cookie);
397 return nullptr;
398}
399
400/*
401Note on the callback ownership.
402
403In the Binder ownership model, the server implementation is kept alive
404as long as there is any client (proxy object) alive. This is done by
405incrementing the refcount of the server-side object by the Binder framework.
406When it detects that the last client is gone, it decrements the refcount back.
407
408Thus, it is not needed to keep any references to StreamCallback on our
409side (after we have sent an instance to the client), because we are
410the server-side. The callback object will be kept alive as long as the HAL server
411holds a strong ref to IStreamCallback proxy.
412*/
413
414class OutputStreamCallbackAidl : public StreamCallbackBase,
415 public StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>,
416 public ::aidl::android::hardware::audio::core::BnStreamCallback {
417 public:
418 explicit OutputStreamCallbackAidl(const sp<CallbackBroker>& broker)
419 : StreamCallbackBase(broker),
420 StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>(
421 *static_cast<StreamCallbackBase*>(this)) {}
422 ndk::ScopedAStatus onTransferReady() override {
423 return runCb([](CbRef cb) { cb->onWriteReady(); });
424 }
425 ndk::ScopedAStatus onError() override {
Mikhail Naganovbf203ce2024-05-23 16:27:59 -0700426 return runCb([](CbRef cb) { cb->onError(true /*isHardError*/); });
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800427 }
428 ndk::ScopedAStatus onDrainReady() override {
429 return runCb([](CbRef cb) { cb->onDrainReady(); });
430 }
431};
432
433class OutputStreamEventCallbackAidl :
434 public StreamCallbackBase,
435 public StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>,
436 public StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>,
437 public ::aidl::android::hardware::audio::core::BnStreamOutEventCallback {
438 public:
439 explicit OutputStreamEventCallbackAidl(const sp<CallbackBroker>& broker)
440 : StreamCallbackBase(broker),
441 StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>(
442 *static_cast<StreamCallbackBase*>(this)),
443 StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>(
444 *static_cast<StreamCallbackBase*>(this)) {}
Ryan Prichard78c5e452024-02-08 16:16:57 -0800445 ndk::ScopedAStatus onCodecFormatChanged(const std::vector<uint8_t>& halMetadata) override {
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800446 return StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>::runCb(
447 [&halMetadata](auto cb) { cb->onCodecFormatChanged(halMetadata); });
448 }
449 ndk::ScopedAStatus onRecommendedLatencyModeChanged(
450 const std::vector<AudioLatencyMode>& in_modes) override {
451 auto halModes = VALUE_OR_FATAL(
452 ::aidl::android::convertContainer<std::vector<audio_latency_mode_t>>(
453 in_modes,
454 ::aidl::android::aidl2legacy_AudioLatencyMode_audio_latency_mode_t));
455 return StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>::runCb(
456 [&halModes](auto cb) { cb->onRecommendedLatencyModeChanged(halModes); });
457 }
458};
459
460} // namespace
461
Mikhail Naganov31d46652023-01-10 18:29:25 +0000462status_t DeviceHalAidl::openOutputStream(
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800463 audio_io_handle_t handle, audio_devices_t devices,
464 audio_output_flags_t flags, struct audio_config* config,
465 const char* address,
Haofan Wangbf44e092024-07-07 15:29:38 -0700466 sp<StreamOutHalInterface>* outStream,
467 const std::vector<playback_track_metadata_v7_t>& sourceMetadata) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530468 AUGMENT_LOG(D, "handle: %d devices %0x flags %0x", handle, devices, flags);
Shunkai Yao35665b12024-08-21 00:30:54 +0000469
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700470 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530471 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700472 if (outStream == nullptr || config == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530473 AUGMENT_LOG(E, "invalid outStream or config");
Mikhail Naganov31d46652023-01-10 18:29:25 +0000474 return BAD_VALUE;
475 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700476 constexpr bool isInput = false;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800477 int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
478 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(handle));
479 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700480 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, isInput));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800481 AudioDevice aidlDevice = VALUE_OR_RETURN_STATUS(
482 ::aidl::android::legacy2aidl_audio_device_AudioDevice(devices, address));
483 int32_t aidlOutputFlags = VALUE_OR_RETURN_STATUS(
484 ::aidl::android::legacy2aidl_audio_output_flags_t_int32_t_mask(flags));
Haofan Wangbf44e092024-07-07 15:29:38 -0700485 SourceMetadata aidlMetadata = VALUE_OR_RETURN_STATUS(
Haofan Wang9b390862024-08-22 17:44:59 +0000486 ::aidl::android::legacy2aidl_playback_track_metadata_v7_SourceMetadata(sourceMetadata));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800487 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::output>(aidlOutputFlags);
488 AudioPortConfig mixPortConfig;
Mikhail Naganove93a0862023-03-15 17:06:59 -0700489 AudioPatch aidlPatch;
Haofan Wangbf44e092024-07-07 15:29:38 -0700490
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700491 Hal2AidlMapper::Cleanups cleanups(mMapperAccessor);
492 {
493 std::lock_guard l(mLock);
494 RETURN_STATUS_IF_ERROR(mMapper.prepareToOpenStream(aidlHandle, aidlDevice, aidlFlags,
495 AudioSource::SYS_RESERVED_INVALID /*only needed for input*/,
496 &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
497 }
498 *config = VALUE_OR_RETURN_STATUS(
499 ::aidl::android::aidl2legacy_AudioConfig_audio_config_t(aidlConfig, isInput));
Mikhail Naganovca92a5c2023-12-07 14:00:48 -0800500 if (mixPortConfig.id == 0) return BAD_VALUE; // HAL suggests a different config.
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800501 ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamArguments args;
502 args.portConfigId = mixPortConfig.id;
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800503 const bool isOffload = isBitPositionFlagSet(
504 aidlOutputFlags, AudioOutputFlags::COMPRESS_OFFLOAD);
Kuowei Li3b9a69d2024-06-07 17:54:32 +0800505 const bool isHwAvSync = isBitPositionFlagSet(
506 aidlOutputFlags, AudioOutputFlags::HW_AV_SYNC);
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800507 std::shared_ptr<OutputStreamCallbackAidl> streamCb;
508 if (isOffload) {
509 streamCb = ndk::SharedRefBase::make<OutputStreamCallbackAidl>(this);
Andy Hungab659d62024-09-24 20:51:07 -0700510 ndk::SpAIBinder binder = streamCb->asBinder();
511 AIBinder_setMinSchedulerPolicy(binder.get(), SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
512 AIBinder_setInheritRt(binder.get(), true);
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800513 }
514 auto eventCb = ndk::SharedRefBase::make<OutputStreamEventCallbackAidl>(this);
Andy Hungab659d62024-09-24 20:51:07 -0700515 ndk::SpAIBinder binder = eventCb->asBinder();
516 AIBinder_setMinSchedulerPolicy(binder.get(), SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
517 AIBinder_setInheritRt(binder.get(), true);
518
Kuowei Li3b9a69d2024-06-07 17:54:32 +0800519 if (isOffload || isHwAvSync) {
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800520 args.offloadInfo = aidlConfig.offloadInfo;
Kuowei Li3b9a69d2024-06-07 17:54:32 +0800521 }
522 if (isOffload) {
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800523 args.callback = streamCb;
524 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800525 args.bufferSizeFrames = aidlConfig.frameCount;
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800526 args.eventCallback = eventCb;
Haofan Wangbf44e092024-07-07 15:29:38 -0700527 args.sourceMetadata = aidlMetadata;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800528 ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamReturn ret;
529 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openOutputStream(args, &ret)));
Jaideep Sharma145313e2024-08-14 14:51:24 +0530530 StreamContextAidl context(ret.desc, isOffload, aidlHandle);
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800531 if (!context.isValid()) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530532 AUGMENT_LOG(E, "Failed to created a valid stream context from the descriptor: %s",
533 ret.desc.toString().c_str());
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800534 return NO_INIT;
535 }
Mikhail Naganov8065bfd2024-03-25 14:59:49 -0700536 auto stream = sp<StreamOutHalAidl>::make(*config, std::move(context), aidlPatch.latenciesMs[0],
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700537 std::move(ret.stream), mVendorExt, this /*callbackBroker*/);
Mikhail Naganov8065bfd2024-03-25 14:59:49 -0700538 *outStream = stream;
539 /* StreamOutHalInterface* */ void* cbCookie = (*outStream).get();
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800540 {
Mikhail Naganov22578412024-08-16 16:50:34 -0700541 std::lock_guard l(mCallbacksLock);
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800542 mCallbacks.emplace(cbCookie, Callbacks{});
Mikhail Naganov22578412024-08-16 16:50:34 -0700543 }
544 {
545 std::lock_guard l(mLock);
Mikhail Naganov78f7f9a2023-11-16 15:49:23 -0800546 mMapper.addStream(*outStream, mixPortConfig.id, aidlPatch.id);
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800547 }
Mikhail Naganov8065bfd2024-03-25 14:59:49 -0700548 if (streamCb) {
549 streamCb->setCookie(cbCookie);
550 // Although StreamOutHalAidl implements StreamOutHalInterfaceCallback,
551 // we always go via the CallbackBroker for consistency.
552 setStreamOutCallback(cbCookie, stream);
553 }
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800554 eventCb->setCookie(cbCookie);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800555 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000556 return OK;
557}
558
Mikhail Naganov31d46652023-01-10 18:29:25 +0000559status_t DeviceHalAidl::openInputStream(
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800560 audio_io_handle_t handle, audio_devices_t devices,
561 struct audio_config* config, audio_input_flags_t flags,
562 const char* address, audio_source_t source,
563 audio_devices_t outputDevice, const char* outputDeviceAddress,
Mikhail Naganov31d46652023-01-10 18:29:25 +0000564 sp<StreamInHalInterface>* inStream) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530565 AUGMENT_LOG(D, "handle: %d devices %0x flags %0x", handle, devices, flags);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700566 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530567 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700568 if (inStream == nullptr || config == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530569 AUGMENT_LOG(E, "invalid inStream or config");
Mikhail Naganov31d46652023-01-10 18:29:25 +0000570 return BAD_VALUE;
571 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700572 constexpr bool isInput = true;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800573 int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
574 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(handle));
575 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700576 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, isInput));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800577 AudioDevice aidlDevice = VALUE_OR_RETURN_STATUS(
578 ::aidl::android::legacy2aidl_audio_device_AudioDevice(devices, address));
579 int32_t aidlInputFlags = VALUE_OR_RETURN_STATUS(
580 ::aidl::android::legacy2aidl_audio_input_flags_t_int32_t_mask(flags));
581 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::input>(aidlInputFlags);
582 AudioSource aidlSource = VALUE_OR_RETURN_STATUS(
583 ::aidl::android::legacy2aidl_audio_source_t_AudioSource(source));
584 AudioPortConfig mixPortConfig;
Mikhail Naganove93a0862023-03-15 17:06:59 -0700585 AudioPatch aidlPatch;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700586 Hal2AidlMapper::Cleanups cleanups(mMapperAccessor);
587 {
588 std::lock_guard l(mLock);
589 RETURN_STATUS_IF_ERROR(mMapper.prepareToOpenStream(
590 aidlHandle, aidlDevice, aidlFlags, aidlSource,
591 &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
592 }
593 *config = VALUE_OR_RETURN_STATUS(
594 ::aidl::android::aidl2legacy_AudioConfig_audio_config_t(aidlConfig, isInput));
Mikhail Naganovca92a5c2023-12-07 14:00:48 -0800595 if (mixPortConfig.id == 0) return BAD_VALUE; // HAL suggests a different config.
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800596 ::aidl::android::hardware::audio::core::IModule::OpenInputStreamArguments args;
597 args.portConfigId = mixPortConfig.id;
598 RecordTrackMetadata aidlTrackMetadata{
599 .source = aidlSource, .gain = 1, .channelMask = aidlConfig.base.channelMask };
600 if (outputDevice != AUDIO_DEVICE_NONE) {
601 aidlTrackMetadata.destinationDevice = VALUE_OR_RETURN_STATUS(
602 ::aidl::android::legacy2aidl_audio_device_AudioDevice(
603 outputDevice, outputDeviceAddress));
604 }
605 args.sinkMetadata.tracks.push_back(std::move(aidlTrackMetadata));
606 args.bufferSizeFrames = aidlConfig.frameCount;
607 ::aidl::android::hardware::audio::core::IModule::OpenInputStreamReturn ret;
608 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openInputStream(args, &ret)));
Jaideep Sharma145313e2024-08-14 14:51:24 +0530609 StreamContextAidl context(ret.desc, false /*isAsynchronous*/, aidlHandle);
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800610 if (!context.isValid()) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530611 AUGMENT_LOG(E, "Failed to created a valid stream context from the descriptor: %s",
612 ret.desc.toString().c_str());
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800613 return NO_INIT;
614 }
Mikhail Naganove93a0862023-03-15 17:06:59 -0700615 *inStream = sp<StreamInHalAidl>::make(*config, std::move(context), aidlPatch.latenciesMs[0],
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700616 std::move(ret.stream), mVendorExt, this /*micInfoProvider*/);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700617 {
618 std::lock_guard l(mLock);
Mikhail Naganov78f7f9a2023-11-16 15:49:23 -0800619 mMapper.addStream(*inStream, mixPortConfig.id, aidlPatch.id);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700620 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800621 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000622 return OK;
623}
624
625status_t DeviceHalAidl::supportsAudioPatches(bool* supportsPatches) {
Shunkai Yao35665b12024-08-21 00:30:54 +0000626 AUGMENT_LOG(V);
Jaideep Sharma145313e2024-08-14 14:51:24 +0530627 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700628 if (supportsPatches == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530629 AUGMENT_LOG(E, "uninitialized supportsPatches");
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700630 return BAD_VALUE;
631 }
Shunkai Yao51202502022-12-12 06:11:46 +0000632 *supportsPatches = true;
633 return OK;
634}
635
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800636status_t DeviceHalAidl::createAudioPatch(unsigned int num_sources,
637 const struct audio_port_config* sources,
638 unsigned int num_sinks,
639 const struct audio_port_config* sinks,
640 audio_patch_handle_t* patch) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530641 AUGMENT_LOG(D, "sources: %d sinks %d", num_sources, num_sinks);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000642 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530643 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
644 if (num_sinks > AUDIO_PATCH_PORTS_MAX || num_sources > AUDIO_PATCH_PORTS_MAX) {
645 AUGMENT_LOG(E, "invalid sources %d or sinks %d ", num_sources, num_sinks);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800646 return BAD_VALUE;
647 }
Jaideep Sharma145313e2024-08-14 14:51:24 +0530648
649 if (sources == nullptr || sinks == nullptr || patch == nullptr) {
650 AUGMENT_LOG(E, "uninitialized sources %d or sinks %d or patches %d", (sources == nullptr),
651 (sinks == nullptr), (patch == nullptr));
652 return BAD_VALUE;
653 }
654
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800655 // When the patch handle (*patch) is AUDIO_PATCH_HANDLE_NONE, it means
656 // the framework wants to create a new patch. The handle has to be generated
657 // by the HAL. Since handles generated this way can only be unique within
658 // a HAL module, the framework generates a globally unique handle, and maps
659 // it on the <HAL module, patch handle> pair.
660 // When the patch handle is set, it meant the framework intends to update
661 // an existing patch.
662 //
663 // This behavior corresponds to HAL module behavior, with the only difference
664 // that the HAL module uses `int32_t` for patch IDs. The following assert ensures
665 // that both the framework and the HAL use the same value for "no ID":
666 static_assert(AUDIO_PATCH_HANDLE_NONE == 0);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800667
668 // Upon conversion, mix port configs contain audio configuration, while
669 // device port configs contain device address. This data is used to find
670 // or create HAL configs.
671 std::vector<AudioPortConfig> aidlSources, aidlSinks;
672 for (unsigned int i = 0; i < num_sources; ++i) {
673 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
674 sources[i].role, sources[i].type)) ==
675 ::aidl::android::AudioPortDirection::INPUT;
676 aidlSources.push_back(VALUE_OR_RETURN_STATUS(
677 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
678 sources[i], isInput, 0)));
679 }
680 for (unsigned int i = 0; i < num_sinks; ++i) {
681 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
682 sinks[i].role, sinks[i].type)) ==
683 ::aidl::android::AudioPortDirection::INPUT;
684 aidlSinks.push_back(VALUE_OR_RETURN_STATUS(
685 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
686 sinks[i], isInput, 0)));
687 }
Mikhail Naganov6b5da722024-03-14 12:59:32 -0700688 int32_t aidlPatchId = static_cast<int32_t>(*patch);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700689 Hal2AidlMapper::Cleanups cleanups(mMapperAccessor);
690 {
691 std::lock_guard l(mLock);
Mikhail Naganov6b5da722024-03-14 12:59:32 -0700692 // Check for patches that only exist for the framework, or have different HAL patch ID.
693 if (int32_t aidlHalPatchId = mMapper.findFwkPatch(aidlPatchId); aidlHalPatchId != 0) {
694 if (aidlHalPatchId == aidlPatchId) {
695 // This patch was previously released by the HAL. Thus we need to pass '0'
696 // to the HAL to obtain a new patch.
697 int32_t newAidlPatchId = 0;
698 RETURN_STATUS_IF_ERROR(mMapper.createOrUpdatePatch(
699 aidlSources, aidlSinks, &newAidlPatchId, &cleanups));
700 mMapper.updateFwkPatch(aidlPatchId, newAidlPatchId);
701 } else {
702 RETURN_STATUS_IF_ERROR(mMapper.createOrUpdatePatch(
703 aidlSources, aidlSinks, &aidlHalPatchId, &cleanups));
704 }
705 } else {
706 RETURN_STATUS_IF_ERROR(mMapper.createOrUpdatePatch(
707 aidlSources, aidlSinks, &aidlPatchId, &cleanups));
708 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800709 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700710 *patch = static_cast<audio_patch_handle_t>(aidlPatchId);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800711 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000712 return OK;
713}
714
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800715status_t DeviceHalAidl::releaseAudioPatch(audio_patch_handle_t patch) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530716 AUGMENT_LOG(D, "patch: %d", patch);
717
Mikhail Naganov31d46652023-01-10 18:29:25 +0000718 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530719 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800720 static_assert(AUDIO_PATCH_HANDLE_NONE == 0);
721 if (patch == AUDIO_PATCH_HANDLE_NONE) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800722 return BAD_VALUE;
723 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700724 std::lock_guard l(mLock);
Mikhail Naganov6b5da722024-03-14 12:59:32 -0700725 // Check for patches that only exist for the framework, or have different HAL patch ID.
726 int32_t aidlPatchId = static_cast<int32_t>(patch);
727 if (int32_t aidlHalPatchId = mMapper.findFwkPatch(aidlPatchId); aidlHalPatchId != 0) {
728 if (aidlHalPatchId == aidlPatchId) {
729 // This patch was previously released by the HAL, just need to finish its removal.
730 mMapper.eraseFwkPatch(aidlPatchId);
731 return OK;
732 } else {
733 // This patch has a HAL patch ID which is different
734 aidlPatchId = aidlHalPatchId;
735 }
736 }
737 RETURN_STATUS_IF_ERROR(mMapper.releaseAudioPatch(aidlPatchId));
Shunkai Yao51202502022-12-12 06:11:46 +0000738 return OK;
739}
740
Mikhail Naganove93a0862023-03-15 17:06:59 -0700741status_t DeviceHalAidl::getAudioPort(struct audio_port* port) {
Shunkai Yao35665b12024-08-21 00:30:54 +0000742 AUGMENT_LOG(V);
Jaideep Sharma145313e2024-08-14 14:51:24 +0530743 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganove93a0862023-03-15 17:06:59 -0700744 if (port == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530745 AUGMENT_LOG(E, "port not initialized");
Mikhail Naganove93a0862023-03-15 17:06:59 -0700746 return BAD_VALUE;
747 }
748 audio_port_v7 portV7;
749 audio_populate_audio_port_v7(port, &portV7);
750 RETURN_STATUS_IF_ERROR(getAudioPort(&portV7));
751 return audio_populate_audio_port(&portV7, port) ? OK : BAD_VALUE;
752}
753
754status_t DeviceHalAidl::getAudioPort(struct audio_port_v7 *port) {
Shunkai Yao35665b12024-08-21 00:30:54 +0000755 AUGMENT_LOG(D);
Jaideep Sharma145313e2024-08-14 14:51:24 +0530756
Mikhail Naganove93a0862023-03-15 17:06:59 -0700757 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530758 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganove93a0862023-03-15 17:06:59 -0700759 if (port == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530760 AUGMENT_LOG(E, "port not initialized");
Mikhail Naganove93a0862023-03-15 17:06:59 -0700761 return BAD_VALUE;
762 }
763 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(port->role, port->type)) ==
764 ::aidl::android::AudioPortDirection::INPUT;
765 auto aidlPort = VALUE_OR_RETURN_STATUS(
766 ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
767 if (aidlPort.ext.getTag() != AudioPortExt::device) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530768 AUGMENT_LOG(E, "provided port is not a device port %s", aidlPort.toString().c_str());
Mikhail Naganove93a0862023-03-15 17:06:59 -0700769 return BAD_VALUE;
770 }
771 const auto& matchDevice = aidlPort.ext.get<AudioPortExt::device>().device;
772 // It seems that we don't have to call HAL since all valid ports have been added either
773 // during initialization, or while handling connection of an external device.
Mikhail Naganove93a0862023-03-15 17:06:59 -0700774 const int32_t fwkId = aidlPort.id;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700775 {
776 std::lock_guard l(mLock);
777 RETURN_STATUS_IF_ERROR(mMapper.getAudioPortCached(matchDevice, &aidlPort));
778 }
Mikhail Naganove93a0862023-03-15 17:06:59 -0700779 aidlPort.id = fwkId;
780 *port = VALUE_OR_RETURN_STATUS(::aidl::android::aidl2legacy_AudioPort_audio_port_v7(
781 aidlPort, isInput));
782 return OK;
783}
784
jiabin12537fc2023-10-12 17:56:08 +0000785status_t DeviceHalAidl::getAudioMixPort(const struct audio_port_v7 *devicePort,
786 struct audio_port_v7 *mixPort) {
Shunkai Yao35665b12024-08-21 00:30:54 +0000787 AUGMENT_LOG(D);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700788 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530789 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
790
791 if (devicePort == nullptr || mixPort == nullptr || devicePort->type != AUDIO_PORT_TYPE_DEVICE ||
792 mixPort->type != AUDIO_PORT_TYPE_MIX) {
793 AUGMENT_LOG(E, "invalid device or mix port");
jiabin12537fc2023-10-12 17:56:08 +0000794 return BAD_VALUE;
795 }
796 const int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
797 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(mixPort->ext.mix.handle));
jiabin12537fc2023-10-12 17:56:08 +0000798 AudioPort port;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700799 {
800 std::lock_guard l(mLock);
801 RETURN_STATUS_IF_ERROR(mMapper.getAudioMixPort(aidlHandle, &port));
jiabin12537fc2023-10-12 17:56:08 +0000802 }
803 const bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
804 mixPort->role, mixPort->type)) == ::aidl::android::AudioPortDirection::INPUT;
805 *mixPort = VALUE_OR_RETURN_STATUS(::aidl::android::aidl2legacy_AudioPort_audio_port_v7(
806 port, isInput));
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700807 return OK;
jiabin12537fc2023-10-12 17:56:08 +0000808}
809
Mikhail Naganove93a0862023-03-15 17:06:59 -0700810status_t DeviceHalAidl::setAudioPortConfig(const struct audio_port_config* config) {
Shunkai Yao35665b12024-08-21 00:30:54 +0000811 AUGMENT_LOG(D);
Jaideep Sharma145313e2024-08-14 14:51:24 +0530812
Mikhail Naganove93a0862023-03-15 17:06:59 -0700813 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530814 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganove93a0862023-03-15 17:06:59 -0700815 if (config == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530816 AUGMENT_LOG(E, "config not initialized");
Mikhail Naganove93a0862023-03-15 17:06:59 -0700817 return BAD_VALUE;
818 }
819 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
820 config->role, config->type)) == ::aidl::android::AudioPortDirection::INPUT;
821 AudioPortConfig requestedPortConfig = VALUE_OR_RETURN_STATUS(
822 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
823 *config, isInput, 0 /*portId*/));
824 AudioPortConfig portConfig;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700825 std::lock_guard l(mLock);
Mikhail Naganovca92a5c2023-12-07 14:00:48 -0800826 return mMapper.setPortConfig(requestedPortConfig, std::set<int32_t>(), &portConfig);
Shunkai Yao51202502022-12-12 06:11:46 +0000827}
828
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800829MicrophoneInfoProvider::Info const* DeviceHalAidl::getMicrophoneInfo() {
Shunkai Yao35665b12024-08-21 00:30:54 +0000830 AUGMENT_LOG(D);
Jaideep Sharma145313e2024-08-14 14:51:24 +0530831
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700832 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530833 RETURN_IF_MODULE_NOT_INIT({});
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700834 std::lock_guard l(mLock);
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800835 if (mMicrophones.status == Microphones::Status::UNKNOWN) {
836 TIME_CHECK();
837 std::vector<MicrophoneInfo> aidlInfo;
838 status_t status = statusTFromBinderStatus(mModule->getMicrophones(&aidlInfo));
839 if (status == OK) {
840 mMicrophones.status = Microphones::Status::QUERIED;
841 mMicrophones.info = std::move(aidlInfo);
842 } else if (status == INVALID_OPERATION) {
843 mMicrophones.status = Microphones::Status::NOT_SUPPORTED;
844 } else {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530845 AUGMENT_LOG(E, "Unexpected status from HAL: %d", status);
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800846 return {};
847 }
848 }
849 if (mMicrophones.status == Microphones::Status::QUERIED) {
850 return &mMicrophones.info;
851 }
852 return {}; // NOT_SUPPORTED
853}
854
Shunkai Yao51202502022-12-12 06:11:46 +0000855status_t DeviceHalAidl::getMicrophones(
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800856 std::vector<audio_microphone_characteristic_t>* microphones) {
Shunkai Yao35665b12024-08-21 00:30:54 +0000857 AUGMENT_LOG(D);
Jaideep Sharma145313e2024-08-14 14:51:24 +0530858
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700859 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530860 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700861 if (microphones == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530862 AUGMENT_LOG(E, "microphones not initialized");
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800863 return BAD_VALUE;
864 }
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800865 auto staticInfo = getMicrophoneInfo();
866 if (!staticInfo) return INVALID_OPERATION;
867 std::vector<MicrophoneDynamicInfo> emptyDynamicInfo;
868 emptyDynamicInfo.reserve(staticInfo->size());
869 std::transform(staticInfo->begin(), staticInfo->end(), std::back_inserter(emptyDynamicInfo),
870 [](const auto& info) { return MicrophoneDynamicInfo{ .id = info.id }; });
871 *microphones = VALUE_OR_RETURN_STATUS(
872 ::aidl::android::convertContainers<std::vector<audio_microphone_characteristic_t>>(
873 *staticInfo, emptyDynamicInfo,
874 ::aidl::android::aidl2legacy_MicrophoneInfos_audio_microphone_characteristic_t)
875 );
Shunkai Yao51202502022-12-12 06:11:46 +0000876 return OK;
877}
878
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700879status_t DeviceHalAidl::addDeviceEffect(
880 const struct audio_port_config *device, sp<EffectHalInterface> effect) {
Shunkai Yao35665b12024-08-21 00:30:54 +0000881 AUGMENT_LOG(D);
Jaideep Sharma145313e2024-08-14 14:51:24 +0530882
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700883 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530884 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700885 if (device == nullptr || effect == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530886 AUGMENT_LOG(E, "device or effect not initialized");
Shunkai Yao51202502022-12-12 06:11:46 +0000887 return BAD_VALUE;
888 }
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700889 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
890 device->role, device->type)) == ::aidl::android::AudioPortDirection::INPUT;
891 auto requestedPortConfig = VALUE_OR_RETURN_STATUS(
892 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
893 *device, isInput, 0));
894 if (requestedPortConfig.ext.getTag() != AudioPortExt::Tag::device) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530895 AUGMENT_LOG(E, "provided port config is not a device port config: %s",
896 requestedPortConfig.toString().c_str());
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700897 return BAD_VALUE;
898 }
899 AudioPortConfig devicePortConfig;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700900 Hal2AidlMapper::Cleanups cleanups(mMapperAccessor);
901 {
902 std::lock_guard l(mLock);
Mikhail Naganovca92a5c2023-12-07 14:00:48 -0800903 RETURN_STATUS_IF_ERROR(mMapper.setPortConfig(
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700904 requestedPortConfig, {} /*destinationPortIds*/, &devicePortConfig, &cleanups));
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700905 }
906 auto aidlEffect = sp<effect::EffectHalAidl>::cast(effect);
907 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->addDeviceEffect(
908 devicePortConfig.id, aidlEffect->getIEffect())));
909 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000910 return OK;
911}
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700912status_t DeviceHalAidl::removeDeviceEffect(
913 const struct audio_port_config *device, sp<EffectHalInterface> effect) {
Shunkai Yao35665b12024-08-21 00:30:54 +0000914 AUGMENT_LOG(D);
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700915 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530916 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700917 if (device == nullptr || effect == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530918 AUGMENT_LOG(E, "device or effect not initialized");
Shunkai Yao51202502022-12-12 06:11:46 +0000919 return BAD_VALUE;
920 }
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700921 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
922 device->role, device->type)) == ::aidl::android::AudioPortDirection::INPUT;
923 auto requestedPortConfig = VALUE_OR_RETURN_STATUS(
924 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
925 *device, isInput, 0));
926 if (requestedPortConfig.ext.getTag() != AudioPortExt::Tag::device) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530927 AUGMENT_LOG(E, "provided port config is not a device port config: %s",
928 requestedPortConfig.toString().c_str());
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700929 return BAD_VALUE;
930 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700931 AudioPortConfig devicePortConfig;
932 {
933 std::lock_guard l(mLock);
934 RETURN_STATUS_IF_ERROR(mMapper.findPortConfig(
935 requestedPortConfig.ext.get<AudioPortExt::Tag::device>().device,
936 &devicePortConfig));
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700937 }
938 auto aidlEffect = sp<effect::EffectHalAidl>::cast(effect);
939 return statusTFromBinderStatus(mModule->removeDeviceEffect(
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700940 devicePortConfig.id, aidlEffect->getIEffect()));
Shunkai Yao51202502022-12-12 06:11:46 +0000941}
942
943status_t DeviceHalAidl::getMmapPolicyInfos(
David Li9cf5e622023-03-21 00:51:10 +0800944 media::audio::common::AudioMMapPolicyType policyType,
945 std::vector<media::audio::common::AudioMMapPolicyInfo>* policyInfos) {
Shunkai Yao35665b12024-08-21 00:30:54 +0000946 AUGMENT_LOG(D);
Jaideep Sharma145313e2024-08-14 14:51:24 +0530947
Mikhail Naganov31d46652023-01-10 18:29:25 +0000948 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530949 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
950
951 AudioMMapPolicyType mmapPolicyType =
952 VALUE_OR_RETURN_STATUS(cpp2ndk_AudioMMapPolicyType(policyType));
David Li9cf5e622023-03-21 00:51:10 +0800953
954 std::vector<AudioMMapPolicyInfo> mmapPolicyInfos;
955
956 if (status_t status = statusTFromBinderStatus(
957 mModule->getMmapPolicyInfos(mmapPolicyType, &mmapPolicyInfos)); status != OK) {
958 return status;
959 }
960
961 *policyInfos = VALUE_OR_RETURN_STATUS(
962 convertContainer<std::vector<media::audio::common::AudioMMapPolicyInfo>>(
963 mmapPolicyInfos, ndk2cpp_AudioMMapPolicyInfo));
Shunkai Yao51202502022-12-12 06:11:46 +0000964 return OK;
965}
966
967int32_t DeviceHalAidl::getAAudioMixerBurstCount() {
Shunkai Yao35665b12024-08-21 00:30:54 +0000968 AUGMENT_LOG(D);
Jaideep Sharma145313e2024-08-14 14:51:24 +0530969
Mikhail Naganov31d46652023-01-10 18:29:25 +0000970 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530971 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
David Li9cf5e622023-03-21 00:51:10 +0800972 int32_t mixerBurstCount = 0;
973 if (mModule->getAAudioMixerBurstCount(&mixerBurstCount).isOk()) {
974 return mixerBurstCount;
975 }
976 return 0;
Shunkai Yao51202502022-12-12 06:11:46 +0000977}
978
979int32_t DeviceHalAidl::getAAudioHardwareBurstMinUsec() {
Shunkai Yao35665b12024-08-21 00:30:54 +0000980 AUGMENT_LOG(D);
Jaideep Sharma145313e2024-08-14 14:51:24 +0530981
Mikhail Naganov31d46652023-01-10 18:29:25 +0000982 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530983 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
David Li9cf5e622023-03-21 00:51:10 +0800984 int32_t hardwareBurstMinUsec = 0;
985 if (mModule->getAAudioHardwareBurstMinUsec(&hardwareBurstMinUsec).isOk()) {
986 return hardwareBurstMinUsec;
987 }
988 return 0;
Shunkai Yao51202502022-12-12 06:11:46 +0000989}
990
991error::Result<audio_hw_sync_t> DeviceHalAidl::getHwAvSync() {
Shunkai Yao35665b12024-08-21 00:30:54 +0000992 AUGMENT_LOG(D);
Jaideep Sharma145313e2024-08-14 14:51:24 +0530993
Mikhail Naganov31d46652023-01-10 18:29:25 +0000994 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530995 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganov08a62ab2023-03-14 17:11:51 -0700996 int32_t aidlHwAvSync;
997 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->generateHwAvSyncId(&aidlHwAvSync)));
998 return VALUE_OR_RETURN_STATUS(
999 ::aidl::android::aidl2legacy_int32_t_audio_hw_sync_t(aidlHwAvSync));
Shunkai Yao51202502022-12-12 06:11:46 +00001000}
1001
Mikhail Naganovfab697c2023-01-11 19:33:13 +00001002status_t DeviceHalAidl::dump(int fd, const Vector<String16>& args) {
1003 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -07001004 if (mModule == nullptr) return NO_INIT;
David Li21289462024-04-17 01:09:23 +08001005 Vector<String16> newArgs = args;
1006 newArgs.push(String16(kDumpFromAudioServerArgument));
1007 return mModule->dump(fd, Args(newArgs).args(), newArgs.size());
David Li9cf5e622023-03-21 00:51:10 +08001008}
Shunkai Yao51202502022-12-12 06:11:46 +00001009
Eric Laurent7af6ee72023-06-29 11:44:54 +02001010status_t DeviceHalAidl::supportsBluetoothVariableLatency(bool* supports) {
Shunkai Yao35665b12024-08-21 00:30:54 +00001011 AUGMENT_LOG(D);
Jaideep Sharma145313e2024-08-14 14:51:24 +05301012
Mikhail Naganov31d46652023-01-10 18:29:25 +00001013 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +05301014 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganov3ac95c92023-04-12 13:14:30 -07001015 if (supports == nullptr) {
1016 return BAD_VALUE;
1017 }
1018 return statusTFromBinderStatus(mModule->supportsVariableLatency(supports));
Shunkai Yao51202502022-12-12 06:11:46 +00001019}
Mikhail Naganov31d46652023-01-10 18:29:25 +00001020
Jaideep Sharma145313e2024-08-14 14:51:24 +05301021status_t DeviceHalAidl::getSoundDoseInterface([[maybe_unused]] const std::string& module,
1022 ::ndk::SpAIBinder* soundDoseBinder) {
Shunkai Yao35665b12024-08-21 00:30:54 +00001023 AUGMENT_LOG(V);
Jaideep Sharma145313e2024-08-14 14:51:24 +05301024 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
1025
Mikhail Naganovac9d4e72023-10-23 12:00:09 -07001026 if (soundDoseBinder == nullptr) {
1027 return BAD_VALUE;
1028 }
Vlad Popa03bd5bc2023-01-17 16:16:51 +01001029 if (mSoundDose == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +05301030 AUGMENT_LOG(E, "failed to retrieve the sound dose interface");
Mikhail Naganovac9d4e72023-10-23 12:00:09 -07001031 return BAD_VALUE;
Vlad Popa03bd5bc2023-01-17 16:16:51 +01001032 }
Vlad Popae1f33902023-10-30 19:48:25 -07001033
1034 if (mSoundDose == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +05301035 AUGMENT_LOG(E, "failed to return the sound dose interface not implemented");
Vlad Popae1f33902023-10-30 19:48:25 -07001036 return NO_INIT;
1037 }
1038
Vlad Popa03bd5bc2023-01-17 16:16:51 +01001039 *soundDoseBinder = mSoundDose->asBinder();
Jaideep Sharma145313e2024-08-14 14:51:24 +05301040 AUGMENT_LOG(I, "using audio AIDL HAL sound dose interface");
Vlad Popa03bd5bc2023-01-17 16:16:51 +01001041 return OK;
1042}
jiabin872de702023-04-27 22:04:31 +00001043
1044status_t DeviceHalAidl::prepareToDisconnectExternalDevice(const struct audio_port_v7* port) {
Shunkai Yao35665b12024-08-21 00:30:54 +00001045 AUGMENT_LOG(V);
jiabin62750c22023-12-21 22:06:07 +00001046 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +05301047 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
jiabin62750c22023-12-21 22:06:07 +00001048 if (port == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +05301049 AUGMENT_LOG(E, "port not initialized");
jiabin62750c22023-12-21 22:06:07 +00001050 return BAD_VALUE;
1051 }
Jaideep Sharma145313e2024-08-14 14:51:24 +05301052 const bool isInput =
1053 VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(port->role, port->type)) ==
1054 ::aidl::android::AudioPortDirection::INPUT;
jiabin62750c22023-12-21 22:06:07 +00001055 AudioPort aidlPort = VALUE_OR_RETURN_STATUS(
1056 ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
1057 if (aidlPort.ext.getTag() != AudioPortExt::device) {
Jaideep Sharma145313e2024-08-14 14:51:24 +05301058 AUGMENT_LOG(E, "provided port is not a device port: %s", aidlPort.toString().c_str());
jiabin62750c22023-12-21 22:06:07 +00001059 return BAD_VALUE;
1060 }
Jaideep Sharma145313e2024-08-14 14:51:24 +05301061
1062 AUGMENT_LOG(D, "device %s", aidlPort.toString().c_str());
1063
jiabin62750c22023-12-21 22:06:07 +00001064 status_t status = NO_ERROR;
1065 {
1066 std::lock_guard l(mLock);
1067 status = mMapper.prepareToDisconnectExternalDevice(aidlPort);
1068 }
1069 if (status == UNKNOWN_TRANSACTION) {
1070 // If there is not AIDL API defined for `prepareToDisconnectExternalDevice`.
1071 // Call `setConnectedState` instead.
1072 RETURN_STATUS_IF_ERROR(setConnectedState(port, false /*connected*/));
1073 std::lock_guard l(mLock);
1074 mDeviceDisconnectionNotified.insert(port->id);
1075 // Return that there was no error as otherwise the disconnection procedure will not be
1076 // considered complete for upper layers, and 'setConnectedState' will not be called again
1077 return OK;
1078 } else {
1079 return status;
1080 }
jiabin872de702023-04-27 22:04:31 +00001081}
1082
Mikhail Naganove93a0862023-03-15 17:06:59 -07001083status_t DeviceHalAidl::setConnectedState(const struct audio_port_v7 *port, bool connected) {
Shunkai Yao35665b12024-08-21 00:30:54 +00001084 AUGMENT_LOG(V);
Mikhail Naganove93a0862023-03-15 17:06:59 -07001085 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +05301086 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganove93a0862023-03-15 17:06:59 -07001087 if (port == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +05301088 AUGMENT_LOG(E, "port not initialized");
Mikhail Naganove93a0862023-03-15 17:06:59 -07001089 return BAD_VALUE;
1090 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -07001091 if (!connected) {
1092 std::lock_guard l(mLock);
1093 if (mDeviceDisconnectionNotified.erase(port->id) > 0) {
1094 // For device disconnection, APM will first call `prepareToDisconnectExternalDevice`
jiabin62750c22023-12-21 22:06:07 +00001095 // and then call `setConnectedState`. If `prepareToDisconnectExternalDevice` doesn't
1096 // exit, `setConnectedState` will be called when calling
1097 // `prepareToDisconnectExternalDevice`. Do not call to the HAL if previous call is
1098 // successful. Also remove the cache here to avoid a large cache after a long run.
Mikhail Naganovac9d4e72023-10-23 12:00:09 -07001099 return OK;
1100 }
jiabin872de702023-04-27 22:04:31 +00001101 }
Mikhail Naganove93a0862023-03-15 17:06:59 -07001102 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(port->role, port->type)) ==
1103 ::aidl::android::AudioPortDirection::INPUT;
1104 AudioPort aidlPort = VALUE_OR_RETURN_STATUS(
1105 ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
1106 if (aidlPort.ext.getTag() != AudioPortExt::device) {
Jaideep Sharma145313e2024-08-14 14:51:24 +05301107 AUGMENT_LOG(E, "provided port is not a device port: %s", aidlPort.toString().c_str());
Mikhail Naganove93a0862023-03-15 17:06:59 -07001108 return BAD_VALUE;
1109 }
Jaideep Sharma145313e2024-08-14 14:51:24 +05301110 AUGMENT_LOG(D, "connected %d port: %s", connected, aidlPort.toString().c_str());
Mikhail Naganovac9d4e72023-10-23 12:00:09 -07001111 std::lock_guard l(mLock);
1112 return mMapper.setDevicePortConnectedState(aidlPort, connected);
Mikhail Naganove93a0862023-03-15 17:06:59 -07001113}
1114
1115status_t DeviceHalAidl::setSimulateDeviceConnections(bool enabled) {
Shunkai Yao35665b12024-08-21 00:30:54 +00001116 AUGMENT_LOG(V);
Mikhail Naganove93a0862023-03-15 17:06:59 -07001117 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +05301118 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -07001119 {
1120 std::lock_guard l(mLock);
Mikhail Naganov6b5da722024-03-14 12:59:32 -07001121 mMapper.resetUnusedPatchesAndPortConfigs();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -07001122 }
Mikhail Naganove93a0862023-03-15 17:06:59 -07001123 ModuleDebug debug{ .simulateDeviceConnections = enabled };
1124 status_t status = statusTFromBinderStatus(mModule->setModuleDebug(debug));
1125 // This is important to log as it affects HAL behavior.
1126 if (status == OK) {
Jaideep Sharma145313e2024-08-14 14:51:24 +05301127 AUGMENT_LOG(I, "set enabled: %d", enabled);
Mikhail Naganove93a0862023-03-15 17:06:59 -07001128 } else {
Jaideep Sharma145313e2024-08-14 14:51:24 +05301129 AUGMENT_LOG(W, "set enabled to %d failed: %d", enabled, status);
Mikhail Naganove93a0862023-03-15 17:06:59 -07001130 }
1131 return status;
1132}
1133
Mikhail Naganove7a26ad2023-05-25 17:36:48 -07001134status_t DeviceHalAidl::filterAndRetrieveBtA2dpParameters(
1135 AudioParameter &keys, AudioParameter *result) {
Mikhail Naganove7a26ad2023-05-25 17:36:48 -07001136 if (String8 key = String8(AudioParameter::keyReconfigA2dpSupported); keys.containsKey(key)) {
1137 keys.remove(key);
David Lia7761ed2023-11-03 17:22:07 +00001138 if (mBluetoothA2dp != nullptr) {
1139 bool supports;
1140 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
1141 mBluetoothA2dp->supportsOffloadReconfiguration(&supports)));
1142 result->addInt(key, supports ? 1 : 0);
1143 } else {
Jaideep Sharma145313e2024-08-14 14:51:24 +05301144 AUGMENT_LOG(I, "no IBluetoothA2dp");
David Lia7761ed2023-11-03 17:22:07 +00001145 result->addInt(key, 0);
1146 }
Mikhail Naganove7a26ad2023-05-25 17:36:48 -07001147 }
1148 return OK;
1149}
1150
Eric Laurent7e3c0832023-11-30 15:04:50 +01001151status_t DeviceHalAidl::filterAndRetrieveBtLeParameters(
1152 AudioParameter &keys, AudioParameter *result) {
1153 if (String8 key = String8(AudioParameter::keyReconfigLeSupported); keys.containsKey(key)) {
1154 keys.remove(key);
1155 if (mBluetoothLe != nullptr) {
1156 bool supports;
1157 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
1158 mBluetoothLe->supportsOffloadReconfiguration(&supports)));
1159 result->addInt(key, supports ? 1 : 0);
1160 } else {
Jaideep Sharma145313e2024-08-14 14:51:24 +05301161 AUGMENT_LOG(I, "no mBluetoothLe");
Eric Laurent7e3c0832023-11-30 15:04:50 +01001162 result->addInt(key, 0);
1163 }
1164 }
1165 return OK;
1166}
1167
Mikhail Naganovccc82112023-04-27 18:14:15 -07001168status_t DeviceHalAidl::filterAndUpdateBtA2dpParameters(AudioParameter &parameters) {
Mikhail Naganovccc82112023-04-27 18:14:15 -07001169 std::optional<bool> a2dpEnabled;
Mikhail Naganove7a26ad2023-05-25 17:36:48 -07001170 std::optional<std::vector<VendorParameter>> reconfigureOffload;
Mikhail Naganovccc82112023-04-27 18:14:15 -07001171 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301172 parameters, String8(AudioParameter::keyBtA2dpSuspended),
1173 [&a2dpEnabled, this](const String8& trueOrFalse) {
1174 if (trueOrFalse == AudioParameter::valueTrue) {
1175 a2dpEnabled = false; // 'suspended' == true
1176 return OK;
1177 } else if (trueOrFalse == AudioParameter::valueFalse) {
1178 a2dpEnabled = true; // 'suspended' == false
1179 return OK;
1180 }
1181 AUGMENT_LOG(E, "setParameters: parameter key \"%s\" has invalid value \"%s\"",
1182 AudioParameter::keyBtA2dpSuspended, trueOrFalse.c_str());
1183 return BAD_VALUE;
1184 }));
Mikhail Naganove7a26ad2023-05-25 17:36:48 -07001185 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301186 parameters, String8(AudioParameter::keyReconfigA2dp),
1187 [&](const String8& value) -> status_t {
1188 std::vector<VendorParameter> result;
1189 RETURN_STATUS_IF_ERROR(
1190 statusTFromBinderStatus(mVendorExt->parseBluetoothA2dpReconfigureOffload(
1191 std::string(value.c_str()), &result)));
1192 reconfigureOffload = std::move(result);
1193 return OK;
1194 }));
Mikhail Naganovccc82112023-04-27 18:14:15 -07001195 if (mBluetoothA2dp != nullptr && a2dpEnabled.has_value()) {
1196 return statusTFromBinderStatus(mBluetoothA2dp->setEnabled(a2dpEnabled.value()));
1197 }
Mikhail Naganove7a26ad2023-05-25 17:36:48 -07001198 if (mBluetoothA2dp != nullptr && reconfigureOffload.has_value()) {
1199 return statusTFromBinderStatus(mBluetoothA2dp->reconfigureOffload(
1200 reconfigureOffload.value()));
1201 }
Mikhail Naganovccc82112023-04-27 18:14:15 -07001202 return OK;
1203}
1204
1205status_t DeviceHalAidl::filterAndUpdateBtHfpParameters(AudioParameter &parameters) {
Mikhail Naganovccc82112023-04-27 18:14:15 -07001206 IBluetooth::HfpConfig hfpConfig;
1207 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301208 parameters, String8(AudioParameter::keyBtHfpEnable),
1209 [&hfpConfig, this](const String8& trueOrFalse) {
1210 if (trueOrFalse == AudioParameter::valueTrue) {
1211 hfpConfig.isEnabled = Boolean{.value = true};
1212 return OK;
1213 } else if (trueOrFalse == AudioParameter::valueFalse) {
1214 hfpConfig.isEnabled = Boolean{.value = false};
1215 return OK;
1216 }
1217 AUGMENT_LOG(E, "setParameters: parameter key \"%s\" has invalid value \"%s\"",
1218 AudioParameter::keyBtHfpEnable, trueOrFalse.c_str());
1219 return BAD_VALUE;
1220 }));
Mikhail Naganovccc82112023-04-27 18:14:15 -07001221 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301222 parameters, String8(AudioParameter::keyBtHfpSamplingRate),
1223 [&hfpConfig](int sampleRate) {
1224 return sampleRate > 0 ? hfpConfig.sampleRate = Int{.value = sampleRate},
1225 OK : BAD_VALUE;
1226 }));
Mikhail Naganovccc82112023-04-27 18:14:15 -07001227 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301228 parameters, String8(AudioParameter::keyBtHfpVolume), [&hfpConfig](int volume0to15) {
1229 if (volume0to15 >= 0 && volume0to15 <= 15) {
1230 hfpConfig.volume = Float{.value = volume0to15 / 15.0f};
1231 return OK;
1232 }
1233 return BAD_VALUE;
1234 }));
Mikhail Naganovccc82112023-04-27 18:14:15 -07001235 if (mBluetooth != nullptr && hfpConfig != IBluetooth::HfpConfig{}) {
1236 IBluetooth::HfpConfig newHfpConfig;
1237 return statusTFromBinderStatus(mBluetooth->setHfpConfig(hfpConfig, &newHfpConfig));
1238 }
1239 return OK;
1240}
1241
1242status_t DeviceHalAidl::filterAndUpdateBtLeParameters(AudioParameter &parameters) {
Mikhail Naganovccc82112023-04-27 18:14:15 -07001243 std::optional<bool> leEnabled;
Eric Laurent7e3c0832023-11-30 15:04:50 +01001244 std::optional<std::vector<VendorParameter>> reconfigureOffload;
Mikhail Naganovccc82112023-04-27 18:14:15 -07001245 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301246 parameters, String8(AudioParameter::keyBtLeSuspended),
1247 [&leEnabled, this](const String8& trueOrFalse) {
1248 if (trueOrFalse == AudioParameter::valueTrue) {
1249 leEnabled = false; // 'suspended' == true
1250 return OK;
1251 } else if (trueOrFalse == AudioParameter::valueFalse) {
1252 leEnabled = true; // 'suspended' == false
1253 return OK;
1254 }
1255 AUGMENT_LOG(E, "setParameters: parameter key \"%s\" has invalid value \"%s\"",
1256 AudioParameter::keyBtLeSuspended, trueOrFalse.c_str());
1257 return BAD_VALUE;
1258 }));
Eric Laurent7e3c0832023-11-30 15:04:50 +01001259 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301260 parameters, String8(AudioParameter::keyReconfigLe),
1261 [&](const String8& value) -> status_t {
1262 if (mVendorExt != nullptr) {
1263 std::vector<VendorParameter> result;
1264 RETURN_STATUS_IF_ERROR(
1265 statusTFromBinderStatus(mVendorExt->parseBluetoothLeReconfigureOffload(
1266 std::string(value.c_str()), &result)));
1267 reconfigureOffload = std::move(result);
1268 } else {
1269 reconfigureOffload = std::vector<VendorParameter>();
1270 }
1271 return OK;
1272 }));
Mikhail Naganovccc82112023-04-27 18:14:15 -07001273 if (mBluetoothLe != nullptr && leEnabled.has_value()) {
1274 return statusTFromBinderStatus(mBluetoothLe->setEnabled(leEnabled.value()));
1275 }
Eric Laurent7e3c0832023-11-30 15:04:50 +01001276 if (mBluetoothLe != nullptr && reconfigureOffload.has_value()) {
Jaideep Sharma145313e2024-08-14 14:51:24 +05301277 return statusTFromBinderStatus(
1278 mBluetoothLe->reconfigureOffload(reconfigureOffload.value()));
Eric Laurent7e3c0832023-11-30 15:04:50 +01001279 }
Mikhail Naganovccc82112023-04-27 18:14:15 -07001280 return OK;
1281}
1282
1283status_t DeviceHalAidl::filterAndUpdateBtScoParameters(AudioParameter &parameters) {
Mikhail Naganovccc82112023-04-27 18:14:15 -07001284 IBluetooth::ScoConfig scoConfig;
1285 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301286 parameters, String8(AudioParameter::keyBtSco),
1287 [&scoConfig, this](const String8& onOrOff) {
1288 if (onOrOff == AudioParameter::valueOn) {
1289 scoConfig.isEnabled = Boolean{.value = true};
1290 return OK;
1291 } else if (onOrOff == AudioParameter::valueOff) {
1292 scoConfig.isEnabled = Boolean{.value = false};
1293 return OK;
1294 }
1295 AUGMENT_LOG(E, "setParameters: parameter key \"%s\" has invalid value \"%s\"",
1296 AudioParameter::keyBtSco, onOrOff.c_str());
1297 return BAD_VALUE;
1298 }));
Mikhail Naganovccc82112023-04-27 18:14:15 -07001299 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301300 parameters, String8(AudioParameter::keyBtScoHeadsetName),
1301 [&scoConfig](const String8& name) {
1302 scoConfig.debugName = name;
1303 return OK;
1304 }));
Mikhail Naganovccc82112023-04-27 18:14:15 -07001305 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301306 parameters, String8(AudioParameter::keyBtNrec),
1307 [&scoConfig, this](const String8& onOrOff) {
1308 if (onOrOff == AudioParameter::valueOn) {
1309 scoConfig.isNrecEnabled = Boolean{.value = true};
1310 return OK;
1311 } else if (onOrOff == AudioParameter::valueOff) {
1312 scoConfig.isNrecEnabled = Boolean{.value = false};
1313 return OK;
1314 }
1315 AUGMENT_LOG(E, "setParameters: parameter key \"%s\" has invalid value \"%s\"",
1316 AudioParameter::keyBtNrec, onOrOff.c_str());
1317 return BAD_VALUE;
1318 }));
Mikhail Naganovccc82112023-04-27 18:14:15 -07001319 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301320 parameters, String8(AudioParameter::keyBtScoWb),
1321 [&scoConfig, this](const String8& onOrOff) {
1322 if (onOrOff == AudioParameter::valueOn) {
1323 scoConfig.mode = IBluetooth::ScoConfig::Mode::SCO_WB;
1324 return OK;
1325 } else if (onOrOff == AudioParameter::valueOff) {
1326 scoConfig.mode = IBluetooth::ScoConfig::Mode::SCO;
1327 return OK;
1328 }
1329 AUGMENT_LOG(E, "setParameters: parameter key \"%s\" has invalid value \"%s\"",
1330 AudioParameter::keyBtScoWb, onOrOff.c_str());
1331 return BAD_VALUE;
1332 }));
Mikhail Naganovccc82112023-04-27 18:14:15 -07001333 if (mBluetooth != nullptr && scoConfig != IBluetooth::ScoConfig{}) {
1334 IBluetooth::ScoConfig newScoConfig;
1335 return statusTFromBinderStatus(mBluetooth->setScoConfig(scoConfig, &newScoConfig));
1336 }
1337 return OK;
1338}
1339
Mikhail Naganove92c34b2023-05-31 14:24:48 -07001340status_t DeviceHalAidl::filterAndUpdateScreenParameters(AudioParameter &parameters) {
Mikhail Naganove92c34b2023-05-31 14:24:48 -07001341 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301342 parameters, String8(AudioParameter::keyScreenState),
1343 [&, this](const String8& onOrOff) -> status_t {
1344 std::optional<bool> isTurnedOn;
1345 if (onOrOff == AudioParameter::valueOn) {
1346 isTurnedOn = true;
1347 } else if (onOrOff == AudioParameter::valueOff) {
1348 isTurnedOn = false;
1349 }
1350 if (!isTurnedOn.has_value()) {
1351 AUGMENT_LOG(E, "setParameters: parameter key \"%s\" has invalid value \"%s\"",
1352 AudioParameter::keyScreenState, onOrOff.c_str());
1353 return BAD_VALUE;
1354 }
1355 return statusTFromBinderStatus(mModule->updateScreenState(isTurnedOn.value()));
1356 }));
Mikhail Naganove92c34b2023-05-31 14:24:48 -07001357 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301358 parameters, String8(AudioParameter::keyScreenRotation),
1359 [&, this](int rotationDegrees) -> status_t {
Mikhail Naganove92c34b2023-05-31 14:24:48 -07001360 IModule::ScreenRotation rotation;
1361 switch (rotationDegrees) {
Jaideep Sharma145313e2024-08-14 14:51:24 +05301362 case 0:
1363 rotation = IModule::ScreenRotation::DEG_0;
1364 break;
1365 case 90:
1366 rotation = IModule::ScreenRotation::DEG_90;
1367 break;
1368 case 180:
1369 rotation = IModule::ScreenRotation::DEG_180;
1370 break;
1371 case 270:
1372 rotation = IModule::ScreenRotation::DEG_270;
1373 break;
Mikhail Naganove92c34b2023-05-31 14:24:48 -07001374 default:
Jaideep Sharma145313e2024-08-14 14:51:24 +05301375 AUGMENT_LOG(E, "setParameters: parameter key \"%s\" has invalid value %d",
1376 AudioParameter::keyScreenRotation, rotationDegrees);
Mikhail Naganove92c34b2023-05-31 14:24:48 -07001377 return BAD_VALUE;
1378 }
1379 return statusTFromBinderStatus(mModule->updateScreenRotation(rotation));
1380 }));
1381 return OK;
1382}
1383
Mikhail Naganovb9a81312023-07-18 13:55:34 -07001384status_t DeviceHalAidl::filterAndUpdateTelephonyParameters(AudioParameter &parameters) {
Mikhail Naganovb9a81312023-07-18 13:55:34 -07001385 using TtyMode = ITelephony::TelecomConfig::TtyMode;
1386 ITelephony::TelecomConfig telConfig;
1387 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301388 parameters, String8(AudioParameter::keyTtyMode),
1389 [&telConfig, this](const String8& mode) {
1390 if (mode == AudioParameter::valueTtyModeOff) {
1391 telConfig.ttyMode = TtyMode::OFF;
1392 return OK;
1393 } else if (mode == AudioParameter::valueTtyModeFull) {
1394 telConfig.ttyMode = TtyMode::FULL;
1395 return OK;
1396 } else if (mode == AudioParameter::valueTtyModeHco) {
1397 telConfig.ttyMode = TtyMode::HCO;
1398 return OK;
1399 } else if (mode == AudioParameter::valueTtyModeVco) {
1400 telConfig.ttyMode = TtyMode::VCO;
1401 return OK;
1402 }
1403 AUGMENT_LOG(E, "setParameters: parameter key \"%s\" has invalid value \"%s\"",
1404 AudioParameter::keyTtyMode, mode.c_str());
1405 return BAD_VALUE;
1406 }));
Mikhail Naganovb9a81312023-07-18 13:55:34 -07001407 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301408 parameters, String8(AudioParameter::keyHacSetting),
1409 [&telConfig, this](const String8& onOrOff) {
1410 if (onOrOff == AudioParameter::valueHacOn) {
1411 telConfig.isHacEnabled = Boolean{.value = true};
1412 return OK;
1413 } else if (onOrOff == AudioParameter::valueHacOff) {
1414 telConfig.isHacEnabled = Boolean{.value = false};
1415 return OK;
1416 }
1417 AUGMENT_LOG(E, "setParameters: parameter key \"%s\" has invalid value \"%s\"",
1418 AudioParameter::keyHacSetting, onOrOff.c_str());
1419 return BAD_VALUE;
1420 }));
Mikhail Naganovb9a81312023-07-18 13:55:34 -07001421 if (mTelephony != nullptr && telConfig != ITelephony::TelecomConfig{}) {
1422 ITelephony::TelecomConfig newTelConfig;
Jaideep Sharma145313e2024-08-14 14:51:24 +05301423 return statusTFromBinderStatus(mTelephony->setTelecomConfig(telConfig, &newTelConfig));
Mikhail Naganovb9a81312023-07-18 13:55:34 -07001424 }
1425 return OK;
1426}
1427
Mikhail Naganovdfd594e2023-02-08 16:59:41 -08001428void DeviceHalAidl::clearCallbacks(void* cookie) {
Mikhail Naganov22578412024-08-16 16:50:34 -07001429 std::lock_guard l(mCallbacksLock);
Mikhail Naganovdfd594e2023-02-08 16:59:41 -08001430 mCallbacks.erase(cookie);
1431}
1432
1433sp<StreamOutHalInterfaceCallback> DeviceHalAidl::getStreamOutCallback(void* cookie) {
1434 return getCallbackImpl(cookie, &Callbacks::out);
1435}
1436
1437void DeviceHalAidl::setStreamOutCallback(
1438 void* cookie, const sp<StreamOutHalInterfaceCallback>& cb) {
1439 setCallbackImpl(cookie, &Callbacks::out, cb);
1440}
1441
1442sp<StreamOutHalInterfaceEventCallback> DeviceHalAidl::getStreamOutEventCallback(
1443 void* cookie) {
1444 return getCallbackImpl(cookie, &Callbacks::event);
1445}
1446
1447void DeviceHalAidl::setStreamOutEventCallback(
1448 void* cookie, const sp<StreamOutHalInterfaceEventCallback>& cb) {
1449 setCallbackImpl(cookie, &Callbacks::event, cb);
1450}
1451
1452sp<StreamOutHalInterfaceLatencyModeCallback> DeviceHalAidl::getStreamOutLatencyModeCallback(
1453 void* cookie) {
1454 return getCallbackImpl(cookie, &Callbacks::latency);
1455}
1456
1457void DeviceHalAidl::setStreamOutLatencyModeCallback(
1458 void* cookie, const sp<StreamOutHalInterfaceLatencyModeCallback>& cb) {
1459 setCallbackImpl(cookie, &Callbacks::latency, cb);
1460}
1461
Mikhail Naganov22578412024-08-16 16:50:34 -07001462template <class C>
Mikhail Naganovdfd594e2023-02-08 16:59:41 -08001463sp<C> DeviceHalAidl::getCallbackImpl(void* cookie, wp<C> DeviceHalAidl::Callbacks::* field) {
Mikhail Naganov22578412024-08-16 16:50:34 -07001464 wp<C> result;
1465 {
1466 std::lock_guard l(mCallbacksLock);
1467 if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
1468 result = (it->second).*field;
1469 }
Mikhail Naganovdfd594e2023-02-08 16:59:41 -08001470 }
Mikhail Naganov22578412024-08-16 16:50:34 -07001471 return result.promote();
Mikhail Naganovdfd594e2023-02-08 16:59:41 -08001472}
1473template<class C>
1474void DeviceHalAidl::setCallbackImpl(
1475 void* cookie, wp<C> DeviceHalAidl::Callbacks::* field, const sp<C>& cb) {
Mikhail Naganov22578412024-08-16 16:50:34 -07001476 std::lock_guard l(mCallbacksLock);
Mikhail Naganovdfd594e2023-02-08 16:59:41 -08001477 if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
1478 (it->second).*field = cb;
1479 }
1480}
1481
Mikhail Naganov31d46652023-01-10 18:29:25 +00001482} // namespace android