blob: 3cc923d35e7102ec2025414d9d00e3ace407aa6b [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>
25#include <error/expected_utils.h>
26#include <media/AidlConversionCppNdk.h>
Haofan Wangbf44e092024-07-07 15:29:38 -070027#include <media/AidlConversionNdk.h>
Mikhail Naganov25bc9a22023-04-21 18:48:16 -070028#include <media/AidlConversionNdkCpp.h>
Mikhail Naganovfab697c2023-01-11 19:33:13 +000029#include <media/AidlConversionUtil.h>
Mikhail Naganov31d46652023-01-10 18:29:25 +000030#include <mediautils/TimeCheck.h>
Mikhail Naganovae9063d2023-11-07 16:43:51 -080031#include <system/audio.h>
Mikhail Naganov89a9f742023-01-30 12:33:18 -080032#include <Utils.h>
Mikhail Naganov31d46652023-01-10 18:29:25 +000033#include <utils/Log.h>
Shunkai Yao51202502022-12-12 06:11:46 +000034
Jaideep Sharma145313e2024-08-14 14:51:24 +053035#include "AidlUtils.h"
Mikhail Naganov31d46652023-01-10 18:29:25 +000036#include "DeviceHalAidl.h"
Mikhail Naganova82a69d2023-06-14 16:31:32 -070037#include "EffectHalAidl.h"
Mikhail Naganov31d46652023-01-10 18:29:25 +000038#include "StreamHalAidl.h"
39
Mikhail Naganovfab697c2023-01-11 19:33:13 +000040using aidl::android::aidl_utils::statusTFromBinderStatus;
Mikhail Naganovccc82112023-04-27 18:14:15 -070041using aidl::android::media::audio::common::Boolean;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -080042using aidl::android::media::audio::common::AudioConfig;
43using aidl::android::media::audio::common::AudioDevice;
Mikhail Naganov89a9f742023-01-30 12:33:18 -080044using aidl::android::media::audio::common::AudioDeviceType;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -080045using aidl::android::media::audio::common::AudioIoFlags;
Mikhail Naganovdfd594e2023-02-08 16:59:41 -080046using aidl::android::media::audio::common::AudioLatencyMode;
David Li9cf5e622023-03-21 00:51:10 +080047using aidl::android::media::audio::common::AudioMMapPolicy;
48using aidl::android::media::audio::common::AudioMMapPolicyInfo;
49using aidl::android::media::audio::common::AudioMMapPolicyType;
Mikhail Naganovfab697c2023-01-11 19:33:13 +000050using aidl::android::media::audio::common::AudioMode;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -080051using aidl::android::media::audio::common::AudioOutputFlags;
52using aidl::android::media::audio::common::AudioPort;
53using aidl::android::media::audio::common::AudioPortConfig;
David Li9cf5e622023-03-21 00:51:10 +080054using aidl::android::media::audio::common::AudioPortExt;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -080055using aidl::android::media::audio::common::AudioSource;
Mikhail Naganovfab697c2023-01-11 19:33:13 +000056using aidl::android::media::audio::common::Float;
David Li9cf5e622023-03-21 00:51:10 +080057using aidl::android::media::audio::common::Int;
58using aidl::android::media::audio::common::MicrophoneDynamicInfo;
59using aidl::android::media::audio::common::MicrophoneInfo;
Mikhail Naganove7a26ad2023-05-25 17:36:48 -070060using aidl::android::media::audio::IHalAdapterVendorExtension;
Mikhail Naganov6352e822023-03-09 18:22:36 -080061using aidl::android::hardware::audio::common::getFrameSizeInBytes;
62using aidl::android::hardware::audio::common::isBitPositionFlagSet;
David Li21289462024-04-17 01:09:23 +080063using aidl::android::hardware::audio::common::kDumpFromAudioServerArgument;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -080064using aidl::android::hardware::audio::common::RecordTrackMetadata;
Haofan Wangbf44e092024-07-07 15:29:38 -070065using aidl::android::hardware::audio::common::PlaybackTrackMetadata;
66using aidl::android::hardware::audio::common::SourceMetadata;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -070067using aidl::android::hardware::audio::core::sounddose::ISoundDose;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -080068using aidl::android::hardware::audio::core::AudioPatch;
Mikhail Naganov289468a2023-03-29 10:06:15 -070069using aidl::android::hardware::audio::core::AudioRoute;
Mikhail Naganovccc82112023-04-27 18:14:15 -070070using aidl::android::hardware::audio::core::IBluetooth;
71using aidl::android::hardware::audio::core::IBluetoothA2dp;
72using aidl::android::hardware::audio::core::IBluetoothLe;
Mikhail Naganovfab697c2023-01-11 19:33:13 +000073using aidl::android::hardware::audio::core::IModule;
74using aidl::android::hardware::audio::core::ITelephony;
Mikhail Naganove93a0862023-03-15 17:06:59 -070075using aidl::android::hardware::audio::core::ModuleDebug;
Mikhail Naganove7a26ad2023-05-25 17:36:48 -070076using aidl::android::hardware::audio::core::VendorParameter;
Mikhail Naganov31d46652023-01-10 18:29:25 +000077
Jaideep Sharma145313e2024-08-14 14:51:24 +053078#define RETURN_IF_MODULE_NOT_INIT(retVal) \
79 if (mModule == nullptr) { \
80 AUGMENT_LOG(E, "module not initialized"); \
81 return retVal; \
82 }
83
84#define RETURN_IF_TELEPHONY_NOT_INIT(retVal) \
85 if (mTelephony == nullptr) { \
86 AUGMENT_LOG(E, "telephony not initialized"); \
87 return retVal; \
88 }
89
Mikhail Naganov31d46652023-01-10 18:29:25 +000090namespace android {
91
Mikhail Naganov5b1eed12023-01-25 11:29:11 -080092namespace {
93
Mikhail Naganovf83b9742023-04-24 13:06:04 -070094// Note: these converters are for types defined in different AIDL files. Although these
95// AIDL files are copies of each other, however formally these are different types
96// thus we don't use a conversion via a parcelable.
97ConversionResult<media::AudioRoute> ndk2cpp_AudioRoute(const AudioRoute& ndk) {
98 media::AudioRoute cpp;
99 cpp.sourcePortIds.insert(
100 cpp.sourcePortIds.end(), ndk.sourcePortIds.begin(), ndk.sourcePortIds.end());
101 cpp.sinkPortId = ndk.sinkPortId;
102 cpp.isExclusive = ndk.isExclusive;
David Li9cf5e622023-03-21 00:51:10 +0800103 return cpp;
104}
105
Mikhail Naganov1fba38c2023-05-03 17:45:36 -0700106template<typename T>
107std::shared_ptr<T> retrieveSubInterface(const std::shared_ptr<IModule>& module,
108 ::ndk::ScopedAStatus (IModule::*getT)(std::shared_ptr<T>*)) {
109 if (module != nullptr) {
110 std::shared_ptr<T> instance;
111 if (auto status = (module.get()->*getT)(&instance); status.isOk()) {
112 return instance;
113 }
114 }
115 return nullptr;
116}
117
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800118} // namespace
119
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700120DeviceHalAidl::DeviceHalAidl(const std::string& instance, const std::shared_ptr<IModule>& module,
121 const std::shared_ptr<IHalAdapterVendorExtension>& vext)
Jaideep Sharma145313e2024-08-14 14:51:24 +0530122 : ConversionHelperAidl("DeviceHalAidl", instance),
123 mModule(module),
124 mVendorExt(vext),
125 mTelephony(retrieveSubInterface<ITelephony>(module, &IModule::getTelephony)),
126 mBluetooth(retrieveSubInterface<IBluetooth>(module, &IModule::getBluetooth)),
127 mBluetoothA2dp(retrieveSubInterface<IBluetoothA2dp>(module, &IModule::getBluetoothA2dp)),
128 mBluetoothLe(retrieveSubInterface<IBluetoothLe>(module, &IModule::getBluetoothLe)),
129 mSoundDose(retrieveSubInterface<ISoundDose>(module, &IModule::getSoundDose)),
130 mMapper(instance, module),
131 mMapperAccessor(mMapper, mLock) {}
Mikhail Naganov1fba38c2023-05-03 17:45:36 -0700132
Mikhail Naganovf83b9742023-04-24 13:06:04 -0700133status_t DeviceHalAidl::getAudioPorts(std::vector<media::audio::common::AudioPort> *ports) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700134 std::lock_guard l(mLock);
135 return mMapper.getAudioPorts(ports, ndk2cpp_AudioPort);
Mikhail Naganovf83b9742023-04-24 13:06:04 -0700136}
137
138status_t DeviceHalAidl::getAudioRoutes(std::vector<media::AudioRoute> *routes) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700139 std::lock_guard l(mLock);
140 return mMapper.getAudioRoutes(routes, ndk2cpp_AudioRoute);
Mikhail Naganovf83b9742023-04-24 13:06:04 -0700141}
142
Mikhail Naganov1fba38c2023-05-03 17:45:36 -0700143status_t DeviceHalAidl::getSupportedModes(std::vector<media::audio::common::AudioMode> *modes) {
Shunkai Yao35665b12024-08-21 00:30:54 +0000144 AUGMENT_LOG(D);
Mikhail Naganov1fba38c2023-05-03 17:45:36 -0700145 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530146 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
147 RETURN_IF_TELEPHONY_NOT_INIT(INVALID_OPERATION);
148
Mikhail Naganov1fba38c2023-05-03 17:45:36 -0700149 if (modes == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530150 AUGMENT_LOG(E, "uninitialized modes");
Mikhail Naganov1fba38c2023-05-03 17:45:36 -0700151 return BAD_VALUE;
152 }
Mikhail Naganov1fba38c2023-05-03 17:45:36 -0700153 std::vector<AudioMode> aidlModes;
154 RETURN_STATUS_IF_ERROR(
155 statusTFromBinderStatus(mTelephony->getSupportedAudioModes(&aidlModes)));
156 *modes = VALUE_OR_RETURN_STATUS(
157 ::aidl::android::convertContainer<std::vector<media::audio::common::AudioMode>>(
158 aidlModes, ndk2cpp_AudioMode));
159 return OK;
160}
161
Mikhail Naganov31d46652023-01-10 18:29:25 +0000162status_t DeviceHalAidl::getSupportedDevices(uint32_t*) {
163 // Obsolete.
164 return INVALID_OPERATION;
Shunkai Yao51202502022-12-12 06:11:46 +0000165}
166
167status_t DeviceHalAidl::initCheck() {
Shunkai Yao35665b12024-08-21 00:30:54 +0000168 AUGMENT_LOG(D);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800169 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530170 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700171 std::lock_guard l(mLock);
172 return mMapper.initialize();
Shunkai Yao51202502022-12-12 06:11:46 +0000173}
174
175status_t DeviceHalAidl::setVoiceVolume(float volume) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530176 AUGMENT_LOG(D, "volume %f", volume);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000177 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530178 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
179 RETURN_IF_TELEPHONY_NOT_INIT(INVALID_OPERATION);
180
181 ITelephony::TelecomConfig inConfig{.voiceVolume = Float{volume}}, outConfig;
Mikhail Naganov1fba38c2023-05-03 17:45:36 -0700182 RETURN_STATUS_IF_ERROR(
183 statusTFromBinderStatus(mTelephony->setTelecomConfig(inConfig, &outConfig)));
Jaideep Sharma145313e2024-08-14 14:51:24 +0530184 AUGMENT_LOG_IF(
185 W, outConfig.voiceVolume.has_value() && volume != outConfig.voiceVolume.value().value,
186 "the resulting voice volume %f is not the same as requested %f",
187 outConfig.voiceVolume.value().value, volume);
Mikhail Naganov1fba38c2023-05-03 17:45:36 -0700188 return OK;
Shunkai Yao51202502022-12-12 06:11:46 +0000189}
190
191status_t DeviceHalAidl::setMasterVolume(float volume) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530192 AUGMENT_LOG(D, "volume %f", volume);
193
Mikhail Naganov31d46652023-01-10 18:29:25 +0000194 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530195 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000196 return statusTFromBinderStatus(mModule->setMasterVolume(volume));
Shunkai Yao51202502022-12-12 06:11:46 +0000197}
198
199status_t DeviceHalAidl::getMasterVolume(float *volume) {
Shunkai Yao35665b12024-08-21 00:30:54 +0000200 AUGMENT_LOG(D);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000201 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530202 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700203 if (volume == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530204 AUGMENT_LOG(E, "uninitialized volumes");
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700205 return BAD_VALUE;
206 }
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000207 return statusTFromBinderStatus(mModule->getMasterVolume(volume));
Shunkai Yao51202502022-12-12 06:11:46 +0000208}
209
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000210status_t DeviceHalAidl::setMode(audio_mode_t mode) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530211 AUGMENT_LOG(D, "mode %d", mode);
212
Mikhail Naganov31d46652023-01-10 18:29:25 +0000213 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530214 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000215 AudioMode audioMode = VALUE_OR_FATAL(::aidl::android::legacy2aidl_audio_mode_t_AudioMode(mode));
Mikhail Naganov1fba38c2023-05-03 17:45:36 -0700216 if (mTelephony != nullptr) {
217 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mTelephony->switchAudioMode(audioMode)));
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000218 }
219 return statusTFromBinderStatus(mModule->updateAudioMode(audioMode));
Shunkai Yao51202502022-12-12 06:11:46 +0000220}
221
222status_t DeviceHalAidl::setMicMute(bool state) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530223 AUGMENT_LOG(D, "mute %d", state);
224
Mikhail Naganov31d46652023-01-10 18:29:25 +0000225 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530226 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000227 return statusTFromBinderStatus(mModule->setMicMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000228}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000229
Shunkai Yao51202502022-12-12 06:11:46 +0000230status_t DeviceHalAidl::getMicMute(bool *state) {
Shunkai Yao35665b12024-08-21 00:30:54 +0000231 AUGMENT_LOG(D);
Jaideep Sharma145313e2024-08-14 14:51:24 +0530232
Mikhail Naganov31d46652023-01-10 18:29:25 +0000233 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530234 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700235 if (state == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530236 AUGMENT_LOG(E, "uninitialized mute state");
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700237 return BAD_VALUE;
238 }
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000239 return statusTFromBinderStatus(mModule->getMicMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000240}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000241
Shunkai Yao51202502022-12-12 06:11:46 +0000242status_t DeviceHalAidl::setMasterMute(bool state) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530243 AUGMENT_LOG(D, "mute %d", state);
244
Mikhail Naganov31d46652023-01-10 18:29:25 +0000245 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530246 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000247 return statusTFromBinderStatus(mModule->setMasterMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000248}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000249
Shunkai Yao51202502022-12-12 06:11:46 +0000250status_t DeviceHalAidl::getMasterMute(bool *state) {
Shunkai Yao35665b12024-08-21 00:30:54 +0000251 AUGMENT_LOG(D);
Jaideep Sharma145313e2024-08-14 14:51:24 +0530252
Mikhail Naganov31d46652023-01-10 18:29:25 +0000253 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530254 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700255 if (state == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530256 AUGMENT_LOG(E, "uninitialized mute state");
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700257 return BAD_VALUE;
258 }
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000259 return statusTFromBinderStatus(mModule->getMasterMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000260}
261
Mikhail Naganovccc82112023-04-27 18:14:15 -0700262status_t DeviceHalAidl::setParameters(const String8& kvPairs) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700263 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530264 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovccc82112023-04-27 18:14:15 -0700265 AudioParameter parameters(kvPairs);
Jaideep Sharma145313e2024-08-14 14:51:24 +0530266 AUGMENT_LOG(D, "parameters: \"%s\"", parameters.toString().c_str());
Mikhail Naganovccc82112023-04-27 18:14:15 -0700267
268 if (status_t status = filterAndUpdateBtA2dpParameters(parameters); status != OK) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530269 AUGMENT_LOG(W, "filterAndUpdateBtA2dpParameters failed: %d", status);
Mikhail Naganovccc82112023-04-27 18:14:15 -0700270 }
271 if (status_t status = filterAndUpdateBtHfpParameters(parameters); status != OK) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530272 AUGMENT_LOG(W, "filterAndUpdateBtHfpParameters failed: %d", status);
Mikhail Naganovccc82112023-04-27 18:14:15 -0700273 }
274 if (status_t status = filterAndUpdateBtLeParameters(parameters); status != OK) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530275 AUGMENT_LOG(W, "filterAndUpdateBtLeParameters failed: %d", status);
Mikhail Naganovccc82112023-04-27 18:14:15 -0700276 }
277 if (status_t status = filterAndUpdateBtScoParameters(parameters); status != OK) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530278 AUGMENT_LOG(W, "filterAndUpdateBtScoParameters failed: %d", status);
Mikhail Naganovccc82112023-04-27 18:14:15 -0700279 }
Mikhail Naganove92c34b2023-05-31 14:24:48 -0700280 if (status_t status = filterAndUpdateScreenParameters(parameters); status != OK) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530281 AUGMENT_LOG(W, "filterAndUpdateScreenParameters failed: %d", status);
Mikhail Naganove92c34b2023-05-31 14:24:48 -0700282 }
Mikhail Naganovb9a81312023-07-18 13:55:34 -0700283 if (status_t status = filterAndUpdateTelephonyParameters(parameters); status != OK) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530284 AUGMENT_LOG(W, "filterAndUpdateTelephonyParameters failed: %d", status);
Mikhail Naganovb9a81312023-07-18 13:55:34 -0700285 }
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700286 return parseAndSetVendorParameters(mVendorExt, mModule, parameters);
Shunkai Yao51202502022-12-12 06:11:46 +0000287}
288
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700289status_t DeviceHalAidl::getParameters(const String8& keys, String8 *values) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530290 AUGMENT_LOG(D, "keys: \"%s\"", keys.c_str());
291
Mikhail Naganov31d46652023-01-10 18:29:25 +0000292 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530293 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700294 if (values == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530295 AUGMENT_LOG(E, "invalid values");
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700296 return BAD_VALUE;
297 }
298 AudioParameter parameterKeys(keys), result;
299 if (status_t status = filterAndRetrieveBtA2dpParameters(parameterKeys, &result); status != OK) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530300 AUGMENT_LOG(W, "filterAndRetrieveBtA2dpParameters failed: %d", status);
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700301 }
Eric Laurent7e3c0832023-11-30 15:04:50 +0100302 if (status_t status = filterAndRetrieveBtLeParameters(parameterKeys, &result); status != OK) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530303 AUGMENT_LOG(W, "filterAndRetrieveBtLeParameters failed: %d", status);
Eric Laurent7e3c0832023-11-30 15:04:50 +0100304 }
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700305 *values = result.toString();
306 return parseAndGetVendorParameters(mVendorExt, mModule, parameterKeys, values);
Shunkai Yao51202502022-12-12 06:11:46 +0000307}
308
Mikhail Naganovd5b643f2024-02-15 11:51:26 -0800309status_t DeviceHalAidl::getInputBufferSize(struct audio_config* config, size_t* size) {
Shunkai Yao35665b12024-08-21 00:30:54 +0000310 AUGMENT_LOG(D);
Jaideep Sharma145313e2024-08-14 14:51:24 +0530311
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800312 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530313 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700314 if (config == nullptr || size == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530315 AUGMENT_LOG(E, "invalid config or size");
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700316 return BAD_VALUE;
317 }
Mikhail Naganovd5b643f2024-02-15 11:51:26 -0800318 constexpr bool isInput = true;
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800319 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
Mikhail Naganovd5b643f2024-02-15 11:51:26 -0800320 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, isInput));
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800321 AudioDevice aidlDevice;
322 aidlDevice.type.type = AudioDeviceType::IN_DEFAULT;
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800323 AudioSource aidlSource = AudioSource::DEFAULT;
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800324 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::input>(0);
325 AudioPortConfig mixPortConfig;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700326 Hal2AidlMapper::Cleanups cleanups(mMapperAccessor);
Mikhail Naganove93a0862023-03-15 17:06:59 -0700327 AudioPatch aidlPatch;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700328 {
329 std::lock_guard l(mLock);
330 RETURN_STATUS_IF_ERROR(mMapper.prepareToOpenStream(
331 0 /*handle*/, aidlDevice, aidlFlags, aidlSource,
332 &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
333 }
Mikhail Naganovd5b643f2024-02-15 11:51:26 -0800334 *config = VALUE_OR_RETURN_STATUS(
335 ::aidl::android::aidl2legacy_AudioConfig_audio_config_t(aidlConfig, isInput));
336 if (mixPortConfig.id == 0) return BAD_VALUE; // HAL suggests a different config.
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800337 *size = aidlConfig.frameCount *
338 getFrameSizeInBytes(aidlConfig.base.format, aidlConfig.base.channelMask);
339 // Do not disarm cleanups to release temporary port configs.
340 return OK;
341}
342
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800343namespace {
344
345class StreamCallbackBase {
346 protected:
347 explicit StreamCallbackBase(const sp<CallbackBroker>& broker) : mBroker(broker) {}
348 public:
349 void* getCookie() const { return mCookie; }
350 void setCookie(void* cookie) { mCookie = cookie; }
351 sp<CallbackBroker> getBroker() const {
352 if (void* cookie = mCookie; cookie != nullptr) return mBroker.promote();
353 return nullptr;
354 }
355 private:
356 const wp<CallbackBroker> mBroker;
357 std::atomic<void*> mCookie;
358};
359
360template<class C>
361class StreamCallbackBaseHelper {
362 protected:
363 explicit StreamCallbackBaseHelper(const StreamCallbackBase& base) : mBase(base) {}
364 sp<C> getCb(const sp<CallbackBroker>& broker, void* cookie);
365 using CbRef = const sp<C>&;
366 ndk::ScopedAStatus runCb(const std::function<void(CbRef cb)>& f) {
367 if (auto cb = getCb(mBase.getBroker(), mBase.getCookie()); cb != nullptr) f(cb);
368 return ndk::ScopedAStatus::ok();
369 }
370 private:
371 const StreamCallbackBase& mBase;
372};
373
374template<>
375sp<StreamOutHalInterfaceCallback> StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>::getCb(
376 const sp<CallbackBroker>& broker, void* cookie) {
377 if (broker != nullptr) return broker->getStreamOutCallback(cookie);
378 return nullptr;
379}
380
381template<>
382sp<StreamOutHalInterfaceEventCallback>
383StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>::getCb(
384 const sp<CallbackBroker>& broker, void* cookie) {
385 if (broker != nullptr) return broker->getStreamOutEventCallback(cookie);
386 return nullptr;
387}
388
389template<>
390sp<StreamOutHalInterfaceLatencyModeCallback>
391StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>::getCb(
392 const sp<CallbackBroker>& broker, void* cookie) {
393 if (broker != nullptr) return broker->getStreamOutLatencyModeCallback(cookie);
394 return nullptr;
395}
396
397/*
398Note on the callback ownership.
399
400In the Binder ownership model, the server implementation is kept alive
401as long as there is any client (proxy object) alive. This is done by
402incrementing the refcount of the server-side object by the Binder framework.
403When it detects that the last client is gone, it decrements the refcount back.
404
405Thus, it is not needed to keep any references to StreamCallback on our
406side (after we have sent an instance to the client), because we are
407the server-side. The callback object will be kept alive as long as the HAL server
408holds a strong ref to IStreamCallback proxy.
409*/
410
411class OutputStreamCallbackAidl : public StreamCallbackBase,
412 public StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>,
413 public ::aidl::android::hardware::audio::core::BnStreamCallback {
414 public:
415 explicit OutputStreamCallbackAidl(const sp<CallbackBroker>& broker)
416 : StreamCallbackBase(broker),
417 StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>(
418 *static_cast<StreamCallbackBase*>(this)) {}
419 ndk::ScopedAStatus onTransferReady() override {
420 return runCb([](CbRef cb) { cb->onWriteReady(); });
421 }
422 ndk::ScopedAStatus onError() override {
Mikhail Naganovbf203ce2024-05-23 16:27:59 -0700423 return runCb([](CbRef cb) { cb->onError(true /*isHardError*/); });
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800424 }
425 ndk::ScopedAStatus onDrainReady() override {
426 return runCb([](CbRef cb) { cb->onDrainReady(); });
427 }
428};
429
430class OutputStreamEventCallbackAidl :
431 public StreamCallbackBase,
432 public StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>,
433 public StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>,
434 public ::aidl::android::hardware::audio::core::BnStreamOutEventCallback {
435 public:
436 explicit OutputStreamEventCallbackAidl(const sp<CallbackBroker>& broker)
437 : StreamCallbackBase(broker),
438 StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>(
439 *static_cast<StreamCallbackBase*>(this)),
440 StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>(
441 *static_cast<StreamCallbackBase*>(this)) {}
Ryan Prichard78c5e452024-02-08 16:16:57 -0800442 ndk::ScopedAStatus onCodecFormatChanged(const std::vector<uint8_t>& halMetadata) override {
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800443 return StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>::runCb(
444 [&halMetadata](auto cb) { cb->onCodecFormatChanged(halMetadata); });
445 }
446 ndk::ScopedAStatus onRecommendedLatencyModeChanged(
447 const std::vector<AudioLatencyMode>& in_modes) override {
448 auto halModes = VALUE_OR_FATAL(
449 ::aidl::android::convertContainer<std::vector<audio_latency_mode_t>>(
450 in_modes,
451 ::aidl::android::aidl2legacy_AudioLatencyMode_audio_latency_mode_t));
452 return StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>::runCb(
453 [&halModes](auto cb) { cb->onRecommendedLatencyModeChanged(halModes); });
454 }
455};
456
457} // namespace
458
Mikhail Naganov31d46652023-01-10 18:29:25 +0000459status_t DeviceHalAidl::openOutputStream(
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800460 audio_io_handle_t handle, audio_devices_t devices,
461 audio_output_flags_t flags, struct audio_config* config,
462 const char* address,
Haofan Wangbf44e092024-07-07 15:29:38 -0700463 sp<StreamOutHalInterface>* outStream,
464 const std::vector<playback_track_metadata_v7_t>& sourceMetadata) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530465 AUGMENT_LOG(D, "handle: %d devices %0x flags %0x", handle, devices, flags);
Shunkai Yao35665b12024-08-21 00:30:54 +0000466
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700467 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530468 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700469 if (outStream == nullptr || config == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530470 AUGMENT_LOG(E, "invalid outStream or config");
Mikhail Naganov31d46652023-01-10 18:29:25 +0000471 return BAD_VALUE;
472 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700473 constexpr bool isInput = false;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800474 int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
475 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(handle));
476 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700477 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, isInput));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800478 AudioDevice aidlDevice = VALUE_OR_RETURN_STATUS(
479 ::aidl::android::legacy2aidl_audio_device_AudioDevice(devices, address));
480 int32_t aidlOutputFlags = VALUE_OR_RETURN_STATUS(
481 ::aidl::android::legacy2aidl_audio_output_flags_t_int32_t_mask(flags));
Haofan Wangbf44e092024-07-07 15:29:38 -0700482 SourceMetadata aidlMetadata = VALUE_OR_RETURN_STATUS(
Haofan Wang9b390862024-08-22 17:44:59 +0000483 ::aidl::android::legacy2aidl_playback_track_metadata_v7_SourceMetadata(sourceMetadata));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800484 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::output>(aidlOutputFlags);
485 AudioPortConfig mixPortConfig;
Mikhail Naganove93a0862023-03-15 17:06:59 -0700486 AudioPatch aidlPatch;
Haofan Wangbf44e092024-07-07 15:29:38 -0700487
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700488 Hal2AidlMapper::Cleanups cleanups(mMapperAccessor);
489 {
490 std::lock_guard l(mLock);
491 RETURN_STATUS_IF_ERROR(mMapper.prepareToOpenStream(aidlHandle, aidlDevice, aidlFlags,
492 AudioSource::SYS_RESERVED_INVALID /*only needed for input*/,
493 &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
494 }
495 *config = VALUE_OR_RETURN_STATUS(
496 ::aidl::android::aidl2legacy_AudioConfig_audio_config_t(aidlConfig, isInput));
Mikhail Naganovca92a5c2023-12-07 14:00:48 -0800497 if (mixPortConfig.id == 0) return BAD_VALUE; // HAL suggests a different config.
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800498 ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamArguments args;
499 args.portConfigId = mixPortConfig.id;
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800500 const bool isOffload = isBitPositionFlagSet(
501 aidlOutputFlags, AudioOutputFlags::COMPRESS_OFFLOAD);
Kuowei Li3b9a69d2024-06-07 17:54:32 +0800502 const bool isHwAvSync = isBitPositionFlagSet(
503 aidlOutputFlags, AudioOutputFlags::HW_AV_SYNC);
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800504 std::shared_ptr<OutputStreamCallbackAidl> streamCb;
505 if (isOffload) {
506 streamCb = ndk::SharedRefBase::make<OutputStreamCallbackAidl>(this);
507 }
508 auto eventCb = ndk::SharedRefBase::make<OutputStreamEventCallbackAidl>(this);
Kuowei Li3b9a69d2024-06-07 17:54:32 +0800509 if (isOffload || isHwAvSync) {
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800510 args.offloadInfo = aidlConfig.offloadInfo;
Kuowei Li3b9a69d2024-06-07 17:54:32 +0800511 }
512 if (isOffload) {
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800513 args.callback = streamCb;
514 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800515 args.bufferSizeFrames = aidlConfig.frameCount;
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800516 args.eventCallback = eventCb;
Haofan Wangbf44e092024-07-07 15:29:38 -0700517 args.sourceMetadata = aidlMetadata;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800518 ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamReturn ret;
519 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openOutputStream(args, &ret)));
Jaideep Sharma145313e2024-08-14 14:51:24 +0530520 StreamContextAidl context(ret.desc, isOffload, aidlHandle);
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800521 if (!context.isValid()) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530522 AUGMENT_LOG(E, "Failed to created a valid stream context from the descriptor: %s",
523 ret.desc.toString().c_str());
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800524 return NO_INIT;
525 }
Mikhail Naganov8065bfd2024-03-25 14:59:49 -0700526 auto stream = sp<StreamOutHalAidl>::make(*config, std::move(context), aidlPatch.latenciesMs[0],
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700527 std::move(ret.stream), mVendorExt, this /*callbackBroker*/);
Mikhail Naganov8065bfd2024-03-25 14:59:49 -0700528 *outStream = stream;
529 /* StreamOutHalInterface* */ void* cbCookie = (*outStream).get();
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800530 {
Mikhail Naganov22578412024-08-16 16:50:34 -0700531 std::lock_guard l(mCallbacksLock);
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800532 mCallbacks.emplace(cbCookie, Callbacks{});
Mikhail Naganov22578412024-08-16 16:50:34 -0700533 }
534 {
535 std::lock_guard l(mLock);
Mikhail Naganov78f7f9a2023-11-16 15:49:23 -0800536 mMapper.addStream(*outStream, mixPortConfig.id, aidlPatch.id);
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800537 }
Mikhail Naganov8065bfd2024-03-25 14:59:49 -0700538 if (streamCb) {
539 streamCb->setCookie(cbCookie);
540 // Although StreamOutHalAidl implements StreamOutHalInterfaceCallback,
541 // we always go via the CallbackBroker for consistency.
542 setStreamOutCallback(cbCookie, stream);
543 }
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800544 eventCb->setCookie(cbCookie);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800545 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000546 return OK;
547}
548
Mikhail Naganov31d46652023-01-10 18:29:25 +0000549status_t DeviceHalAidl::openInputStream(
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800550 audio_io_handle_t handle, audio_devices_t devices,
551 struct audio_config* config, audio_input_flags_t flags,
552 const char* address, audio_source_t source,
553 audio_devices_t outputDevice, const char* outputDeviceAddress,
Mikhail Naganov31d46652023-01-10 18:29:25 +0000554 sp<StreamInHalInterface>* inStream) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530555 AUGMENT_LOG(D, "handle: %d devices %0x flags %0x", handle, devices, flags);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700556 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530557 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700558 if (inStream == nullptr || config == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530559 AUGMENT_LOG(E, "invalid inStream or config");
Mikhail Naganov31d46652023-01-10 18:29:25 +0000560 return BAD_VALUE;
561 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700562 constexpr bool isInput = true;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800563 int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
564 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(handle));
565 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700566 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, isInput));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800567 AudioDevice aidlDevice = VALUE_OR_RETURN_STATUS(
568 ::aidl::android::legacy2aidl_audio_device_AudioDevice(devices, address));
569 int32_t aidlInputFlags = VALUE_OR_RETURN_STATUS(
570 ::aidl::android::legacy2aidl_audio_input_flags_t_int32_t_mask(flags));
571 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::input>(aidlInputFlags);
572 AudioSource aidlSource = VALUE_OR_RETURN_STATUS(
573 ::aidl::android::legacy2aidl_audio_source_t_AudioSource(source));
574 AudioPortConfig mixPortConfig;
Mikhail Naganove93a0862023-03-15 17:06:59 -0700575 AudioPatch aidlPatch;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700576 Hal2AidlMapper::Cleanups cleanups(mMapperAccessor);
577 {
578 std::lock_guard l(mLock);
579 RETURN_STATUS_IF_ERROR(mMapper.prepareToOpenStream(
580 aidlHandle, aidlDevice, aidlFlags, aidlSource,
581 &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
582 }
583 *config = VALUE_OR_RETURN_STATUS(
584 ::aidl::android::aidl2legacy_AudioConfig_audio_config_t(aidlConfig, isInput));
Mikhail Naganovca92a5c2023-12-07 14:00:48 -0800585 if (mixPortConfig.id == 0) return BAD_VALUE; // HAL suggests a different config.
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800586 ::aidl::android::hardware::audio::core::IModule::OpenInputStreamArguments args;
587 args.portConfigId = mixPortConfig.id;
588 RecordTrackMetadata aidlTrackMetadata{
589 .source = aidlSource, .gain = 1, .channelMask = aidlConfig.base.channelMask };
590 if (outputDevice != AUDIO_DEVICE_NONE) {
591 aidlTrackMetadata.destinationDevice = VALUE_OR_RETURN_STATUS(
592 ::aidl::android::legacy2aidl_audio_device_AudioDevice(
593 outputDevice, outputDeviceAddress));
594 }
595 args.sinkMetadata.tracks.push_back(std::move(aidlTrackMetadata));
596 args.bufferSizeFrames = aidlConfig.frameCount;
597 ::aidl::android::hardware::audio::core::IModule::OpenInputStreamReturn ret;
598 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openInputStream(args, &ret)));
Jaideep Sharma145313e2024-08-14 14:51:24 +0530599 StreamContextAidl context(ret.desc, false /*isAsynchronous*/, aidlHandle);
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800600 if (!context.isValid()) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530601 AUGMENT_LOG(E, "Failed to created a valid stream context from the descriptor: %s",
602 ret.desc.toString().c_str());
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800603 return NO_INIT;
604 }
Mikhail Naganove93a0862023-03-15 17:06:59 -0700605 *inStream = sp<StreamInHalAidl>::make(*config, std::move(context), aidlPatch.latenciesMs[0],
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700606 std::move(ret.stream), mVendorExt, this /*micInfoProvider*/);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700607 {
608 std::lock_guard l(mLock);
Mikhail Naganov78f7f9a2023-11-16 15:49:23 -0800609 mMapper.addStream(*inStream, mixPortConfig.id, aidlPatch.id);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700610 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800611 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000612 return OK;
613}
614
615status_t DeviceHalAidl::supportsAudioPatches(bool* supportsPatches) {
Shunkai Yao35665b12024-08-21 00:30:54 +0000616 AUGMENT_LOG(V);
Jaideep Sharma145313e2024-08-14 14:51:24 +0530617 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700618 if (supportsPatches == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530619 AUGMENT_LOG(E, "uninitialized supportsPatches");
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700620 return BAD_VALUE;
621 }
Shunkai Yao51202502022-12-12 06:11:46 +0000622 *supportsPatches = true;
623 return OK;
624}
625
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800626status_t DeviceHalAidl::createAudioPatch(unsigned int num_sources,
627 const struct audio_port_config* sources,
628 unsigned int num_sinks,
629 const struct audio_port_config* sinks,
630 audio_patch_handle_t* patch) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530631 AUGMENT_LOG(D, "sources: %d sinks %d", num_sources, num_sinks);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000632 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530633 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
634 if (num_sinks > AUDIO_PATCH_PORTS_MAX || num_sources > AUDIO_PATCH_PORTS_MAX) {
635 AUGMENT_LOG(E, "invalid sources %d or sinks %d ", num_sources, num_sinks);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800636 return BAD_VALUE;
637 }
Jaideep Sharma145313e2024-08-14 14:51:24 +0530638
639 if (sources == nullptr || sinks == nullptr || patch == nullptr) {
640 AUGMENT_LOG(E, "uninitialized sources %d or sinks %d or patches %d", (sources == nullptr),
641 (sinks == nullptr), (patch == nullptr));
642 return BAD_VALUE;
643 }
644
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800645 // When the patch handle (*patch) is AUDIO_PATCH_HANDLE_NONE, it means
646 // the framework wants to create a new patch. The handle has to be generated
647 // by the HAL. Since handles generated this way can only be unique within
648 // a HAL module, the framework generates a globally unique handle, and maps
649 // it on the <HAL module, patch handle> pair.
650 // When the patch handle is set, it meant the framework intends to update
651 // an existing patch.
652 //
653 // This behavior corresponds to HAL module behavior, with the only difference
654 // that the HAL module uses `int32_t` for patch IDs. The following assert ensures
655 // that both the framework and the HAL use the same value for "no ID":
656 static_assert(AUDIO_PATCH_HANDLE_NONE == 0);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800657
658 // Upon conversion, mix port configs contain audio configuration, while
659 // device port configs contain device address. This data is used to find
660 // or create HAL configs.
661 std::vector<AudioPortConfig> aidlSources, aidlSinks;
662 for (unsigned int i = 0; i < num_sources; ++i) {
663 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
664 sources[i].role, sources[i].type)) ==
665 ::aidl::android::AudioPortDirection::INPUT;
666 aidlSources.push_back(VALUE_OR_RETURN_STATUS(
667 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
668 sources[i], isInput, 0)));
669 }
670 for (unsigned int i = 0; i < num_sinks; ++i) {
671 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
672 sinks[i].role, sinks[i].type)) ==
673 ::aidl::android::AudioPortDirection::INPUT;
674 aidlSinks.push_back(VALUE_OR_RETURN_STATUS(
675 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
676 sinks[i], isInput, 0)));
677 }
Mikhail Naganov6b5da722024-03-14 12:59:32 -0700678 int32_t aidlPatchId = static_cast<int32_t>(*patch);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700679 Hal2AidlMapper::Cleanups cleanups(mMapperAccessor);
680 {
681 std::lock_guard l(mLock);
Mikhail Naganov6b5da722024-03-14 12:59:32 -0700682 // Check for patches that only exist for the framework, or have different HAL patch ID.
683 if (int32_t aidlHalPatchId = mMapper.findFwkPatch(aidlPatchId); aidlHalPatchId != 0) {
684 if (aidlHalPatchId == aidlPatchId) {
685 // This patch was previously released by the HAL. Thus we need to pass '0'
686 // to the HAL to obtain a new patch.
687 int32_t newAidlPatchId = 0;
688 RETURN_STATUS_IF_ERROR(mMapper.createOrUpdatePatch(
689 aidlSources, aidlSinks, &newAidlPatchId, &cleanups));
690 mMapper.updateFwkPatch(aidlPatchId, newAidlPatchId);
691 } else {
692 RETURN_STATUS_IF_ERROR(mMapper.createOrUpdatePatch(
693 aidlSources, aidlSinks, &aidlHalPatchId, &cleanups));
694 }
695 } else {
696 RETURN_STATUS_IF_ERROR(mMapper.createOrUpdatePatch(
697 aidlSources, aidlSinks, &aidlPatchId, &cleanups));
698 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800699 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700700 *patch = static_cast<audio_patch_handle_t>(aidlPatchId);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800701 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000702 return OK;
703}
704
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800705status_t DeviceHalAidl::releaseAudioPatch(audio_patch_handle_t patch) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530706 AUGMENT_LOG(D, "patch: %d", patch);
707
Mikhail Naganov31d46652023-01-10 18:29:25 +0000708 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530709 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800710 static_assert(AUDIO_PATCH_HANDLE_NONE == 0);
711 if (patch == AUDIO_PATCH_HANDLE_NONE) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800712 return BAD_VALUE;
713 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700714 std::lock_guard l(mLock);
Mikhail Naganov6b5da722024-03-14 12:59:32 -0700715 // Check for patches that only exist for the framework, or have different HAL patch ID.
716 int32_t aidlPatchId = static_cast<int32_t>(patch);
717 if (int32_t aidlHalPatchId = mMapper.findFwkPatch(aidlPatchId); aidlHalPatchId != 0) {
718 if (aidlHalPatchId == aidlPatchId) {
719 // This patch was previously released by the HAL, just need to finish its removal.
720 mMapper.eraseFwkPatch(aidlPatchId);
721 return OK;
722 } else {
723 // This patch has a HAL patch ID which is different
724 aidlPatchId = aidlHalPatchId;
725 }
726 }
727 RETURN_STATUS_IF_ERROR(mMapper.releaseAudioPatch(aidlPatchId));
Shunkai Yao51202502022-12-12 06:11:46 +0000728 return OK;
729}
730
Mikhail Naganove93a0862023-03-15 17:06:59 -0700731status_t DeviceHalAidl::getAudioPort(struct audio_port* port) {
Shunkai Yao35665b12024-08-21 00:30:54 +0000732 AUGMENT_LOG(V);
Jaideep Sharma145313e2024-08-14 14:51:24 +0530733 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganove93a0862023-03-15 17:06:59 -0700734 if (port == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530735 AUGMENT_LOG(E, "port not initialized");
Mikhail Naganove93a0862023-03-15 17:06:59 -0700736 return BAD_VALUE;
737 }
738 audio_port_v7 portV7;
739 audio_populate_audio_port_v7(port, &portV7);
740 RETURN_STATUS_IF_ERROR(getAudioPort(&portV7));
741 return audio_populate_audio_port(&portV7, port) ? OK : BAD_VALUE;
742}
743
744status_t DeviceHalAidl::getAudioPort(struct audio_port_v7 *port) {
Shunkai Yao35665b12024-08-21 00:30:54 +0000745 AUGMENT_LOG(D);
Jaideep Sharma145313e2024-08-14 14:51:24 +0530746
Mikhail Naganove93a0862023-03-15 17:06:59 -0700747 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530748 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganove93a0862023-03-15 17:06:59 -0700749 if (port == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530750 AUGMENT_LOG(E, "port not initialized");
Mikhail Naganove93a0862023-03-15 17:06:59 -0700751 return BAD_VALUE;
752 }
753 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(port->role, port->type)) ==
754 ::aidl::android::AudioPortDirection::INPUT;
755 auto aidlPort = VALUE_OR_RETURN_STATUS(
756 ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
757 if (aidlPort.ext.getTag() != AudioPortExt::device) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530758 AUGMENT_LOG(E, "provided port is not a device port %s", aidlPort.toString().c_str());
Mikhail Naganove93a0862023-03-15 17:06:59 -0700759 return BAD_VALUE;
760 }
761 const auto& matchDevice = aidlPort.ext.get<AudioPortExt::device>().device;
762 // It seems that we don't have to call HAL since all valid ports have been added either
763 // during initialization, or while handling connection of an external device.
Mikhail Naganove93a0862023-03-15 17:06:59 -0700764 const int32_t fwkId = aidlPort.id;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700765 {
766 std::lock_guard l(mLock);
767 RETURN_STATUS_IF_ERROR(mMapper.getAudioPortCached(matchDevice, &aidlPort));
768 }
Mikhail Naganove93a0862023-03-15 17:06:59 -0700769 aidlPort.id = fwkId;
770 *port = VALUE_OR_RETURN_STATUS(::aidl::android::aidl2legacy_AudioPort_audio_port_v7(
771 aidlPort, isInput));
772 return OK;
773}
774
jiabin12537fc2023-10-12 17:56:08 +0000775status_t DeviceHalAidl::getAudioMixPort(const struct audio_port_v7 *devicePort,
776 struct audio_port_v7 *mixPort) {
Shunkai Yao35665b12024-08-21 00:30:54 +0000777 AUGMENT_LOG(D);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700778 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530779 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
780
781 if (devicePort == nullptr || mixPort == nullptr || devicePort->type != AUDIO_PORT_TYPE_DEVICE ||
782 mixPort->type != AUDIO_PORT_TYPE_MIX) {
783 AUGMENT_LOG(E, "invalid device or mix port");
jiabin12537fc2023-10-12 17:56:08 +0000784 return BAD_VALUE;
785 }
786 const int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
787 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(mixPort->ext.mix.handle));
jiabin12537fc2023-10-12 17:56:08 +0000788 AudioPort port;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700789 {
790 std::lock_guard l(mLock);
791 RETURN_STATUS_IF_ERROR(mMapper.getAudioMixPort(aidlHandle, &port));
jiabin12537fc2023-10-12 17:56:08 +0000792 }
793 const bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
794 mixPort->role, mixPort->type)) == ::aidl::android::AudioPortDirection::INPUT;
795 *mixPort = VALUE_OR_RETURN_STATUS(::aidl::android::aidl2legacy_AudioPort_audio_port_v7(
796 port, isInput));
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700797 return OK;
jiabin12537fc2023-10-12 17:56:08 +0000798}
799
Mikhail Naganove93a0862023-03-15 17:06:59 -0700800status_t DeviceHalAidl::setAudioPortConfig(const struct audio_port_config* config) {
Shunkai Yao35665b12024-08-21 00:30:54 +0000801 AUGMENT_LOG(D);
Jaideep Sharma145313e2024-08-14 14:51:24 +0530802
Mikhail Naganove93a0862023-03-15 17:06:59 -0700803 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530804 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganove93a0862023-03-15 17:06:59 -0700805 if (config == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530806 AUGMENT_LOG(E, "config not initialized");
Mikhail Naganove93a0862023-03-15 17:06:59 -0700807 return BAD_VALUE;
808 }
809 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
810 config->role, config->type)) == ::aidl::android::AudioPortDirection::INPUT;
811 AudioPortConfig requestedPortConfig = VALUE_OR_RETURN_STATUS(
812 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
813 *config, isInput, 0 /*portId*/));
814 AudioPortConfig portConfig;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700815 std::lock_guard l(mLock);
Mikhail Naganovca92a5c2023-12-07 14:00:48 -0800816 return mMapper.setPortConfig(requestedPortConfig, std::set<int32_t>(), &portConfig);
Shunkai Yao51202502022-12-12 06:11:46 +0000817}
818
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800819MicrophoneInfoProvider::Info const* DeviceHalAidl::getMicrophoneInfo() {
Shunkai Yao35665b12024-08-21 00:30:54 +0000820 AUGMENT_LOG(D);
Jaideep Sharma145313e2024-08-14 14:51:24 +0530821
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700822 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530823 RETURN_IF_MODULE_NOT_INIT({});
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700824 std::lock_guard l(mLock);
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800825 if (mMicrophones.status == Microphones::Status::UNKNOWN) {
826 TIME_CHECK();
827 std::vector<MicrophoneInfo> aidlInfo;
828 status_t status = statusTFromBinderStatus(mModule->getMicrophones(&aidlInfo));
829 if (status == OK) {
830 mMicrophones.status = Microphones::Status::QUERIED;
831 mMicrophones.info = std::move(aidlInfo);
832 } else if (status == INVALID_OPERATION) {
833 mMicrophones.status = Microphones::Status::NOT_SUPPORTED;
834 } else {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530835 AUGMENT_LOG(E, "Unexpected status from HAL: %d", status);
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800836 return {};
837 }
838 }
839 if (mMicrophones.status == Microphones::Status::QUERIED) {
840 return &mMicrophones.info;
841 }
842 return {}; // NOT_SUPPORTED
843}
844
Shunkai Yao51202502022-12-12 06:11:46 +0000845status_t DeviceHalAidl::getMicrophones(
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800846 std::vector<audio_microphone_characteristic_t>* microphones) {
Shunkai Yao35665b12024-08-21 00:30:54 +0000847 AUGMENT_LOG(D);
Jaideep Sharma145313e2024-08-14 14:51:24 +0530848
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700849 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530850 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700851 if (microphones == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530852 AUGMENT_LOG(E, "microphones not initialized");
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800853 return BAD_VALUE;
854 }
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800855 auto staticInfo = getMicrophoneInfo();
856 if (!staticInfo) return INVALID_OPERATION;
857 std::vector<MicrophoneDynamicInfo> emptyDynamicInfo;
858 emptyDynamicInfo.reserve(staticInfo->size());
859 std::transform(staticInfo->begin(), staticInfo->end(), std::back_inserter(emptyDynamicInfo),
860 [](const auto& info) { return MicrophoneDynamicInfo{ .id = info.id }; });
861 *microphones = VALUE_OR_RETURN_STATUS(
862 ::aidl::android::convertContainers<std::vector<audio_microphone_characteristic_t>>(
863 *staticInfo, emptyDynamicInfo,
864 ::aidl::android::aidl2legacy_MicrophoneInfos_audio_microphone_characteristic_t)
865 );
Shunkai Yao51202502022-12-12 06:11:46 +0000866 return OK;
867}
868
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700869status_t DeviceHalAidl::addDeviceEffect(
870 const struct audio_port_config *device, sp<EffectHalInterface> effect) {
Shunkai Yao35665b12024-08-21 00:30:54 +0000871 AUGMENT_LOG(D);
Jaideep Sharma145313e2024-08-14 14:51:24 +0530872
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700873 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530874 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700875 if (device == nullptr || effect == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530876 AUGMENT_LOG(E, "device or effect not initialized");
Shunkai Yao51202502022-12-12 06:11:46 +0000877 return BAD_VALUE;
878 }
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700879 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
880 device->role, device->type)) == ::aidl::android::AudioPortDirection::INPUT;
881 auto requestedPortConfig = VALUE_OR_RETURN_STATUS(
882 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
883 *device, isInput, 0));
884 if (requestedPortConfig.ext.getTag() != AudioPortExt::Tag::device) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530885 AUGMENT_LOG(E, "provided port config is not a device port config: %s",
886 requestedPortConfig.toString().c_str());
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700887 return BAD_VALUE;
888 }
889 AudioPortConfig devicePortConfig;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700890 Hal2AidlMapper::Cleanups cleanups(mMapperAccessor);
891 {
892 std::lock_guard l(mLock);
Mikhail Naganovca92a5c2023-12-07 14:00:48 -0800893 RETURN_STATUS_IF_ERROR(mMapper.setPortConfig(
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700894 requestedPortConfig, {} /*destinationPortIds*/, &devicePortConfig, &cleanups));
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700895 }
896 auto aidlEffect = sp<effect::EffectHalAidl>::cast(effect);
897 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->addDeviceEffect(
898 devicePortConfig.id, aidlEffect->getIEffect())));
899 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000900 return OK;
901}
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700902status_t DeviceHalAidl::removeDeviceEffect(
903 const struct audio_port_config *device, sp<EffectHalInterface> effect) {
Shunkai Yao35665b12024-08-21 00:30:54 +0000904 AUGMENT_LOG(D);
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700905 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530906 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700907 if (device == nullptr || effect == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530908 AUGMENT_LOG(E, "device or effect not initialized");
Shunkai Yao51202502022-12-12 06:11:46 +0000909 return BAD_VALUE;
910 }
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700911 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
912 device->role, device->type)) == ::aidl::android::AudioPortDirection::INPUT;
913 auto requestedPortConfig = VALUE_OR_RETURN_STATUS(
914 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
915 *device, isInput, 0));
916 if (requestedPortConfig.ext.getTag() != AudioPortExt::Tag::device) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530917 AUGMENT_LOG(E, "provided port config is not a device port config: %s",
918 requestedPortConfig.toString().c_str());
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700919 return BAD_VALUE;
920 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700921 AudioPortConfig devicePortConfig;
922 {
923 std::lock_guard l(mLock);
924 RETURN_STATUS_IF_ERROR(mMapper.findPortConfig(
925 requestedPortConfig.ext.get<AudioPortExt::Tag::device>().device,
926 &devicePortConfig));
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700927 }
928 auto aidlEffect = sp<effect::EffectHalAidl>::cast(effect);
929 return statusTFromBinderStatus(mModule->removeDeviceEffect(
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700930 devicePortConfig.id, aidlEffect->getIEffect()));
Shunkai Yao51202502022-12-12 06:11:46 +0000931}
932
933status_t DeviceHalAidl::getMmapPolicyInfos(
David Li9cf5e622023-03-21 00:51:10 +0800934 media::audio::common::AudioMMapPolicyType policyType,
935 std::vector<media::audio::common::AudioMMapPolicyInfo>* policyInfos) {
Shunkai Yao35665b12024-08-21 00:30:54 +0000936 AUGMENT_LOG(D);
Jaideep Sharma145313e2024-08-14 14:51:24 +0530937
Mikhail Naganov31d46652023-01-10 18:29:25 +0000938 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530939 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
940
941 AudioMMapPolicyType mmapPolicyType =
942 VALUE_OR_RETURN_STATUS(cpp2ndk_AudioMMapPolicyType(policyType));
David Li9cf5e622023-03-21 00:51:10 +0800943
944 std::vector<AudioMMapPolicyInfo> mmapPolicyInfos;
945
946 if (status_t status = statusTFromBinderStatus(
947 mModule->getMmapPolicyInfos(mmapPolicyType, &mmapPolicyInfos)); status != OK) {
948 return status;
949 }
950
951 *policyInfos = VALUE_OR_RETURN_STATUS(
952 convertContainer<std::vector<media::audio::common::AudioMMapPolicyInfo>>(
953 mmapPolicyInfos, ndk2cpp_AudioMMapPolicyInfo));
Shunkai Yao51202502022-12-12 06:11:46 +0000954 return OK;
955}
956
957int32_t DeviceHalAidl::getAAudioMixerBurstCount() {
Shunkai Yao35665b12024-08-21 00:30:54 +0000958 AUGMENT_LOG(D);
Jaideep Sharma145313e2024-08-14 14:51:24 +0530959
Mikhail Naganov31d46652023-01-10 18:29:25 +0000960 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530961 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
David Li9cf5e622023-03-21 00:51:10 +0800962 int32_t mixerBurstCount = 0;
963 if (mModule->getAAudioMixerBurstCount(&mixerBurstCount).isOk()) {
964 return mixerBurstCount;
965 }
966 return 0;
Shunkai Yao51202502022-12-12 06:11:46 +0000967}
968
969int32_t DeviceHalAidl::getAAudioHardwareBurstMinUsec() {
Shunkai Yao35665b12024-08-21 00:30:54 +0000970 AUGMENT_LOG(D);
Jaideep Sharma145313e2024-08-14 14:51:24 +0530971
Mikhail Naganov31d46652023-01-10 18:29:25 +0000972 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530973 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
David Li9cf5e622023-03-21 00:51:10 +0800974 int32_t hardwareBurstMinUsec = 0;
975 if (mModule->getAAudioHardwareBurstMinUsec(&hardwareBurstMinUsec).isOk()) {
976 return hardwareBurstMinUsec;
977 }
978 return 0;
Shunkai Yao51202502022-12-12 06:11:46 +0000979}
980
981error::Result<audio_hw_sync_t> DeviceHalAidl::getHwAvSync() {
Shunkai Yao35665b12024-08-21 00:30:54 +0000982 AUGMENT_LOG(D);
Jaideep Sharma145313e2024-08-14 14:51:24 +0530983
Mikhail Naganov31d46652023-01-10 18:29:25 +0000984 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530985 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganov08a62ab2023-03-14 17:11:51 -0700986 int32_t aidlHwAvSync;
987 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->generateHwAvSyncId(&aidlHwAvSync)));
988 return VALUE_OR_RETURN_STATUS(
989 ::aidl::android::aidl2legacy_int32_t_audio_hw_sync_t(aidlHwAvSync));
Shunkai Yao51202502022-12-12 06:11:46 +0000990}
991
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000992status_t DeviceHalAidl::dump(int fd, const Vector<String16>& args) {
993 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700994 if (mModule == nullptr) return NO_INIT;
David Li21289462024-04-17 01:09:23 +0800995 Vector<String16> newArgs = args;
996 newArgs.push(String16(kDumpFromAudioServerArgument));
997 return mModule->dump(fd, Args(newArgs).args(), newArgs.size());
David Li9cf5e622023-03-21 00:51:10 +0800998}
Shunkai Yao51202502022-12-12 06:11:46 +0000999
Eric Laurent7af6ee72023-06-29 11:44:54 +02001000status_t DeviceHalAidl::supportsBluetoothVariableLatency(bool* supports) {
Shunkai Yao35665b12024-08-21 00:30:54 +00001001 AUGMENT_LOG(D);
Jaideep Sharma145313e2024-08-14 14:51:24 +05301002
Mikhail Naganov31d46652023-01-10 18:29:25 +00001003 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +05301004 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganov3ac95c92023-04-12 13:14:30 -07001005 if (supports == nullptr) {
1006 return BAD_VALUE;
1007 }
1008 return statusTFromBinderStatus(mModule->supportsVariableLatency(supports));
Shunkai Yao51202502022-12-12 06:11:46 +00001009}
Mikhail Naganov31d46652023-01-10 18:29:25 +00001010
Jaideep Sharma145313e2024-08-14 14:51:24 +05301011status_t DeviceHalAidl::getSoundDoseInterface([[maybe_unused]] const std::string& module,
1012 ::ndk::SpAIBinder* soundDoseBinder) {
Shunkai Yao35665b12024-08-21 00:30:54 +00001013 AUGMENT_LOG(V);
Jaideep Sharma145313e2024-08-14 14:51:24 +05301014 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
1015
Mikhail Naganovac9d4e72023-10-23 12:00:09 -07001016 if (soundDoseBinder == nullptr) {
1017 return BAD_VALUE;
1018 }
Vlad Popa03bd5bc2023-01-17 16:16:51 +01001019 if (mSoundDose == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +05301020 AUGMENT_LOG(E, "failed to retrieve the sound dose interface");
Mikhail Naganovac9d4e72023-10-23 12:00:09 -07001021 return BAD_VALUE;
Vlad Popa03bd5bc2023-01-17 16:16:51 +01001022 }
Vlad Popae1f33902023-10-30 19:48:25 -07001023
1024 if (mSoundDose == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +05301025 AUGMENT_LOG(E, "failed to return the sound dose interface not implemented");
Vlad Popae1f33902023-10-30 19:48:25 -07001026 return NO_INIT;
1027 }
1028
Vlad Popa03bd5bc2023-01-17 16:16:51 +01001029 *soundDoseBinder = mSoundDose->asBinder();
Jaideep Sharma145313e2024-08-14 14:51:24 +05301030 AUGMENT_LOG(I, "using audio AIDL HAL sound dose interface");
Vlad Popa03bd5bc2023-01-17 16:16:51 +01001031 return OK;
1032}
jiabin872de702023-04-27 22:04:31 +00001033
1034status_t DeviceHalAidl::prepareToDisconnectExternalDevice(const struct audio_port_v7* port) {
Shunkai Yao35665b12024-08-21 00:30:54 +00001035 AUGMENT_LOG(V);
jiabin62750c22023-12-21 22:06:07 +00001036 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +05301037 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
jiabin62750c22023-12-21 22:06:07 +00001038 if (port == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +05301039 AUGMENT_LOG(E, "port not initialized");
jiabin62750c22023-12-21 22:06:07 +00001040 return BAD_VALUE;
1041 }
Jaideep Sharma145313e2024-08-14 14:51:24 +05301042 const bool isInput =
1043 VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(port->role, port->type)) ==
1044 ::aidl::android::AudioPortDirection::INPUT;
jiabin62750c22023-12-21 22:06:07 +00001045 AudioPort aidlPort = VALUE_OR_RETURN_STATUS(
1046 ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
1047 if (aidlPort.ext.getTag() != AudioPortExt::device) {
Jaideep Sharma145313e2024-08-14 14:51:24 +05301048 AUGMENT_LOG(E, "provided port is not a device port: %s", aidlPort.toString().c_str());
jiabin62750c22023-12-21 22:06:07 +00001049 return BAD_VALUE;
1050 }
Jaideep Sharma145313e2024-08-14 14:51:24 +05301051
1052 AUGMENT_LOG(D, "device %s", aidlPort.toString().c_str());
1053
jiabin62750c22023-12-21 22:06:07 +00001054 status_t status = NO_ERROR;
1055 {
1056 std::lock_guard l(mLock);
1057 status = mMapper.prepareToDisconnectExternalDevice(aidlPort);
1058 }
1059 if (status == UNKNOWN_TRANSACTION) {
1060 // If there is not AIDL API defined for `prepareToDisconnectExternalDevice`.
1061 // Call `setConnectedState` instead.
1062 RETURN_STATUS_IF_ERROR(setConnectedState(port, false /*connected*/));
1063 std::lock_guard l(mLock);
1064 mDeviceDisconnectionNotified.insert(port->id);
1065 // Return that there was no error as otherwise the disconnection procedure will not be
1066 // considered complete for upper layers, and 'setConnectedState' will not be called again
1067 return OK;
1068 } else {
1069 return status;
1070 }
jiabin872de702023-04-27 22:04:31 +00001071}
1072
Mikhail Naganove93a0862023-03-15 17:06:59 -07001073status_t DeviceHalAidl::setConnectedState(const struct audio_port_v7 *port, bool connected) {
Shunkai Yao35665b12024-08-21 00:30:54 +00001074 AUGMENT_LOG(V);
Mikhail Naganove93a0862023-03-15 17:06:59 -07001075 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +05301076 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganove93a0862023-03-15 17:06:59 -07001077 if (port == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +05301078 AUGMENT_LOG(E, "port not initialized");
Mikhail Naganove93a0862023-03-15 17:06:59 -07001079 return BAD_VALUE;
1080 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -07001081 if (!connected) {
1082 std::lock_guard l(mLock);
1083 if (mDeviceDisconnectionNotified.erase(port->id) > 0) {
1084 // For device disconnection, APM will first call `prepareToDisconnectExternalDevice`
jiabin62750c22023-12-21 22:06:07 +00001085 // and then call `setConnectedState`. If `prepareToDisconnectExternalDevice` doesn't
1086 // exit, `setConnectedState` will be called when calling
1087 // `prepareToDisconnectExternalDevice`. Do not call to the HAL if previous call is
1088 // successful. Also remove the cache here to avoid a large cache after a long run.
Mikhail Naganovac9d4e72023-10-23 12:00:09 -07001089 return OK;
1090 }
jiabin872de702023-04-27 22:04:31 +00001091 }
Mikhail Naganove93a0862023-03-15 17:06:59 -07001092 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(port->role, port->type)) ==
1093 ::aidl::android::AudioPortDirection::INPUT;
1094 AudioPort aidlPort = VALUE_OR_RETURN_STATUS(
1095 ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
1096 if (aidlPort.ext.getTag() != AudioPortExt::device) {
Jaideep Sharma145313e2024-08-14 14:51:24 +05301097 AUGMENT_LOG(E, "provided port is not a device port: %s", aidlPort.toString().c_str());
Mikhail Naganove93a0862023-03-15 17:06:59 -07001098 return BAD_VALUE;
1099 }
Jaideep Sharma145313e2024-08-14 14:51:24 +05301100 AUGMENT_LOG(D, "connected %d port: %s", connected, aidlPort.toString().c_str());
Mikhail Naganovac9d4e72023-10-23 12:00:09 -07001101 std::lock_guard l(mLock);
1102 return mMapper.setDevicePortConnectedState(aidlPort, connected);
Mikhail Naganove93a0862023-03-15 17:06:59 -07001103}
1104
1105status_t DeviceHalAidl::setSimulateDeviceConnections(bool enabled) {
Shunkai Yao35665b12024-08-21 00:30:54 +00001106 AUGMENT_LOG(V);
Mikhail Naganove93a0862023-03-15 17:06:59 -07001107 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +05301108 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -07001109 {
1110 std::lock_guard l(mLock);
Mikhail Naganov6b5da722024-03-14 12:59:32 -07001111 mMapper.resetUnusedPatchesAndPortConfigs();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -07001112 }
Mikhail Naganove93a0862023-03-15 17:06:59 -07001113 ModuleDebug debug{ .simulateDeviceConnections = enabled };
1114 status_t status = statusTFromBinderStatus(mModule->setModuleDebug(debug));
1115 // This is important to log as it affects HAL behavior.
1116 if (status == OK) {
Jaideep Sharma145313e2024-08-14 14:51:24 +05301117 AUGMENT_LOG(I, "set enabled: %d", enabled);
Mikhail Naganove93a0862023-03-15 17:06:59 -07001118 } else {
Jaideep Sharma145313e2024-08-14 14:51:24 +05301119 AUGMENT_LOG(W, "set enabled to %d failed: %d", enabled, status);
Mikhail Naganove93a0862023-03-15 17:06:59 -07001120 }
1121 return status;
1122}
1123
Mikhail Naganove7a26ad2023-05-25 17:36:48 -07001124status_t DeviceHalAidl::filterAndRetrieveBtA2dpParameters(
1125 AudioParameter &keys, AudioParameter *result) {
Mikhail Naganove7a26ad2023-05-25 17:36:48 -07001126 if (String8 key = String8(AudioParameter::keyReconfigA2dpSupported); keys.containsKey(key)) {
1127 keys.remove(key);
David Lia7761ed2023-11-03 17:22:07 +00001128 if (mBluetoothA2dp != nullptr) {
1129 bool supports;
1130 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
1131 mBluetoothA2dp->supportsOffloadReconfiguration(&supports)));
1132 result->addInt(key, supports ? 1 : 0);
1133 } else {
Jaideep Sharma145313e2024-08-14 14:51:24 +05301134 AUGMENT_LOG(I, "no IBluetoothA2dp");
David Lia7761ed2023-11-03 17:22:07 +00001135 result->addInt(key, 0);
1136 }
Mikhail Naganove7a26ad2023-05-25 17:36:48 -07001137 }
1138 return OK;
1139}
1140
Eric Laurent7e3c0832023-11-30 15:04:50 +01001141status_t DeviceHalAidl::filterAndRetrieveBtLeParameters(
1142 AudioParameter &keys, AudioParameter *result) {
1143 if (String8 key = String8(AudioParameter::keyReconfigLeSupported); keys.containsKey(key)) {
1144 keys.remove(key);
1145 if (mBluetoothLe != nullptr) {
1146 bool supports;
1147 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
1148 mBluetoothLe->supportsOffloadReconfiguration(&supports)));
1149 result->addInt(key, supports ? 1 : 0);
1150 } else {
Jaideep Sharma145313e2024-08-14 14:51:24 +05301151 AUGMENT_LOG(I, "no mBluetoothLe");
Eric Laurent7e3c0832023-11-30 15:04:50 +01001152 result->addInt(key, 0);
1153 }
1154 }
1155 return OK;
1156}
1157
Mikhail Naganovccc82112023-04-27 18:14:15 -07001158status_t DeviceHalAidl::filterAndUpdateBtA2dpParameters(AudioParameter &parameters) {
Mikhail Naganovccc82112023-04-27 18:14:15 -07001159 std::optional<bool> a2dpEnabled;
Mikhail Naganove7a26ad2023-05-25 17:36:48 -07001160 std::optional<std::vector<VendorParameter>> reconfigureOffload;
Mikhail Naganovccc82112023-04-27 18:14:15 -07001161 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301162 parameters, String8(AudioParameter::keyBtA2dpSuspended),
1163 [&a2dpEnabled, this](const String8& trueOrFalse) {
1164 if (trueOrFalse == AudioParameter::valueTrue) {
1165 a2dpEnabled = false; // 'suspended' == true
1166 return OK;
1167 } else if (trueOrFalse == AudioParameter::valueFalse) {
1168 a2dpEnabled = true; // 'suspended' == false
1169 return OK;
1170 }
1171 AUGMENT_LOG(E, "setParameters: parameter key \"%s\" has invalid value \"%s\"",
1172 AudioParameter::keyBtA2dpSuspended, trueOrFalse.c_str());
1173 return BAD_VALUE;
1174 }));
Mikhail Naganove7a26ad2023-05-25 17:36:48 -07001175 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301176 parameters, String8(AudioParameter::keyReconfigA2dp),
1177 [&](const String8& value) -> status_t {
1178 std::vector<VendorParameter> result;
1179 RETURN_STATUS_IF_ERROR(
1180 statusTFromBinderStatus(mVendorExt->parseBluetoothA2dpReconfigureOffload(
1181 std::string(value.c_str()), &result)));
1182 reconfigureOffload = std::move(result);
1183 return OK;
1184 }));
Mikhail Naganovccc82112023-04-27 18:14:15 -07001185 if (mBluetoothA2dp != nullptr && a2dpEnabled.has_value()) {
1186 return statusTFromBinderStatus(mBluetoothA2dp->setEnabled(a2dpEnabled.value()));
1187 }
Mikhail Naganove7a26ad2023-05-25 17:36:48 -07001188 if (mBluetoothA2dp != nullptr && reconfigureOffload.has_value()) {
1189 return statusTFromBinderStatus(mBluetoothA2dp->reconfigureOffload(
1190 reconfigureOffload.value()));
1191 }
Mikhail Naganovccc82112023-04-27 18:14:15 -07001192 return OK;
1193}
1194
1195status_t DeviceHalAidl::filterAndUpdateBtHfpParameters(AudioParameter &parameters) {
Mikhail Naganovccc82112023-04-27 18:14:15 -07001196 IBluetooth::HfpConfig hfpConfig;
1197 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301198 parameters, String8(AudioParameter::keyBtHfpEnable),
1199 [&hfpConfig, this](const String8& trueOrFalse) {
1200 if (trueOrFalse == AudioParameter::valueTrue) {
1201 hfpConfig.isEnabled = Boolean{.value = true};
1202 return OK;
1203 } else if (trueOrFalse == AudioParameter::valueFalse) {
1204 hfpConfig.isEnabled = Boolean{.value = false};
1205 return OK;
1206 }
1207 AUGMENT_LOG(E, "setParameters: parameter key \"%s\" has invalid value \"%s\"",
1208 AudioParameter::keyBtHfpEnable, trueOrFalse.c_str());
1209 return BAD_VALUE;
1210 }));
Mikhail Naganovccc82112023-04-27 18:14:15 -07001211 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301212 parameters, String8(AudioParameter::keyBtHfpSamplingRate),
1213 [&hfpConfig](int sampleRate) {
1214 return sampleRate > 0 ? hfpConfig.sampleRate = Int{.value = sampleRate},
1215 OK : BAD_VALUE;
1216 }));
Mikhail Naganovccc82112023-04-27 18:14:15 -07001217 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301218 parameters, String8(AudioParameter::keyBtHfpVolume), [&hfpConfig](int volume0to15) {
1219 if (volume0to15 >= 0 && volume0to15 <= 15) {
1220 hfpConfig.volume = Float{.value = volume0to15 / 15.0f};
1221 return OK;
1222 }
1223 return BAD_VALUE;
1224 }));
Mikhail Naganovccc82112023-04-27 18:14:15 -07001225 if (mBluetooth != nullptr && hfpConfig != IBluetooth::HfpConfig{}) {
1226 IBluetooth::HfpConfig newHfpConfig;
1227 return statusTFromBinderStatus(mBluetooth->setHfpConfig(hfpConfig, &newHfpConfig));
1228 }
1229 return OK;
1230}
1231
1232status_t DeviceHalAidl::filterAndUpdateBtLeParameters(AudioParameter &parameters) {
Mikhail Naganovccc82112023-04-27 18:14:15 -07001233 std::optional<bool> leEnabled;
Eric Laurent7e3c0832023-11-30 15:04:50 +01001234 std::optional<std::vector<VendorParameter>> reconfigureOffload;
Mikhail Naganovccc82112023-04-27 18:14:15 -07001235 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301236 parameters, String8(AudioParameter::keyBtLeSuspended),
1237 [&leEnabled, this](const String8& trueOrFalse) {
1238 if (trueOrFalse == AudioParameter::valueTrue) {
1239 leEnabled = false; // 'suspended' == true
1240 return OK;
1241 } else if (trueOrFalse == AudioParameter::valueFalse) {
1242 leEnabled = true; // 'suspended' == false
1243 return OK;
1244 }
1245 AUGMENT_LOG(E, "setParameters: parameter key \"%s\" has invalid value \"%s\"",
1246 AudioParameter::keyBtLeSuspended, trueOrFalse.c_str());
1247 return BAD_VALUE;
1248 }));
Eric Laurent7e3c0832023-11-30 15:04:50 +01001249 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301250 parameters, String8(AudioParameter::keyReconfigLe),
1251 [&](const String8& value) -> status_t {
1252 if (mVendorExt != nullptr) {
1253 std::vector<VendorParameter> result;
1254 RETURN_STATUS_IF_ERROR(
1255 statusTFromBinderStatus(mVendorExt->parseBluetoothLeReconfigureOffload(
1256 std::string(value.c_str()), &result)));
1257 reconfigureOffload = std::move(result);
1258 } else {
1259 reconfigureOffload = std::vector<VendorParameter>();
1260 }
1261 return OK;
1262 }));
Mikhail Naganovccc82112023-04-27 18:14:15 -07001263 if (mBluetoothLe != nullptr && leEnabled.has_value()) {
1264 return statusTFromBinderStatus(mBluetoothLe->setEnabled(leEnabled.value()));
1265 }
Eric Laurent7e3c0832023-11-30 15:04:50 +01001266 if (mBluetoothLe != nullptr && reconfigureOffload.has_value()) {
Jaideep Sharma145313e2024-08-14 14:51:24 +05301267 return statusTFromBinderStatus(
1268 mBluetoothLe->reconfigureOffload(reconfigureOffload.value()));
Eric Laurent7e3c0832023-11-30 15:04:50 +01001269 }
Mikhail Naganovccc82112023-04-27 18:14:15 -07001270 return OK;
1271}
1272
1273status_t DeviceHalAidl::filterAndUpdateBtScoParameters(AudioParameter &parameters) {
Mikhail Naganovccc82112023-04-27 18:14:15 -07001274 IBluetooth::ScoConfig scoConfig;
1275 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301276 parameters, String8(AudioParameter::keyBtSco),
1277 [&scoConfig, this](const String8& onOrOff) {
1278 if (onOrOff == AudioParameter::valueOn) {
1279 scoConfig.isEnabled = Boolean{.value = true};
1280 return OK;
1281 } else if (onOrOff == AudioParameter::valueOff) {
1282 scoConfig.isEnabled = Boolean{.value = false};
1283 return OK;
1284 }
1285 AUGMENT_LOG(E, "setParameters: parameter key \"%s\" has invalid value \"%s\"",
1286 AudioParameter::keyBtSco, onOrOff.c_str());
1287 return BAD_VALUE;
1288 }));
Mikhail Naganovccc82112023-04-27 18:14:15 -07001289 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301290 parameters, String8(AudioParameter::keyBtScoHeadsetName),
1291 [&scoConfig](const String8& name) {
1292 scoConfig.debugName = name;
1293 return OK;
1294 }));
Mikhail Naganovccc82112023-04-27 18:14:15 -07001295 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301296 parameters, String8(AudioParameter::keyBtNrec),
1297 [&scoConfig, this](const String8& onOrOff) {
1298 if (onOrOff == AudioParameter::valueOn) {
1299 scoConfig.isNrecEnabled = Boolean{.value = true};
1300 return OK;
1301 } else if (onOrOff == AudioParameter::valueOff) {
1302 scoConfig.isNrecEnabled = Boolean{.value = false};
1303 return OK;
1304 }
1305 AUGMENT_LOG(E, "setParameters: parameter key \"%s\" has invalid value \"%s\"",
1306 AudioParameter::keyBtNrec, onOrOff.c_str());
1307 return BAD_VALUE;
1308 }));
Mikhail Naganovccc82112023-04-27 18:14:15 -07001309 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301310 parameters, String8(AudioParameter::keyBtScoWb),
1311 [&scoConfig, this](const String8& onOrOff) {
1312 if (onOrOff == AudioParameter::valueOn) {
1313 scoConfig.mode = IBluetooth::ScoConfig::Mode::SCO_WB;
1314 return OK;
1315 } else if (onOrOff == AudioParameter::valueOff) {
1316 scoConfig.mode = IBluetooth::ScoConfig::Mode::SCO;
1317 return OK;
1318 }
1319 AUGMENT_LOG(E, "setParameters: parameter key \"%s\" has invalid value \"%s\"",
1320 AudioParameter::keyBtScoWb, onOrOff.c_str());
1321 return BAD_VALUE;
1322 }));
Mikhail Naganovccc82112023-04-27 18:14:15 -07001323 if (mBluetooth != nullptr && scoConfig != IBluetooth::ScoConfig{}) {
1324 IBluetooth::ScoConfig newScoConfig;
1325 return statusTFromBinderStatus(mBluetooth->setScoConfig(scoConfig, &newScoConfig));
1326 }
1327 return OK;
1328}
1329
Mikhail Naganove92c34b2023-05-31 14:24:48 -07001330status_t DeviceHalAidl::filterAndUpdateScreenParameters(AudioParameter &parameters) {
Mikhail Naganove92c34b2023-05-31 14:24:48 -07001331 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301332 parameters, String8(AudioParameter::keyScreenState),
1333 [&, this](const String8& onOrOff) -> status_t {
1334 std::optional<bool> isTurnedOn;
1335 if (onOrOff == AudioParameter::valueOn) {
1336 isTurnedOn = true;
1337 } else if (onOrOff == AudioParameter::valueOff) {
1338 isTurnedOn = false;
1339 }
1340 if (!isTurnedOn.has_value()) {
1341 AUGMENT_LOG(E, "setParameters: parameter key \"%s\" has invalid value \"%s\"",
1342 AudioParameter::keyScreenState, onOrOff.c_str());
1343 return BAD_VALUE;
1344 }
1345 return statusTFromBinderStatus(mModule->updateScreenState(isTurnedOn.value()));
1346 }));
Mikhail Naganove92c34b2023-05-31 14:24:48 -07001347 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301348 parameters, String8(AudioParameter::keyScreenRotation),
1349 [&, this](int rotationDegrees) -> status_t {
Mikhail Naganove92c34b2023-05-31 14:24:48 -07001350 IModule::ScreenRotation rotation;
1351 switch (rotationDegrees) {
Jaideep Sharma145313e2024-08-14 14:51:24 +05301352 case 0:
1353 rotation = IModule::ScreenRotation::DEG_0;
1354 break;
1355 case 90:
1356 rotation = IModule::ScreenRotation::DEG_90;
1357 break;
1358 case 180:
1359 rotation = IModule::ScreenRotation::DEG_180;
1360 break;
1361 case 270:
1362 rotation = IModule::ScreenRotation::DEG_270;
1363 break;
Mikhail Naganove92c34b2023-05-31 14:24:48 -07001364 default:
Jaideep Sharma145313e2024-08-14 14:51:24 +05301365 AUGMENT_LOG(E, "setParameters: parameter key \"%s\" has invalid value %d",
1366 AudioParameter::keyScreenRotation, rotationDegrees);
Mikhail Naganove92c34b2023-05-31 14:24:48 -07001367 return BAD_VALUE;
1368 }
1369 return statusTFromBinderStatus(mModule->updateScreenRotation(rotation));
1370 }));
1371 return OK;
1372}
1373
Mikhail Naganovb9a81312023-07-18 13:55:34 -07001374status_t DeviceHalAidl::filterAndUpdateTelephonyParameters(AudioParameter &parameters) {
Mikhail Naganovb9a81312023-07-18 13:55:34 -07001375 using TtyMode = ITelephony::TelecomConfig::TtyMode;
1376 ITelephony::TelecomConfig telConfig;
1377 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301378 parameters, String8(AudioParameter::keyTtyMode),
1379 [&telConfig, this](const String8& mode) {
1380 if (mode == AudioParameter::valueTtyModeOff) {
1381 telConfig.ttyMode = TtyMode::OFF;
1382 return OK;
1383 } else if (mode == AudioParameter::valueTtyModeFull) {
1384 telConfig.ttyMode = TtyMode::FULL;
1385 return OK;
1386 } else if (mode == AudioParameter::valueTtyModeHco) {
1387 telConfig.ttyMode = TtyMode::HCO;
1388 return OK;
1389 } else if (mode == AudioParameter::valueTtyModeVco) {
1390 telConfig.ttyMode = TtyMode::VCO;
1391 return OK;
1392 }
1393 AUGMENT_LOG(E, "setParameters: parameter key \"%s\" has invalid value \"%s\"",
1394 AudioParameter::keyTtyMode, mode.c_str());
1395 return BAD_VALUE;
1396 }));
Mikhail Naganovb9a81312023-07-18 13:55:34 -07001397 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301398 parameters, String8(AudioParameter::keyHacSetting),
1399 [&telConfig, this](const String8& onOrOff) {
1400 if (onOrOff == AudioParameter::valueHacOn) {
1401 telConfig.isHacEnabled = Boolean{.value = true};
1402 return OK;
1403 } else if (onOrOff == AudioParameter::valueHacOff) {
1404 telConfig.isHacEnabled = Boolean{.value = false};
1405 return OK;
1406 }
1407 AUGMENT_LOG(E, "setParameters: parameter key \"%s\" has invalid value \"%s\"",
1408 AudioParameter::keyHacSetting, onOrOff.c_str());
1409 return BAD_VALUE;
1410 }));
Mikhail Naganovb9a81312023-07-18 13:55:34 -07001411 if (mTelephony != nullptr && telConfig != ITelephony::TelecomConfig{}) {
1412 ITelephony::TelecomConfig newTelConfig;
Jaideep Sharma145313e2024-08-14 14:51:24 +05301413 return statusTFromBinderStatus(mTelephony->setTelecomConfig(telConfig, &newTelConfig));
Mikhail Naganovb9a81312023-07-18 13:55:34 -07001414 }
1415 return OK;
1416}
1417
Mikhail Naganovdfd594e2023-02-08 16:59:41 -08001418void DeviceHalAidl::clearCallbacks(void* cookie) {
Mikhail Naganov22578412024-08-16 16:50:34 -07001419 std::lock_guard l(mCallbacksLock);
Mikhail Naganovdfd594e2023-02-08 16:59:41 -08001420 mCallbacks.erase(cookie);
1421}
1422
1423sp<StreamOutHalInterfaceCallback> DeviceHalAidl::getStreamOutCallback(void* cookie) {
1424 return getCallbackImpl(cookie, &Callbacks::out);
1425}
1426
1427void DeviceHalAidl::setStreamOutCallback(
1428 void* cookie, const sp<StreamOutHalInterfaceCallback>& cb) {
1429 setCallbackImpl(cookie, &Callbacks::out, cb);
1430}
1431
1432sp<StreamOutHalInterfaceEventCallback> DeviceHalAidl::getStreamOutEventCallback(
1433 void* cookie) {
1434 return getCallbackImpl(cookie, &Callbacks::event);
1435}
1436
1437void DeviceHalAidl::setStreamOutEventCallback(
1438 void* cookie, const sp<StreamOutHalInterfaceEventCallback>& cb) {
1439 setCallbackImpl(cookie, &Callbacks::event, cb);
1440}
1441
1442sp<StreamOutHalInterfaceLatencyModeCallback> DeviceHalAidl::getStreamOutLatencyModeCallback(
1443 void* cookie) {
1444 return getCallbackImpl(cookie, &Callbacks::latency);
1445}
1446
1447void DeviceHalAidl::setStreamOutLatencyModeCallback(
1448 void* cookie, const sp<StreamOutHalInterfaceLatencyModeCallback>& cb) {
1449 setCallbackImpl(cookie, &Callbacks::latency, cb);
1450}
1451
Mikhail Naganov22578412024-08-16 16:50:34 -07001452template <class C>
Mikhail Naganovdfd594e2023-02-08 16:59:41 -08001453sp<C> DeviceHalAidl::getCallbackImpl(void* cookie, wp<C> DeviceHalAidl::Callbacks::* field) {
Mikhail Naganov22578412024-08-16 16:50:34 -07001454 wp<C> result;
1455 {
1456 std::lock_guard l(mCallbacksLock);
1457 if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
1458 result = (it->second).*field;
1459 }
Mikhail Naganovdfd594e2023-02-08 16:59:41 -08001460 }
Mikhail Naganov22578412024-08-16 16:50:34 -07001461 return result.promote();
Mikhail Naganovdfd594e2023-02-08 16:59:41 -08001462}
1463template<class C>
1464void DeviceHalAidl::setCallbackImpl(
1465 void* cookie, wp<C> DeviceHalAidl::Callbacks::* field, const sp<C>& cb) {
Mikhail Naganov22578412024-08-16 16:50:34 -07001466 std::lock_guard l(mCallbacksLock);
Mikhail Naganovdfd594e2023-02-08 16:59:41 -08001467 if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
1468 (it->second).*field = cb;
1469 }
1470}
1471
Mikhail Naganov31d46652023-01-10 18:29:25 +00001472} // namespace android