blob: f2792812965d12882c31063413ad184a9d5707b4 [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;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -080063using aidl::android::hardware::audio::common::RecordTrackMetadata;
Haofan Wangbf44e092024-07-07 15:29:38 -070064using aidl::android::hardware::audio::common::PlaybackTrackMetadata;
65using aidl::android::hardware::audio::common::SourceMetadata;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -070066using aidl::android::hardware::audio::core::sounddose::ISoundDose;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -080067using aidl::android::hardware::audio::core::AudioPatch;
Mikhail Naganov289468a2023-03-29 10:06:15 -070068using aidl::android::hardware::audio::core::AudioRoute;
Mikhail Naganovccc82112023-04-27 18:14:15 -070069using aidl::android::hardware::audio::core::IBluetooth;
70using aidl::android::hardware::audio::core::IBluetoothA2dp;
71using aidl::android::hardware::audio::core::IBluetoothLe;
Mikhail Naganovfab697c2023-01-11 19:33:13 +000072using aidl::android::hardware::audio::core::IModule;
73using aidl::android::hardware::audio::core::ITelephony;
Mikhail Naganove93a0862023-03-15 17:06:59 -070074using aidl::android::hardware::audio::core::ModuleDebug;
Mikhail Naganove7a26ad2023-05-25 17:36:48 -070075using aidl::android::hardware::audio::core::VendorParameter;
Mikhail Naganov31d46652023-01-10 18:29:25 +000076
Jaideep Sharma145313e2024-08-14 14:51:24 +053077#define RETURN_IF_MODULE_NOT_INIT(retVal) \
78 if (mModule == nullptr) { \
79 AUGMENT_LOG(E, "module not initialized"); \
80 return retVal; \
81 }
82
83#define RETURN_IF_TELEPHONY_NOT_INIT(retVal) \
84 if (mTelephony == nullptr) { \
85 AUGMENT_LOG(E, "telephony not initialized"); \
86 return retVal; \
87 }
88
Mikhail Naganov31d46652023-01-10 18:29:25 +000089namespace android {
90
Mikhail Naganov5b1eed12023-01-25 11:29:11 -080091namespace {
92
Mikhail Naganovf83b9742023-04-24 13:06:04 -070093// Note: these converters are for types defined in different AIDL files. Although these
94// AIDL files are copies of each other, however formally these are different types
95// thus we don't use a conversion via a parcelable.
96ConversionResult<media::AudioRoute> ndk2cpp_AudioRoute(const AudioRoute& ndk) {
97 media::AudioRoute cpp;
98 cpp.sourcePortIds.insert(
99 cpp.sourcePortIds.end(), ndk.sourcePortIds.begin(), ndk.sourcePortIds.end());
100 cpp.sinkPortId = ndk.sinkPortId;
101 cpp.isExclusive = ndk.isExclusive;
David Li9cf5e622023-03-21 00:51:10 +0800102 return cpp;
103}
104
Mikhail Naganov1fba38c2023-05-03 17:45:36 -0700105template<typename T>
106std::shared_ptr<T> retrieveSubInterface(const std::shared_ptr<IModule>& module,
107 ::ndk::ScopedAStatus (IModule::*getT)(std::shared_ptr<T>*)) {
108 if (module != nullptr) {
109 std::shared_ptr<T> instance;
110 if (auto status = (module.get()->*getT)(&instance); status.isOk()) {
111 return instance;
112 }
113 }
114 return nullptr;
115}
116
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800117} // namespace
118
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700119DeviceHalAidl::DeviceHalAidl(const std::string& instance, const std::shared_ptr<IModule>& module,
120 const std::shared_ptr<IHalAdapterVendorExtension>& vext)
Jaideep Sharma145313e2024-08-14 14:51:24 +0530121 : ConversionHelperAidl("DeviceHalAidl", instance),
122 mModule(module),
123 mVendorExt(vext),
124 mTelephony(retrieveSubInterface<ITelephony>(module, &IModule::getTelephony)),
125 mBluetooth(retrieveSubInterface<IBluetooth>(module, &IModule::getBluetooth)),
126 mBluetoothA2dp(retrieveSubInterface<IBluetoothA2dp>(module, &IModule::getBluetoothA2dp)),
127 mBluetoothLe(retrieveSubInterface<IBluetoothLe>(module, &IModule::getBluetoothLe)),
128 mSoundDose(retrieveSubInterface<ISoundDose>(module, &IModule::getSoundDose)),
129 mMapper(instance, module),
130 mMapperAccessor(mMapper, mLock) {}
Mikhail Naganov1fba38c2023-05-03 17:45:36 -0700131
Mikhail Naganovf83b9742023-04-24 13:06:04 -0700132status_t DeviceHalAidl::getAudioPorts(std::vector<media::audio::common::AudioPort> *ports) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700133 std::lock_guard l(mLock);
134 return mMapper.getAudioPorts(ports, ndk2cpp_AudioPort);
Mikhail Naganovf83b9742023-04-24 13:06:04 -0700135}
136
137status_t DeviceHalAidl::getAudioRoutes(std::vector<media::AudioRoute> *routes) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700138 std::lock_guard l(mLock);
139 return mMapper.getAudioRoutes(routes, ndk2cpp_AudioRoute);
Mikhail Naganovf83b9742023-04-24 13:06:04 -0700140}
141
Mikhail Naganov1fba38c2023-05-03 17:45:36 -0700142status_t DeviceHalAidl::getSupportedModes(std::vector<media::audio::common::AudioMode> *modes) {
Shunkai Yao35665b12024-08-21 00:30:54 +0000143 AUGMENT_LOG(D);
Mikhail Naganov1fba38c2023-05-03 17:45:36 -0700144 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530145 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
146 RETURN_IF_TELEPHONY_NOT_INIT(INVALID_OPERATION);
147
Mikhail Naganov1fba38c2023-05-03 17:45:36 -0700148 if (modes == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530149 AUGMENT_LOG(E, "uninitialized modes");
Mikhail Naganov1fba38c2023-05-03 17:45:36 -0700150 return BAD_VALUE;
151 }
Mikhail Naganov1fba38c2023-05-03 17:45:36 -0700152 std::vector<AudioMode> aidlModes;
153 RETURN_STATUS_IF_ERROR(
154 statusTFromBinderStatus(mTelephony->getSupportedAudioModes(&aidlModes)));
155 *modes = VALUE_OR_RETURN_STATUS(
156 ::aidl::android::convertContainer<std::vector<media::audio::common::AudioMode>>(
157 aidlModes, ndk2cpp_AudioMode));
158 return OK;
159}
160
Mikhail Naganov31d46652023-01-10 18:29:25 +0000161status_t DeviceHalAidl::getSupportedDevices(uint32_t*) {
162 // Obsolete.
163 return INVALID_OPERATION;
Shunkai Yao51202502022-12-12 06:11:46 +0000164}
165
166status_t DeviceHalAidl::initCheck() {
Shunkai Yao35665b12024-08-21 00:30:54 +0000167 AUGMENT_LOG(D);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800168 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530169 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700170 std::lock_guard l(mLock);
171 return mMapper.initialize();
Shunkai Yao51202502022-12-12 06:11:46 +0000172}
173
174status_t DeviceHalAidl::setVoiceVolume(float volume) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530175 AUGMENT_LOG(D, "volume %f", volume);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000176 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530177 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
178 RETURN_IF_TELEPHONY_NOT_INIT(INVALID_OPERATION);
179
180 ITelephony::TelecomConfig inConfig{.voiceVolume = Float{volume}}, outConfig;
Mikhail Naganov1fba38c2023-05-03 17:45:36 -0700181 RETURN_STATUS_IF_ERROR(
182 statusTFromBinderStatus(mTelephony->setTelecomConfig(inConfig, &outConfig)));
Jaideep Sharma145313e2024-08-14 14:51:24 +0530183 AUGMENT_LOG_IF(
184 W, outConfig.voiceVolume.has_value() && volume != outConfig.voiceVolume.value().value,
185 "the resulting voice volume %f is not the same as requested %f",
186 outConfig.voiceVolume.value().value, volume);
Mikhail Naganov1fba38c2023-05-03 17:45:36 -0700187 return OK;
Shunkai Yao51202502022-12-12 06:11:46 +0000188}
189
190status_t DeviceHalAidl::setMasterVolume(float volume) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530191 AUGMENT_LOG(D, "volume %f", volume);
192
Mikhail Naganov31d46652023-01-10 18:29:25 +0000193 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530194 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000195 return statusTFromBinderStatus(mModule->setMasterVolume(volume));
Shunkai Yao51202502022-12-12 06:11:46 +0000196}
197
198status_t DeviceHalAidl::getMasterVolume(float *volume) {
Shunkai Yao35665b12024-08-21 00:30:54 +0000199 AUGMENT_LOG(D);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000200 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530201 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700202 if (volume == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530203 AUGMENT_LOG(E, "uninitialized volumes");
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700204 return BAD_VALUE;
205 }
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000206 return statusTFromBinderStatus(mModule->getMasterVolume(volume));
Shunkai Yao51202502022-12-12 06:11:46 +0000207}
208
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000209status_t DeviceHalAidl::setMode(audio_mode_t mode) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530210 AUGMENT_LOG(D, "mode %d", mode);
211
Mikhail Naganov31d46652023-01-10 18:29:25 +0000212 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530213 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000214 AudioMode audioMode = VALUE_OR_FATAL(::aidl::android::legacy2aidl_audio_mode_t_AudioMode(mode));
Mikhail Naganov1fba38c2023-05-03 17:45:36 -0700215 if (mTelephony != nullptr) {
216 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mTelephony->switchAudioMode(audioMode)));
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000217 }
218 return statusTFromBinderStatus(mModule->updateAudioMode(audioMode));
Shunkai Yao51202502022-12-12 06:11:46 +0000219}
220
221status_t DeviceHalAidl::setMicMute(bool state) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530222 AUGMENT_LOG(D, "mute %d", state);
223
Mikhail Naganov31d46652023-01-10 18:29:25 +0000224 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530225 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000226 return statusTFromBinderStatus(mModule->setMicMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000227}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000228
Shunkai Yao51202502022-12-12 06:11:46 +0000229status_t DeviceHalAidl::getMicMute(bool *state) {
Shunkai Yao35665b12024-08-21 00:30:54 +0000230 AUGMENT_LOG(D);
Jaideep Sharma145313e2024-08-14 14:51:24 +0530231
Mikhail Naganov31d46652023-01-10 18:29:25 +0000232 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530233 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700234 if (state == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530235 AUGMENT_LOG(E, "uninitialized mute state");
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700236 return BAD_VALUE;
237 }
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000238 return statusTFromBinderStatus(mModule->getMicMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000239}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000240
Shunkai Yao51202502022-12-12 06:11:46 +0000241status_t DeviceHalAidl::setMasterMute(bool state) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530242 AUGMENT_LOG(D, "mute %d", state);
243
Mikhail Naganov31d46652023-01-10 18:29:25 +0000244 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530245 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000246 return statusTFromBinderStatus(mModule->setMasterMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000247}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000248
Shunkai Yao51202502022-12-12 06:11:46 +0000249status_t DeviceHalAidl::getMasterMute(bool *state) {
Shunkai Yao35665b12024-08-21 00:30:54 +0000250 AUGMENT_LOG(D);
Jaideep Sharma145313e2024-08-14 14:51:24 +0530251
Mikhail Naganov31d46652023-01-10 18:29:25 +0000252 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530253 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700254 if (state == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530255 AUGMENT_LOG(E, "uninitialized mute state");
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700256 return BAD_VALUE;
257 }
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000258 return statusTFromBinderStatus(mModule->getMasterMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000259}
260
Mikhail Naganovccc82112023-04-27 18:14:15 -0700261status_t DeviceHalAidl::setParameters(const String8& kvPairs) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700262 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530263 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovccc82112023-04-27 18:14:15 -0700264 AudioParameter parameters(kvPairs);
Jaideep Sharma145313e2024-08-14 14:51:24 +0530265 AUGMENT_LOG(D, "parameters: \"%s\"", parameters.toString().c_str());
Mikhail Naganovccc82112023-04-27 18:14:15 -0700266
267 if (status_t status = filterAndUpdateBtA2dpParameters(parameters); status != OK) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530268 AUGMENT_LOG(W, "filterAndUpdateBtA2dpParameters failed: %d", status);
Mikhail Naganovccc82112023-04-27 18:14:15 -0700269 }
270 if (status_t status = filterAndUpdateBtHfpParameters(parameters); status != OK) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530271 AUGMENT_LOG(W, "filterAndUpdateBtHfpParameters failed: %d", status);
Mikhail Naganovccc82112023-04-27 18:14:15 -0700272 }
273 if (status_t status = filterAndUpdateBtLeParameters(parameters); status != OK) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530274 AUGMENT_LOG(W, "filterAndUpdateBtLeParameters failed: %d", status);
Mikhail Naganovccc82112023-04-27 18:14:15 -0700275 }
276 if (status_t status = filterAndUpdateBtScoParameters(parameters); status != OK) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530277 AUGMENT_LOG(W, "filterAndUpdateBtScoParameters failed: %d", status);
Mikhail Naganovccc82112023-04-27 18:14:15 -0700278 }
Mikhail Naganove92c34b2023-05-31 14:24:48 -0700279 if (status_t status = filterAndUpdateScreenParameters(parameters); status != OK) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530280 AUGMENT_LOG(W, "filterAndUpdateScreenParameters failed: %d", status);
Mikhail Naganove92c34b2023-05-31 14:24:48 -0700281 }
Mikhail Naganovb9a81312023-07-18 13:55:34 -0700282 if (status_t status = filterAndUpdateTelephonyParameters(parameters); status != OK) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530283 AUGMENT_LOG(W, "filterAndUpdateTelephonyParameters failed: %d", status);
Mikhail Naganovb9a81312023-07-18 13:55:34 -0700284 }
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700285 return parseAndSetVendorParameters(mVendorExt, mModule, parameters);
Shunkai Yao51202502022-12-12 06:11:46 +0000286}
287
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700288status_t DeviceHalAidl::getParameters(const String8& keys, String8 *values) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530289 AUGMENT_LOG(D, "keys: \"%s\"", keys.c_str());
290
Mikhail Naganov31d46652023-01-10 18:29:25 +0000291 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530292 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700293 if (values == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530294 AUGMENT_LOG(E, "invalid values");
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700295 return BAD_VALUE;
296 }
297 AudioParameter parameterKeys(keys), result;
298 if (status_t status = filterAndRetrieveBtA2dpParameters(parameterKeys, &result); status != OK) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530299 AUGMENT_LOG(W, "filterAndRetrieveBtA2dpParameters failed: %d", status);
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700300 }
Eric Laurent7e3c0832023-11-30 15:04:50 +0100301 if (status_t status = filterAndRetrieveBtLeParameters(parameterKeys, &result); status != OK) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530302 AUGMENT_LOG(W, "filterAndRetrieveBtLeParameters failed: %d", status);
Eric Laurent7e3c0832023-11-30 15:04:50 +0100303 }
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700304 *values = result.toString();
305 return parseAndGetVendorParameters(mVendorExt, mModule, parameterKeys, values);
Shunkai Yao51202502022-12-12 06:11:46 +0000306}
307
Mikhail Naganovd5b643f2024-02-15 11:51:26 -0800308status_t DeviceHalAidl::getInputBufferSize(struct audio_config* config, size_t* size) {
Shunkai Yao35665b12024-08-21 00:30:54 +0000309 AUGMENT_LOG(D);
Jaideep Sharma145313e2024-08-14 14:51:24 +0530310
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800311 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530312 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700313 if (config == nullptr || size == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530314 AUGMENT_LOG(E, "invalid config or size");
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700315 return BAD_VALUE;
316 }
Mikhail Naganovd5b643f2024-02-15 11:51:26 -0800317 constexpr bool isInput = true;
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800318 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
Mikhail Naganovd5b643f2024-02-15 11:51:26 -0800319 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, isInput));
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800320 AudioDevice aidlDevice;
321 aidlDevice.type.type = AudioDeviceType::IN_DEFAULT;
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800322 AudioSource aidlSource = AudioSource::DEFAULT;
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800323 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::input>(0);
324 AudioPortConfig mixPortConfig;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700325 Hal2AidlMapper::Cleanups cleanups(mMapperAccessor);
Mikhail Naganove93a0862023-03-15 17:06:59 -0700326 AudioPatch aidlPatch;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700327 {
328 std::lock_guard l(mLock);
329 RETURN_STATUS_IF_ERROR(mMapper.prepareToOpenStream(
330 0 /*handle*/, aidlDevice, aidlFlags, aidlSource,
331 &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
332 }
Mikhail Naganovd5b643f2024-02-15 11:51:26 -0800333 *config = VALUE_OR_RETURN_STATUS(
334 ::aidl::android::aidl2legacy_AudioConfig_audio_config_t(aidlConfig, isInput));
335 if (mixPortConfig.id == 0) return BAD_VALUE; // HAL suggests a different config.
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800336 *size = aidlConfig.frameCount *
337 getFrameSizeInBytes(aidlConfig.base.format, aidlConfig.base.channelMask);
338 // Do not disarm cleanups to release temporary port configs.
339 return OK;
340}
341
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800342namespace {
343
344class StreamCallbackBase {
345 protected:
346 explicit StreamCallbackBase(const sp<CallbackBroker>& broker) : mBroker(broker) {}
347 public:
348 void* getCookie() const { return mCookie; }
349 void setCookie(void* cookie) { mCookie = cookie; }
350 sp<CallbackBroker> getBroker() const {
351 if (void* cookie = mCookie; cookie != nullptr) return mBroker.promote();
352 return nullptr;
353 }
354 private:
355 const wp<CallbackBroker> mBroker;
356 std::atomic<void*> mCookie;
357};
358
359template<class C>
360class StreamCallbackBaseHelper {
361 protected:
362 explicit StreamCallbackBaseHelper(const StreamCallbackBase& base) : mBase(base) {}
363 sp<C> getCb(const sp<CallbackBroker>& broker, void* cookie);
364 using CbRef = const sp<C>&;
365 ndk::ScopedAStatus runCb(const std::function<void(CbRef cb)>& f) {
366 if (auto cb = getCb(mBase.getBroker(), mBase.getCookie()); cb != nullptr) f(cb);
367 return ndk::ScopedAStatus::ok();
368 }
369 private:
370 const StreamCallbackBase& mBase;
371};
372
373template<>
374sp<StreamOutHalInterfaceCallback> StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>::getCb(
375 const sp<CallbackBroker>& broker, void* cookie) {
376 if (broker != nullptr) return broker->getStreamOutCallback(cookie);
377 return nullptr;
378}
379
380template<>
381sp<StreamOutHalInterfaceEventCallback>
382StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>::getCb(
383 const sp<CallbackBroker>& broker, void* cookie) {
384 if (broker != nullptr) return broker->getStreamOutEventCallback(cookie);
385 return nullptr;
386}
387
388template<>
389sp<StreamOutHalInterfaceLatencyModeCallback>
390StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>::getCb(
391 const sp<CallbackBroker>& broker, void* cookie) {
392 if (broker != nullptr) return broker->getStreamOutLatencyModeCallback(cookie);
393 return nullptr;
394}
395
396/*
397Note on the callback ownership.
398
399In the Binder ownership model, the server implementation is kept alive
400as long as there is any client (proxy object) alive. This is done by
401incrementing the refcount of the server-side object by the Binder framework.
402When it detects that the last client is gone, it decrements the refcount back.
403
404Thus, it is not needed to keep any references to StreamCallback on our
405side (after we have sent an instance to the client), because we are
406the server-side. The callback object will be kept alive as long as the HAL server
407holds a strong ref to IStreamCallback proxy.
408*/
409
410class OutputStreamCallbackAidl : public StreamCallbackBase,
411 public StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>,
412 public ::aidl::android::hardware::audio::core::BnStreamCallback {
413 public:
414 explicit OutputStreamCallbackAidl(const sp<CallbackBroker>& broker)
415 : StreamCallbackBase(broker),
416 StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>(
417 *static_cast<StreamCallbackBase*>(this)) {}
418 ndk::ScopedAStatus onTransferReady() override {
419 return runCb([](CbRef cb) { cb->onWriteReady(); });
420 }
421 ndk::ScopedAStatus onError() override {
Mikhail Naganovf548cd32024-05-29 17:06:46 +0000422 return runCb([](CbRef cb) { cb->onError(true /*isHardError*/); });
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800423 }
424 ndk::ScopedAStatus onDrainReady() override {
425 return runCb([](CbRef cb) { cb->onDrainReady(); });
426 }
427};
428
429class OutputStreamEventCallbackAidl :
430 public StreamCallbackBase,
431 public StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>,
432 public StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>,
433 public ::aidl::android::hardware::audio::core::BnStreamOutEventCallback {
434 public:
435 explicit OutputStreamEventCallbackAidl(const sp<CallbackBroker>& broker)
436 : StreamCallbackBase(broker),
437 StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>(
438 *static_cast<StreamCallbackBase*>(this)),
439 StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>(
440 *static_cast<StreamCallbackBase*>(this)) {}
Ryan Prichard78c5e452024-02-08 16:16:57 -0800441 ndk::ScopedAStatus onCodecFormatChanged(const std::vector<uint8_t>& halMetadata) override {
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800442 return StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>::runCb(
443 [&halMetadata](auto cb) { cb->onCodecFormatChanged(halMetadata); });
444 }
445 ndk::ScopedAStatus onRecommendedLatencyModeChanged(
446 const std::vector<AudioLatencyMode>& in_modes) override {
447 auto halModes = VALUE_OR_FATAL(
448 ::aidl::android::convertContainer<std::vector<audio_latency_mode_t>>(
449 in_modes,
450 ::aidl::android::aidl2legacy_AudioLatencyMode_audio_latency_mode_t));
451 return StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>::runCb(
452 [&halModes](auto cb) { cb->onRecommendedLatencyModeChanged(halModes); });
453 }
454};
455
456} // namespace
457
Mikhail Naganov31d46652023-01-10 18:29:25 +0000458status_t DeviceHalAidl::openOutputStream(
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800459 audio_io_handle_t handle, audio_devices_t devices,
460 audio_output_flags_t flags, struct audio_config* config,
461 const char* address,
Haofan Wangbf44e092024-07-07 15:29:38 -0700462 sp<StreamOutHalInterface>* outStream,
463 const std::vector<playback_track_metadata_v7_t>& sourceMetadata) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530464 AUGMENT_LOG(D, "handle: %d devices %0x flags %0x", handle, devices, flags);
Shunkai Yao35665b12024-08-21 00:30:54 +0000465
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700466 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530467 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700468 if (outStream == nullptr || config == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530469 AUGMENT_LOG(E, "invalid outStream or config");
Mikhail Naganov31d46652023-01-10 18:29:25 +0000470 return BAD_VALUE;
471 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700472 constexpr bool isInput = false;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800473 int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
474 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(handle));
475 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700476 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, isInput));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800477 AudioDevice aidlDevice = VALUE_OR_RETURN_STATUS(
478 ::aidl::android::legacy2aidl_audio_device_AudioDevice(devices, address));
479 int32_t aidlOutputFlags = VALUE_OR_RETURN_STATUS(
480 ::aidl::android::legacy2aidl_audio_output_flags_t_int32_t_mask(flags));
Haofan Wangbf44e092024-07-07 15:29:38 -0700481 SourceMetadata aidlMetadata = VALUE_OR_RETURN_STATUS(
482 ::aidl::android::legacy2aidl_SourceMetadata(sourceMetadata));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800483 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::output>(aidlOutputFlags);
484 AudioPortConfig mixPortConfig;
Mikhail Naganove93a0862023-03-15 17:06:59 -0700485 AudioPatch aidlPatch;
Haofan Wangbf44e092024-07-07 15:29:38 -0700486
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700487 Hal2AidlMapper::Cleanups cleanups(mMapperAccessor);
488 {
489 std::lock_guard l(mLock);
490 RETURN_STATUS_IF_ERROR(mMapper.prepareToOpenStream(aidlHandle, aidlDevice, aidlFlags,
491 AudioSource::SYS_RESERVED_INVALID /*only needed for input*/,
492 &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
493 }
494 *config = VALUE_OR_RETURN_STATUS(
495 ::aidl::android::aidl2legacy_AudioConfig_audio_config_t(aidlConfig, isInput));
Mikhail Naganovca92a5c2023-12-07 14:00:48 -0800496 if (mixPortConfig.id == 0) return BAD_VALUE; // HAL suggests a different config.
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800497 ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamArguments args;
498 args.portConfigId = mixPortConfig.id;
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800499 const bool isOffload = isBitPositionFlagSet(
500 aidlOutputFlags, AudioOutputFlags::COMPRESS_OFFLOAD);
Kuowei Li3b9a69d2024-06-07 17:54:32 +0800501 const bool isHwAvSync = isBitPositionFlagSet(
502 aidlOutputFlags, AudioOutputFlags::HW_AV_SYNC);
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800503 std::shared_ptr<OutputStreamCallbackAidl> streamCb;
504 if (isOffload) {
505 streamCb = ndk::SharedRefBase::make<OutputStreamCallbackAidl>(this);
506 }
507 auto eventCb = ndk::SharedRefBase::make<OutputStreamEventCallbackAidl>(this);
Kuowei Li3b9a69d2024-06-07 17:54:32 +0800508 if (isOffload || isHwAvSync) {
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800509 args.offloadInfo = aidlConfig.offloadInfo;
Kuowei Li3b9a69d2024-06-07 17:54:32 +0800510 }
511 if (isOffload) {
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800512 args.callback = streamCb;
513 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800514 args.bufferSizeFrames = aidlConfig.frameCount;
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800515 args.eventCallback = eventCb;
Haofan Wangbf44e092024-07-07 15:29:38 -0700516 args.sourceMetadata = aidlMetadata;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800517 ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamReturn ret;
518 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openOutputStream(args, &ret)));
Jaideep Sharma145313e2024-08-14 14:51:24 +0530519 StreamContextAidl context(ret.desc, isOffload, aidlHandle);
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800520 if (!context.isValid()) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530521 AUGMENT_LOG(E, "Failed to created a valid stream context from the descriptor: %s",
522 ret.desc.toString().c_str());
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800523 return NO_INIT;
524 }
Mikhail Naganov23224a12024-03-28 02:15:21 +0000525 auto stream = sp<StreamOutHalAidl>::make(*config, std::move(context), aidlPatch.latenciesMs[0],
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700526 std::move(ret.stream), mVendorExt, this /*callbackBroker*/);
Mikhail Naganov23224a12024-03-28 02:15:21 +0000527 *outStream = stream;
528 /* StreamOutHalInterface* */ void* cbCookie = (*outStream).get();
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800529 {
Mikhail Naganov22578412024-08-16 16:50:34 -0700530 std::lock_guard l(mCallbacksLock);
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800531 mCallbacks.emplace(cbCookie, Callbacks{});
Mikhail Naganov22578412024-08-16 16:50:34 -0700532 }
533 {
534 std::lock_guard l(mLock);
Mikhail Naganov78f7f9a2023-11-16 15:49:23 -0800535 mMapper.addStream(*outStream, mixPortConfig.id, aidlPatch.id);
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800536 }
Mikhail Naganov23224a12024-03-28 02:15:21 +0000537 if (streamCb) {
538 streamCb->setCookie(cbCookie);
539 // Although StreamOutHalAidl implements StreamOutHalInterfaceCallback,
540 // we always go via the CallbackBroker for consistency.
541 setStreamOutCallback(cbCookie, stream);
542 }
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800543 eventCb->setCookie(cbCookie);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800544 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000545 return OK;
546}
547
Mikhail Naganov31d46652023-01-10 18:29:25 +0000548status_t DeviceHalAidl::openInputStream(
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800549 audio_io_handle_t handle, audio_devices_t devices,
550 struct audio_config* config, audio_input_flags_t flags,
551 const char* address, audio_source_t source,
552 audio_devices_t outputDevice, const char* outputDeviceAddress,
Mikhail Naganov31d46652023-01-10 18:29:25 +0000553 sp<StreamInHalInterface>* inStream) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530554 AUGMENT_LOG(D, "handle: %d devices %0x flags %0x", handle, devices, flags);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700555 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530556 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700557 if (inStream == nullptr || config == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530558 AUGMENT_LOG(E, "invalid inStream or config");
Mikhail Naganov31d46652023-01-10 18:29:25 +0000559 return BAD_VALUE;
560 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700561 constexpr bool isInput = true;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800562 int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
563 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(handle));
564 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700565 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, isInput));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800566 AudioDevice aidlDevice = VALUE_OR_RETURN_STATUS(
567 ::aidl::android::legacy2aidl_audio_device_AudioDevice(devices, address));
568 int32_t aidlInputFlags = VALUE_OR_RETURN_STATUS(
569 ::aidl::android::legacy2aidl_audio_input_flags_t_int32_t_mask(flags));
570 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::input>(aidlInputFlags);
571 AudioSource aidlSource = VALUE_OR_RETURN_STATUS(
572 ::aidl::android::legacy2aidl_audio_source_t_AudioSource(source));
573 AudioPortConfig mixPortConfig;
Mikhail Naganove93a0862023-03-15 17:06:59 -0700574 AudioPatch aidlPatch;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700575 Hal2AidlMapper::Cleanups cleanups(mMapperAccessor);
576 {
577 std::lock_guard l(mLock);
578 RETURN_STATUS_IF_ERROR(mMapper.prepareToOpenStream(
579 aidlHandle, aidlDevice, aidlFlags, aidlSource,
580 &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
581 }
582 *config = VALUE_OR_RETURN_STATUS(
583 ::aidl::android::aidl2legacy_AudioConfig_audio_config_t(aidlConfig, isInput));
Mikhail Naganovca92a5c2023-12-07 14:00:48 -0800584 if (mixPortConfig.id == 0) return BAD_VALUE; // HAL suggests a different config.
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800585 ::aidl::android::hardware::audio::core::IModule::OpenInputStreamArguments args;
586 args.portConfigId = mixPortConfig.id;
587 RecordTrackMetadata aidlTrackMetadata{
588 .source = aidlSource, .gain = 1, .channelMask = aidlConfig.base.channelMask };
589 if (outputDevice != AUDIO_DEVICE_NONE) {
590 aidlTrackMetadata.destinationDevice = VALUE_OR_RETURN_STATUS(
591 ::aidl::android::legacy2aidl_audio_device_AudioDevice(
592 outputDevice, outputDeviceAddress));
593 }
594 args.sinkMetadata.tracks.push_back(std::move(aidlTrackMetadata));
595 args.bufferSizeFrames = aidlConfig.frameCount;
596 ::aidl::android::hardware::audio::core::IModule::OpenInputStreamReturn ret;
597 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openInputStream(args, &ret)));
Jaideep Sharma145313e2024-08-14 14:51:24 +0530598 StreamContextAidl context(ret.desc, false /*isAsynchronous*/, aidlHandle);
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800599 if (!context.isValid()) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530600 AUGMENT_LOG(E, "Failed to created a valid stream context from the descriptor: %s",
601 ret.desc.toString().c_str());
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800602 return NO_INIT;
603 }
Mikhail Naganove93a0862023-03-15 17:06:59 -0700604 *inStream = sp<StreamInHalAidl>::make(*config, std::move(context), aidlPatch.latenciesMs[0],
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700605 std::move(ret.stream), mVendorExt, this /*micInfoProvider*/);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700606 {
607 std::lock_guard l(mLock);
Mikhail Naganov78f7f9a2023-11-16 15:49:23 -0800608 mMapper.addStream(*inStream, mixPortConfig.id, aidlPatch.id);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700609 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800610 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000611 return OK;
612}
613
614status_t DeviceHalAidl::supportsAudioPatches(bool* supportsPatches) {
Shunkai Yao35665b12024-08-21 00:30:54 +0000615 AUGMENT_LOG(V);
Jaideep Sharma145313e2024-08-14 14:51:24 +0530616 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700617 if (supportsPatches == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530618 AUGMENT_LOG(E, "uninitialized supportsPatches");
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700619 return BAD_VALUE;
620 }
Shunkai Yao51202502022-12-12 06:11:46 +0000621 *supportsPatches = true;
622 return OK;
623}
624
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800625status_t DeviceHalAidl::createAudioPatch(unsigned int num_sources,
626 const struct audio_port_config* sources,
627 unsigned int num_sinks,
628 const struct audio_port_config* sinks,
629 audio_patch_handle_t* patch) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530630 AUGMENT_LOG(D, "sources: %d sinks %d", num_sources, num_sinks);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000631 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530632 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
633 if (num_sinks > AUDIO_PATCH_PORTS_MAX || num_sources > AUDIO_PATCH_PORTS_MAX) {
634 AUGMENT_LOG(E, "invalid sources %d or sinks %d ", num_sources, num_sinks);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800635 return BAD_VALUE;
636 }
Jaideep Sharma145313e2024-08-14 14:51:24 +0530637
638 if (sources == nullptr || sinks == nullptr || patch == nullptr) {
639 AUGMENT_LOG(E, "uninitialized sources %d or sinks %d or patches %d", (sources == nullptr),
640 (sinks == nullptr), (patch == nullptr));
641 return BAD_VALUE;
642 }
643
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800644 // When the patch handle (*patch) is AUDIO_PATCH_HANDLE_NONE, it means
645 // the framework wants to create a new patch. The handle has to be generated
646 // by the HAL. Since handles generated this way can only be unique within
647 // a HAL module, the framework generates a globally unique handle, and maps
648 // it on the <HAL module, patch handle> pair.
649 // When the patch handle is set, it meant the framework intends to update
650 // an existing patch.
651 //
652 // This behavior corresponds to HAL module behavior, with the only difference
653 // that the HAL module uses `int32_t` for patch IDs. The following assert ensures
654 // that both the framework and the HAL use the same value for "no ID":
655 static_assert(AUDIO_PATCH_HANDLE_NONE == 0);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800656
657 // Upon conversion, mix port configs contain audio configuration, while
658 // device port configs contain device address. This data is used to find
659 // or create HAL configs.
660 std::vector<AudioPortConfig> aidlSources, aidlSinks;
661 for (unsigned int i = 0; i < num_sources; ++i) {
662 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
663 sources[i].role, sources[i].type)) ==
664 ::aidl::android::AudioPortDirection::INPUT;
665 aidlSources.push_back(VALUE_OR_RETURN_STATUS(
666 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
667 sources[i], isInput, 0)));
668 }
669 for (unsigned int i = 0; i < num_sinks; ++i) {
670 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
671 sinks[i].role, sinks[i].type)) ==
672 ::aidl::android::AudioPortDirection::INPUT;
673 aidlSinks.push_back(VALUE_OR_RETURN_STATUS(
674 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
675 sinks[i], isInput, 0)));
676 }
Mikhail Naganova317a802024-03-15 18:03:10 +0000677 int32_t aidlPatchId = static_cast<int32_t>(*patch);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700678 Hal2AidlMapper::Cleanups cleanups(mMapperAccessor);
679 {
680 std::lock_guard l(mLock);
Mikhail Naganova317a802024-03-15 18:03:10 +0000681 // Check for patches that only exist for the framework, or have different HAL patch ID.
682 if (int32_t aidlHalPatchId = mMapper.findFwkPatch(aidlPatchId); aidlHalPatchId != 0) {
683 if (aidlHalPatchId == aidlPatchId) {
684 // This patch was previously released by the HAL. Thus we need to pass '0'
685 // to the HAL to obtain a new patch.
686 int32_t newAidlPatchId = 0;
687 RETURN_STATUS_IF_ERROR(mMapper.createOrUpdatePatch(
688 aidlSources, aidlSinks, &newAidlPatchId, &cleanups));
689 mMapper.updateFwkPatch(aidlPatchId, newAidlPatchId);
690 } else {
691 RETURN_STATUS_IF_ERROR(mMapper.createOrUpdatePatch(
692 aidlSources, aidlSinks, &aidlHalPatchId, &cleanups));
693 }
694 } else {
695 RETURN_STATUS_IF_ERROR(mMapper.createOrUpdatePatch(
696 aidlSources, aidlSinks, &aidlPatchId, &cleanups));
697 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800698 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700699 *patch = static_cast<audio_patch_handle_t>(aidlPatchId);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800700 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000701 return OK;
702}
703
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800704status_t DeviceHalAidl::releaseAudioPatch(audio_patch_handle_t patch) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530705 AUGMENT_LOG(D, "patch: %d", patch);
706
Mikhail Naganov31d46652023-01-10 18:29:25 +0000707 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530708 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800709 static_assert(AUDIO_PATCH_HANDLE_NONE == 0);
710 if (patch == AUDIO_PATCH_HANDLE_NONE) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800711 return BAD_VALUE;
712 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700713 std::lock_guard l(mLock);
Mikhail Naganova317a802024-03-15 18:03:10 +0000714 // Check for patches that only exist for the framework, or have different HAL patch ID.
715 int32_t aidlPatchId = static_cast<int32_t>(patch);
716 if (int32_t aidlHalPatchId = mMapper.findFwkPatch(aidlPatchId); aidlHalPatchId != 0) {
717 if (aidlHalPatchId == aidlPatchId) {
718 // This patch was previously released by the HAL, just need to finish its removal.
719 mMapper.eraseFwkPatch(aidlPatchId);
720 return OK;
721 } else {
722 // This patch has a HAL patch ID which is different
723 aidlPatchId = aidlHalPatchId;
724 }
725 }
726 RETURN_STATUS_IF_ERROR(mMapper.releaseAudioPatch(aidlPatchId));
Shunkai Yao51202502022-12-12 06:11:46 +0000727 return OK;
728}
729
Mikhail Naganove93a0862023-03-15 17:06:59 -0700730status_t DeviceHalAidl::getAudioPort(struct audio_port* port) {
Shunkai Yao35665b12024-08-21 00:30:54 +0000731 AUGMENT_LOG(V);
Jaideep Sharma145313e2024-08-14 14:51:24 +0530732 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganove93a0862023-03-15 17:06:59 -0700733 if (port == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530734 AUGMENT_LOG(E, "port not initialized");
Mikhail Naganove93a0862023-03-15 17:06:59 -0700735 return BAD_VALUE;
736 }
737 audio_port_v7 portV7;
738 audio_populate_audio_port_v7(port, &portV7);
739 RETURN_STATUS_IF_ERROR(getAudioPort(&portV7));
740 return audio_populate_audio_port(&portV7, port) ? OK : BAD_VALUE;
741}
742
743status_t DeviceHalAidl::getAudioPort(struct audio_port_v7 *port) {
Shunkai Yao35665b12024-08-21 00:30:54 +0000744 AUGMENT_LOG(D);
Jaideep Sharma145313e2024-08-14 14:51:24 +0530745
Mikhail Naganove93a0862023-03-15 17:06:59 -0700746 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530747 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganove93a0862023-03-15 17:06:59 -0700748 if (port == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530749 AUGMENT_LOG(E, "port not initialized");
Mikhail Naganove93a0862023-03-15 17:06:59 -0700750 return BAD_VALUE;
751 }
752 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(port->role, port->type)) ==
753 ::aidl::android::AudioPortDirection::INPUT;
754 auto aidlPort = VALUE_OR_RETURN_STATUS(
755 ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
756 if (aidlPort.ext.getTag() != AudioPortExt::device) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530757 AUGMENT_LOG(E, "provided port is not a device port %s", aidlPort.toString().c_str());
Mikhail Naganove93a0862023-03-15 17:06:59 -0700758 return BAD_VALUE;
759 }
760 const auto& matchDevice = aidlPort.ext.get<AudioPortExt::device>().device;
761 // It seems that we don't have to call HAL since all valid ports have been added either
762 // during initialization, or while handling connection of an external device.
Mikhail Naganove93a0862023-03-15 17:06:59 -0700763 const int32_t fwkId = aidlPort.id;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700764 {
765 std::lock_guard l(mLock);
766 RETURN_STATUS_IF_ERROR(mMapper.getAudioPortCached(matchDevice, &aidlPort));
767 }
Mikhail Naganove93a0862023-03-15 17:06:59 -0700768 aidlPort.id = fwkId;
769 *port = VALUE_OR_RETURN_STATUS(::aidl::android::aidl2legacy_AudioPort_audio_port_v7(
770 aidlPort, isInput));
771 return OK;
772}
773
jiabin12537fc2023-10-12 17:56:08 +0000774status_t DeviceHalAidl::getAudioMixPort(const struct audio_port_v7 *devicePort,
775 struct audio_port_v7 *mixPort) {
Shunkai Yao35665b12024-08-21 00:30:54 +0000776 AUGMENT_LOG(D);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700777 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530778 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
779
780 if (devicePort == nullptr || mixPort == nullptr || devicePort->type != AUDIO_PORT_TYPE_DEVICE ||
781 mixPort->type != AUDIO_PORT_TYPE_MIX) {
782 AUGMENT_LOG(E, "invalid device or mix port");
jiabin12537fc2023-10-12 17:56:08 +0000783 return BAD_VALUE;
784 }
785 const int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
786 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(mixPort->ext.mix.handle));
jiabin12537fc2023-10-12 17:56:08 +0000787 AudioPort port;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700788 {
789 std::lock_guard l(mLock);
790 RETURN_STATUS_IF_ERROR(mMapper.getAudioMixPort(aidlHandle, &port));
jiabin12537fc2023-10-12 17:56:08 +0000791 }
792 const bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
793 mixPort->role, mixPort->type)) == ::aidl::android::AudioPortDirection::INPUT;
794 *mixPort = VALUE_OR_RETURN_STATUS(::aidl::android::aidl2legacy_AudioPort_audio_port_v7(
795 port, isInput));
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700796 return OK;
jiabin12537fc2023-10-12 17:56:08 +0000797}
798
Mikhail Naganove93a0862023-03-15 17:06:59 -0700799status_t DeviceHalAidl::setAudioPortConfig(const struct audio_port_config* config) {
Shunkai Yao35665b12024-08-21 00:30:54 +0000800 AUGMENT_LOG(D);
Jaideep Sharma145313e2024-08-14 14:51:24 +0530801
Mikhail Naganove93a0862023-03-15 17:06:59 -0700802 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530803 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganove93a0862023-03-15 17:06:59 -0700804 if (config == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530805 AUGMENT_LOG(E, "config not initialized");
Mikhail Naganove93a0862023-03-15 17:06:59 -0700806 return BAD_VALUE;
807 }
808 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
809 config->role, config->type)) == ::aidl::android::AudioPortDirection::INPUT;
810 AudioPortConfig requestedPortConfig = VALUE_OR_RETURN_STATUS(
811 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
812 *config, isInput, 0 /*portId*/));
813 AudioPortConfig portConfig;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700814 std::lock_guard l(mLock);
Mikhail Naganovca92a5c2023-12-07 14:00:48 -0800815 return mMapper.setPortConfig(requestedPortConfig, std::set<int32_t>(), &portConfig);
Shunkai Yao51202502022-12-12 06:11:46 +0000816}
817
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800818MicrophoneInfoProvider::Info const* DeviceHalAidl::getMicrophoneInfo() {
Shunkai Yao35665b12024-08-21 00:30:54 +0000819 AUGMENT_LOG(D);
Jaideep Sharma145313e2024-08-14 14:51:24 +0530820
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700821 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530822 RETURN_IF_MODULE_NOT_INIT({});
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700823 std::lock_guard l(mLock);
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800824 if (mMicrophones.status == Microphones::Status::UNKNOWN) {
825 TIME_CHECK();
826 std::vector<MicrophoneInfo> aidlInfo;
827 status_t status = statusTFromBinderStatus(mModule->getMicrophones(&aidlInfo));
828 if (status == OK) {
829 mMicrophones.status = Microphones::Status::QUERIED;
830 mMicrophones.info = std::move(aidlInfo);
831 } else if (status == INVALID_OPERATION) {
832 mMicrophones.status = Microphones::Status::NOT_SUPPORTED;
833 } else {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530834 AUGMENT_LOG(E, "Unexpected status from HAL: %d", status);
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800835 return {};
836 }
837 }
838 if (mMicrophones.status == Microphones::Status::QUERIED) {
839 return &mMicrophones.info;
840 }
841 return {}; // NOT_SUPPORTED
842}
843
Shunkai Yao51202502022-12-12 06:11:46 +0000844status_t DeviceHalAidl::getMicrophones(
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800845 std::vector<audio_microphone_characteristic_t>* microphones) {
Shunkai Yao35665b12024-08-21 00:30:54 +0000846 AUGMENT_LOG(D);
Jaideep Sharma145313e2024-08-14 14:51:24 +0530847
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700848 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530849 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700850 if (microphones == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530851 AUGMENT_LOG(E, "microphones not initialized");
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800852 return BAD_VALUE;
853 }
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800854 auto staticInfo = getMicrophoneInfo();
855 if (!staticInfo) return INVALID_OPERATION;
856 std::vector<MicrophoneDynamicInfo> emptyDynamicInfo;
857 emptyDynamicInfo.reserve(staticInfo->size());
858 std::transform(staticInfo->begin(), staticInfo->end(), std::back_inserter(emptyDynamicInfo),
859 [](const auto& info) { return MicrophoneDynamicInfo{ .id = info.id }; });
860 *microphones = VALUE_OR_RETURN_STATUS(
861 ::aidl::android::convertContainers<std::vector<audio_microphone_characteristic_t>>(
862 *staticInfo, emptyDynamicInfo,
863 ::aidl::android::aidl2legacy_MicrophoneInfos_audio_microphone_characteristic_t)
864 );
Shunkai Yao51202502022-12-12 06:11:46 +0000865 return OK;
866}
867
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700868status_t DeviceHalAidl::addDeviceEffect(
869 const struct audio_port_config *device, sp<EffectHalInterface> effect) {
Shunkai Yao35665b12024-08-21 00:30:54 +0000870 AUGMENT_LOG(D);
Jaideep Sharma145313e2024-08-14 14:51:24 +0530871
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700872 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530873 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700874 if (device == nullptr || effect == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530875 AUGMENT_LOG(E, "device or effect not initialized");
Shunkai Yao51202502022-12-12 06:11:46 +0000876 return BAD_VALUE;
877 }
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700878 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
879 device->role, device->type)) == ::aidl::android::AudioPortDirection::INPUT;
880 auto requestedPortConfig = VALUE_OR_RETURN_STATUS(
881 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
882 *device, isInput, 0));
883 if (requestedPortConfig.ext.getTag() != AudioPortExt::Tag::device) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530884 AUGMENT_LOG(E, "provided port config is not a device port config: %s",
885 requestedPortConfig.toString().c_str());
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700886 return BAD_VALUE;
887 }
888 AudioPortConfig devicePortConfig;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700889 Hal2AidlMapper::Cleanups cleanups(mMapperAccessor);
890 {
891 std::lock_guard l(mLock);
Mikhail Naganovca92a5c2023-12-07 14:00:48 -0800892 RETURN_STATUS_IF_ERROR(mMapper.setPortConfig(
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700893 requestedPortConfig, {} /*destinationPortIds*/, &devicePortConfig, &cleanups));
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700894 }
895 auto aidlEffect = sp<effect::EffectHalAidl>::cast(effect);
896 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->addDeviceEffect(
897 devicePortConfig.id, aidlEffect->getIEffect())));
898 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000899 return OK;
900}
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700901status_t DeviceHalAidl::removeDeviceEffect(
902 const struct audio_port_config *device, sp<EffectHalInterface> effect) {
Shunkai Yao35665b12024-08-21 00:30:54 +0000903 AUGMENT_LOG(D);
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700904 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530905 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700906 if (device == nullptr || effect == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530907 AUGMENT_LOG(E, "device or effect not initialized");
Shunkai Yao51202502022-12-12 06:11:46 +0000908 return BAD_VALUE;
909 }
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700910 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
911 device->role, device->type)) == ::aidl::android::AudioPortDirection::INPUT;
912 auto requestedPortConfig = VALUE_OR_RETURN_STATUS(
913 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
914 *device, isInput, 0));
915 if (requestedPortConfig.ext.getTag() != AudioPortExt::Tag::device) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530916 AUGMENT_LOG(E, "provided port config is not a device port config: %s",
917 requestedPortConfig.toString().c_str());
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700918 return BAD_VALUE;
919 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700920 AudioPortConfig devicePortConfig;
921 {
922 std::lock_guard l(mLock);
923 RETURN_STATUS_IF_ERROR(mMapper.findPortConfig(
924 requestedPortConfig.ext.get<AudioPortExt::Tag::device>().device,
925 &devicePortConfig));
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700926 }
927 auto aidlEffect = sp<effect::EffectHalAidl>::cast(effect);
928 return statusTFromBinderStatus(mModule->removeDeviceEffect(
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700929 devicePortConfig.id, aidlEffect->getIEffect()));
Shunkai Yao51202502022-12-12 06:11:46 +0000930}
931
932status_t DeviceHalAidl::getMmapPolicyInfos(
David Li9cf5e622023-03-21 00:51:10 +0800933 media::audio::common::AudioMMapPolicyType policyType,
934 std::vector<media::audio::common::AudioMMapPolicyInfo>* policyInfos) {
Shunkai Yao35665b12024-08-21 00:30:54 +0000935 AUGMENT_LOG(D);
Jaideep Sharma145313e2024-08-14 14:51:24 +0530936
Mikhail Naganov31d46652023-01-10 18:29:25 +0000937 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530938 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
939
940 AudioMMapPolicyType mmapPolicyType =
941 VALUE_OR_RETURN_STATUS(cpp2ndk_AudioMMapPolicyType(policyType));
David Li9cf5e622023-03-21 00:51:10 +0800942
943 std::vector<AudioMMapPolicyInfo> mmapPolicyInfos;
944
945 if (status_t status = statusTFromBinderStatus(
946 mModule->getMmapPolicyInfos(mmapPolicyType, &mmapPolicyInfos)); status != OK) {
947 return status;
948 }
949
950 *policyInfos = VALUE_OR_RETURN_STATUS(
951 convertContainer<std::vector<media::audio::common::AudioMMapPolicyInfo>>(
952 mmapPolicyInfos, ndk2cpp_AudioMMapPolicyInfo));
Shunkai Yao51202502022-12-12 06:11:46 +0000953 return OK;
954}
955
956int32_t DeviceHalAidl::getAAudioMixerBurstCount() {
Shunkai Yao35665b12024-08-21 00:30:54 +0000957 AUGMENT_LOG(D);
Jaideep Sharma145313e2024-08-14 14:51:24 +0530958
Mikhail Naganov31d46652023-01-10 18:29:25 +0000959 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530960 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
David Li9cf5e622023-03-21 00:51:10 +0800961 int32_t mixerBurstCount = 0;
962 if (mModule->getAAudioMixerBurstCount(&mixerBurstCount).isOk()) {
963 return mixerBurstCount;
964 }
965 return 0;
Shunkai Yao51202502022-12-12 06:11:46 +0000966}
967
968int32_t DeviceHalAidl::getAAudioHardwareBurstMinUsec() {
Shunkai Yao35665b12024-08-21 00:30:54 +0000969 AUGMENT_LOG(D);
Jaideep Sharma145313e2024-08-14 14:51:24 +0530970
Mikhail Naganov31d46652023-01-10 18:29:25 +0000971 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530972 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
David Li9cf5e622023-03-21 00:51:10 +0800973 int32_t hardwareBurstMinUsec = 0;
974 if (mModule->getAAudioHardwareBurstMinUsec(&hardwareBurstMinUsec).isOk()) {
975 return hardwareBurstMinUsec;
976 }
977 return 0;
Shunkai Yao51202502022-12-12 06:11:46 +0000978}
979
980error::Result<audio_hw_sync_t> DeviceHalAidl::getHwAvSync() {
Shunkai Yao35665b12024-08-21 00:30:54 +0000981 AUGMENT_LOG(D);
Jaideep Sharma145313e2024-08-14 14:51:24 +0530982
Mikhail Naganov31d46652023-01-10 18:29:25 +0000983 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530984 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganov08a62ab2023-03-14 17:11:51 -0700985 int32_t aidlHwAvSync;
986 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->generateHwAvSyncId(&aidlHwAvSync)));
987 return VALUE_OR_RETURN_STATUS(
988 ::aidl::android::aidl2legacy_int32_t_audio_hw_sync_t(aidlHwAvSync));
Shunkai Yao51202502022-12-12 06:11:46 +0000989}
990
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000991status_t DeviceHalAidl::dump(int fd, const Vector<String16>& args) {
992 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700993 if (mModule == nullptr) return NO_INIT;
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000994 return mModule->dump(fd, Args(args).args(), args.size());
David Li9cf5e622023-03-21 00:51:10 +0800995}
Shunkai Yao51202502022-12-12 06:11:46 +0000996
Eric Laurent7af6ee72023-06-29 11:44:54 +0200997status_t DeviceHalAidl::supportsBluetoothVariableLatency(bool* supports) {
Shunkai Yao35665b12024-08-21 00:30:54 +0000998 AUGMENT_LOG(D);
Jaideep Sharma145313e2024-08-14 14:51:24 +0530999
Mikhail Naganov31d46652023-01-10 18:29:25 +00001000 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +05301001 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganov3ac95c92023-04-12 13:14:30 -07001002 if (supports == nullptr) {
1003 return BAD_VALUE;
1004 }
1005 return statusTFromBinderStatus(mModule->supportsVariableLatency(supports));
Shunkai Yao51202502022-12-12 06:11:46 +00001006}
Mikhail Naganov31d46652023-01-10 18:29:25 +00001007
Jaideep Sharma145313e2024-08-14 14:51:24 +05301008status_t DeviceHalAidl::getSoundDoseInterface([[maybe_unused]] const std::string& module,
1009 ::ndk::SpAIBinder* soundDoseBinder) {
Shunkai Yao35665b12024-08-21 00:30:54 +00001010 AUGMENT_LOG(V);
Jaideep Sharma145313e2024-08-14 14:51:24 +05301011 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
1012
Mikhail Naganovac9d4e72023-10-23 12:00:09 -07001013 if (soundDoseBinder == nullptr) {
1014 return BAD_VALUE;
1015 }
Vlad Popa03bd5bc2023-01-17 16:16:51 +01001016 if (mSoundDose == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +05301017 AUGMENT_LOG(E, "failed to retrieve the sound dose interface");
Mikhail Naganovac9d4e72023-10-23 12:00:09 -07001018 return BAD_VALUE;
Vlad Popa03bd5bc2023-01-17 16:16:51 +01001019 }
Vlad Popae1f33902023-10-30 19:48:25 -07001020
1021 if (mSoundDose == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +05301022 AUGMENT_LOG(E, "failed to return the sound dose interface not implemented");
Vlad Popae1f33902023-10-30 19:48:25 -07001023 return NO_INIT;
1024 }
1025
Vlad Popa03bd5bc2023-01-17 16:16:51 +01001026 *soundDoseBinder = mSoundDose->asBinder();
Jaideep Sharma145313e2024-08-14 14:51:24 +05301027 AUGMENT_LOG(I, "using audio AIDL HAL sound dose interface");
Vlad Popa03bd5bc2023-01-17 16:16:51 +01001028 return OK;
1029}
jiabin872de702023-04-27 22:04:31 +00001030
1031status_t DeviceHalAidl::prepareToDisconnectExternalDevice(const struct audio_port_v7* port) {
Shunkai Yao35665b12024-08-21 00:30:54 +00001032 AUGMENT_LOG(V);
jiabin62750c22023-12-21 22:06:07 +00001033 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +05301034 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
jiabin62750c22023-12-21 22:06:07 +00001035 if (port == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +05301036 AUGMENT_LOG(E, "port not initialized");
jiabin62750c22023-12-21 22:06:07 +00001037 return BAD_VALUE;
1038 }
Jaideep Sharma145313e2024-08-14 14:51:24 +05301039 const bool isInput =
1040 VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(port->role, port->type)) ==
1041 ::aidl::android::AudioPortDirection::INPUT;
jiabin62750c22023-12-21 22:06:07 +00001042 AudioPort aidlPort = VALUE_OR_RETURN_STATUS(
1043 ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
1044 if (aidlPort.ext.getTag() != AudioPortExt::device) {
Jaideep Sharma145313e2024-08-14 14:51:24 +05301045 AUGMENT_LOG(E, "provided port is not a device port: %s", aidlPort.toString().c_str());
jiabin62750c22023-12-21 22:06:07 +00001046 return BAD_VALUE;
1047 }
Jaideep Sharma145313e2024-08-14 14:51:24 +05301048
1049 AUGMENT_LOG(D, "device %s", aidlPort.toString().c_str());
1050
jiabin62750c22023-12-21 22:06:07 +00001051 status_t status = NO_ERROR;
1052 {
1053 std::lock_guard l(mLock);
1054 status = mMapper.prepareToDisconnectExternalDevice(aidlPort);
1055 }
1056 if (status == UNKNOWN_TRANSACTION) {
1057 // If there is not AIDL API defined for `prepareToDisconnectExternalDevice`.
1058 // Call `setConnectedState` instead.
1059 RETURN_STATUS_IF_ERROR(setConnectedState(port, false /*connected*/));
1060 std::lock_guard l(mLock);
1061 mDeviceDisconnectionNotified.insert(port->id);
1062 // Return that there was no error as otherwise the disconnection procedure will not be
1063 // considered complete for upper layers, and 'setConnectedState' will not be called again
1064 return OK;
1065 } else {
1066 return status;
1067 }
jiabin872de702023-04-27 22:04:31 +00001068}
1069
Mikhail Naganove93a0862023-03-15 17:06:59 -07001070status_t DeviceHalAidl::setConnectedState(const struct audio_port_v7 *port, bool connected) {
Shunkai Yao35665b12024-08-21 00:30:54 +00001071 AUGMENT_LOG(V);
Mikhail Naganove93a0862023-03-15 17:06:59 -07001072 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +05301073 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganove93a0862023-03-15 17:06:59 -07001074 if (port == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +05301075 AUGMENT_LOG(E, "port not initialized");
Mikhail Naganove93a0862023-03-15 17:06:59 -07001076 return BAD_VALUE;
1077 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -07001078 if (!connected) {
1079 std::lock_guard l(mLock);
1080 if (mDeviceDisconnectionNotified.erase(port->id) > 0) {
1081 // For device disconnection, APM will first call `prepareToDisconnectExternalDevice`
jiabin62750c22023-12-21 22:06:07 +00001082 // and then call `setConnectedState`. If `prepareToDisconnectExternalDevice` doesn't
1083 // exit, `setConnectedState` will be called when calling
1084 // `prepareToDisconnectExternalDevice`. Do not call to the HAL if previous call is
1085 // successful. Also remove the cache here to avoid a large cache after a long run.
Mikhail Naganovac9d4e72023-10-23 12:00:09 -07001086 return OK;
1087 }
jiabin872de702023-04-27 22:04:31 +00001088 }
Mikhail Naganove93a0862023-03-15 17:06:59 -07001089 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(port->role, port->type)) ==
1090 ::aidl::android::AudioPortDirection::INPUT;
1091 AudioPort aidlPort = VALUE_OR_RETURN_STATUS(
1092 ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
1093 if (aidlPort.ext.getTag() != AudioPortExt::device) {
Jaideep Sharma145313e2024-08-14 14:51:24 +05301094 AUGMENT_LOG(E, "provided port is not a device port: %s", aidlPort.toString().c_str());
Mikhail Naganove93a0862023-03-15 17:06:59 -07001095 return BAD_VALUE;
1096 }
Jaideep Sharma145313e2024-08-14 14:51:24 +05301097 AUGMENT_LOG(D, "connected %d port: %s", connected, aidlPort.toString().c_str());
Mikhail Naganovac9d4e72023-10-23 12:00:09 -07001098 std::lock_guard l(mLock);
1099 return mMapper.setDevicePortConnectedState(aidlPort, connected);
Mikhail Naganove93a0862023-03-15 17:06:59 -07001100}
1101
1102status_t DeviceHalAidl::setSimulateDeviceConnections(bool enabled) {
Shunkai Yao35665b12024-08-21 00:30:54 +00001103 AUGMENT_LOG(V);
Mikhail Naganove93a0862023-03-15 17:06:59 -07001104 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +05301105 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -07001106 {
1107 std::lock_guard l(mLock);
Mikhail Naganova317a802024-03-15 18:03:10 +00001108 mMapper.resetUnusedPatchesAndPortConfigs();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -07001109 }
Mikhail Naganove93a0862023-03-15 17:06:59 -07001110 ModuleDebug debug{ .simulateDeviceConnections = enabled };
1111 status_t status = statusTFromBinderStatus(mModule->setModuleDebug(debug));
1112 // This is important to log as it affects HAL behavior.
1113 if (status == OK) {
Jaideep Sharma145313e2024-08-14 14:51:24 +05301114 AUGMENT_LOG(I, "set enabled: %d", enabled);
Mikhail Naganove93a0862023-03-15 17:06:59 -07001115 } else {
Jaideep Sharma145313e2024-08-14 14:51:24 +05301116 AUGMENT_LOG(W, "set enabled to %d failed: %d", enabled, status);
Mikhail Naganove93a0862023-03-15 17:06:59 -07001117 }
1118 return status;
1119}
1120
Mikhail Naganove7a26ad2023-05-25 17:36:48 -07001121status_t DeviceHalAidl::filterAndRetrieveBtA2dpParameters(
1122 AudioParameter &keys, AudioParameter *result) {
Mikhail Naganove7a26ad2023-05-25 17:36:48 -07001123 if (String8 key = String8(AudioParameter::keyReconfigA2dpSupported); keys.containsKey(key)) {
1124 keys.remove(key);
David Lia7761ed2023-11-03 17:22:07 +00001125 if (mBluetoothA2dp != nullptr) {
1126 bool supports;
1127 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
1128 mBluetoothA2dp->supportsOffloadReconfiguration(&supports)));
1129 result->addInt(key, supports ? 1 : 0);
1130 } else {
Jaideep Sharma145313e2024-08-14 14:51:24 +05301131 AUGMENT_LOG(I, "no IBluetoothA2dp");
David Lia7761ed2023-11-03 17:22:07 +00001132 result->addInt(key, 0);
1133 }
Mikhail Naganove7a26ad2023-05-25 17:36:48 -07001134 }
1135 return OK;
1136}
1137
Eric Laurent7e3c0832023-11-30 15:04:50 +01001138status_t DeviceHalAidl::filterAndRetrieveBtLeParameters(
1139 AudioParameter &keys, AudioParameter *result) {
1140 if (String8 key = String8(AudioParameter::keyReconfigLeSupported); keys.containsKey(key)) {
1141 keys.remove(key);
1142 if (mBluetoothLe != nullptr) {
1143 bool supports;
1144 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
1145 mBluetoothLe->supportsOffloadReconfiguration(&supports)));
1146 result->addInt(key, supports ? 1 : 0);
1147 } else {
Jaideep Sharma145313e2024-08-14 14:51:24 +05301148 AUGMENT_LOG(I, "no mBluetoothLe");
Eric Laurent7e3c0832023-11-30 15:04:50 +01001149 result->addInt(key, 0);
1150 }
1151 }
1152 return OK;
1153}
1154
Mikhail Naganovccc82112023-04-27 18:14:15 -07001155status_t DeviceHalAidl::filterAndUpdateBtA2dpParameters(AudioParameter &parameters) {
Mikhail Naganovccc82112023-04-27 18:14:15 -07001156 std::optional<bool> a2dpEnabled;
Mikhail Naganove7a26ad2023-05-25 17:36:48 -07001157 std::optional<std::vector<VendorParameter>> reconfigureOffload;
Mikhail Naganovccc82112023-04-27 18:14:15 -07001158 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301159 parameters, String8(AudioParameter::keyBtA2dpSuspended),
1160 [&a2dpEnabled, this](const String8& trueOrFalse) {
1161 if (trueOrFalse == AudioParameter::valueTrue) {
1162 a2dpEnabled = false; // 'suspended' == true
1163 return OK;
1164 } else if (trueOrFalse == AudioParameter::valueFalse) {
1165 a2dpEnabled = true; // 'suspended' == false
1166 return OK;
1167 }
1168 AUGMENT_LOG(E, "setParameters: parameter key \"%s\" has invalid value \"%s\"",
1169 AudioParameter::keyBtA2dpSuspended, trueOrFalse.c_str());
1170 return BAD_VALUE;
1171 }));
Mikhail Naganove7a26ad2023-05-25 17:36:48 -07001172 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301173 parameters, String8(AudioParameter::keyReconfigA2dp),
1174 [&](const String8& value) -> status_t {
1175 std::vector<VendorParameter> result;
1176 RETURN_STATUS_IF_ERROR(
1177 statusTFromBinderStatus(mVendorExt->parseBluetoothA2dpReconfigureOffload(
1178 std::string(value.c_str()), &result)));
1179 reconfigureOffload = std::move(result);
1180 return OK;
1181 }));
Mikhail Naganovccc82112023-04-27 18:14:15 -07001182 if (mBluetoothA2dp != nullptr && a2dpEnabled.has_value()) {
1183 return statusTFromBinderStatus(mBluetoothA2dp->setEnabled(a2dpEnabled.value()));
1184 }
Mikhail Naganove7a26ad2023-05-25 17:36:48 -07001185 if (mBluetoothA2dp != nullptr && reconfigureOffload.has_value()) {
1186 return statusTFromBinderStatus(mBluetoothA2dp->reconfigureOffload(
1187 reconfigureOffload.value()));
1188 }
Mikhail Naganovccc82112023-04-27 18:14:15 -07001189 return OK;
1190}
1191
1192status_t DeviceHalAidl::filterAndUpdateBtHfpParameters(AudioParameter &parameters) {
Mikhail Naganovccc82112023-04-27 18:14:15 -07001193 IBluetooth::HfpConfig hfpConfig;
1194 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301195 parameters, String8(AudioParameter::keyBtHfpEnable),
1196 [&hfpConfig, this](const String8& trueOrFalse) {
1197 if (trueOrFalse == AudioParameter::valueTrue) {
1198 hfpConfig.isEnabled = Boolean{.value = true};
1199 return OK;
1200 } else if (trueOrFalse == AudioParameter::valueFalse) {
1201 hfpConfig.isEnabled = Boolean{.value = false};
1202 return OK;
1203 }
1204 AUGMENT_LOG(E, "setParameters: parameter key \"%s\" has invalid value \"%s\"",
1205 AudioParameter::keyBtHfpEnable, trueOrFalse.c_str());
1206 return BAD_VALUE;
1207 }));
Mikhail Naganovccc82112023-04-27 18:14:15 -07001208 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301209 parameters, String8(AudioParameter::keyBtHfpSamplingRate),
1210 [&hfpConfig](int sampleRate) {
1211 return sampleRate > 0 ? hfpConfig.sampleRate = Int{.value = sampleRate},
1212 OK : BAD_VALUE;
1213 }));
Mikhail Naganovccc82112023-04-27 18:14:15 -07001214 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301215 parameters, String8(AudioParameter::keyBtHfpVolume), [&hfpConfig](int volume0to15) {
1216 if (volume0to15 >= 0 && volume0to15 <= 15) {
1217 hfpConfig.volume = Float{.value = volume0to15 / 15.0f};
1218 return OK;
1219 }
1220 return BAD_VALUE;
1221 }));
Mikhail Naganovccc82112023-04-27 18:14:15 -07001222 if (mBluetooth != nullptr && hfpConfig != IBluetooth::HfpConfig{}) {
1223 IBluetooth::HfpConfig newHfpConfig;
1224 return statusTFromBinderStatus(mBluetooth->setHfpConfig(hfpConfig, &newHfpConfig));
1225 }
1226 return OK;
1227}
1228
1229status_t DeviceHalAidl::filterAndUpdateBtLeParameters(AudioParameter &parameters) {
Mikhail Naganovccc82112023-04-27 18:14:15 -07001230 std::optional<bool> leEnabled;
Eric Laurent7e3c0832023-11-30 15:04:50 +01001231 std::optional<std::vector<VendorParameter>> reconfigureOffload;
Mikhail Naganovccc82112023-04-27 18:14:15 -07001232 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301233 parameters, String8(AudioParameter::keyBtLeSuspended),
1234 [&leEnabled, this](const String8& trueOrFalse) {
1235 if (trueOrFalse == AudioParameter::valueTrue) {
1236 leEnabled = false; // 'suspended' == true
1237 return OK;
1238 } else if (trueOrFalse == AudioParameter::valueFalse) {
1239 leEnabled = true; // 'suspended' == false
1240 return OK;
1241 }
1242 AUGMENT_LOG(E, "setParameters: parameter key \"%s\" has invalid value \"%s\"",
1243 AudioParameter::keyBtLeSuspended, trueOrFalse.c_str());
1244 return BAD_VALUE;
1245 }));
Eric Laurent7e3c0832023-11-30 15:04:50 +01001246 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301247 parameters, String8(AudioParameter::keyReconfigLe),
1248 [&](const String8& value) -> status_t {
1249 if (mVendorExt != nullptr) {
1250 std::vector<VendorParameter> result;
1251 RETURN_STATUS_IF_ERROR(
1252 statusTFromBinderStatus(mVendorExt->parseBluetoothLeReconfigureOffload(
1253 std::string(value.c_str()), &result)));
1254 reconfigureOffload = std::move(result);
1255 } else {
1256 reconfigureOffload = std::vector<VendorParameter>();
1257 }
1258 return OK;
1259 }));
Mikhail Naganovccc82112023-04-27 18:14:15 -07001260 if (mBluetoothLe != nullptr && leEnabled.has_value()) {
1261 return statusTFromBinderStatus(mBluetoothLe->setEnabled(leEnabled.value()));
1262 }
Eric Laurent7e3c0832023-11-30 15:04:50 +01001263 if (mBluetoothLe != nullptr && reconfigureOffload.has_value()) {
Jaideep Sharma145313e2024-08-14 14:51:24 +05301264 return statusTFromBinderStatus(
1265 mBluetoothLe->reconfigureOffload(reconfigureOffload.value()));
Eric Laurent7e3c0832023-11-30 15:04:50 +01001266 }
Mikhail Naganovccc82112023-04-27 18:14:15 -07001267 return OK;
1268}
1269
1270status_t DeviceHalAidl::filterAndUpdateBtScoParameters(AudioParameter &parameters) {
Mikhail Naganovccc82112023-04-27 18:14:15 -07001271 IBluetooth::ScoConfig scoConfig;
1272 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301273 parameters, String8(AudioParameter::keyBtSco),
1274 [&scoConfig, this](const String8& onOrOff) {
1275 if (onOrOff == AudioParameter::valueOn) {
1276 scoConfig.isEnabled = Boolean{.value = true};
1277 return OK;
1278 } else if (onOrOff == AudioParameter::valueOff) {
1279 scoConfig.isEnabled = Boolean{.value = false};
1280 return OK;
1281 }
1282 AUGMENT_LOG(E, "setParameters: parameter key \"%s\" has invalid value \"%s\"",
1283 AudioParameter::keyBtSco, onOrOff.c_str());
1284 return BAD_VALUE;
1285 }));
Mikhail Naganovccc82112023-04-27 18:14:15 -07001286 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301287 parameters, String8(AudioParameter::keyBtScoHeadsetName),
1288 [&scoConfig](const String8& name) {
1289 scoConfig.debugName = name;
1290 return OK;
1291 }));
Mikhail Naganovccc82112023-04-27 18:14:15 -07001292 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301293 parameters, String8(AudioParameter::keyBtNrec),
1294 [&scoConfig, this](const String8& onOrOff) {
1295 if (onOrOff == AudioParameter::valueOn) {
1296 scoConfig.isNrecEnabled = Boolean{.value = true};
1297 return OK;
1298 } else if (onOrOff == AudioParameter::valueOff) {
1299 scoConfig.isNrecEnabled = Boolean{.value = false};
1300 return OK;
1301 }
1302 AUGMENT_LOG(E, "setParameters: parameter key \"%s\" has invalid value \"%s\"",
1303 AudioParameter::keyBtNrec, onOrOff.c_str());
1304 return BAD_VALUE;
1305 }));
Mikhail Naganovccc82112023-04-27 18:14:15 -07001306 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301307 parameters, String8(AudioParameter::keyBtScoWb),
1308 [&scoConfig, this](const String8& onOrOff) {
1309 if (onOrOff == AudioParameter::valueOn) {
1310 scoConfig.mode = IBluetooth::ScoConfig::Mode::SCO_WB;
1311 return OK;
1312 } else if (onOrOff == AudioParameter::valueOff) {
1313 scoConfig.mode = IBluetooth::ScoConfig::Mode::SCO;
1314 return OK;
1315 }
1316 AUGMENT_LOG(E, "setParameters: parameter key \"%s\" has invalid value \"%s\"",
1317 AudioParameter::keyBtScoWb, onOrOff.c_str());
1318 return BAD_VALUE;
1319 }));
Mikhail Naganovccc82112023-04-27 18:14:15 -07001320 if (mBluetooth != nullptr && scoConfig != IBluetooth::ScoConfig{}) {
1321 IBluetooth::ScoConfig newScoConfig;
1322 return statusTFromBinderStatus(mBluetooth->setScoConfig(scoConfig, &newScoConfig));
1323 }
1324 return OK;
1325}
1326
Mikhail Naganove92c34b2023-05-31 14:24:48 -07001327status_t DeviceHalAidl::filterAndUpdateScreenParameters(AudioParameter &parameters) {
Mikhail Naganove92c34b2023-05-31 14:24:48 -07001328 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301329 parameters, String8(AudioParameter::keyScreenState),
1330 [&, this](const String8& onOrOff) -> status_t {
1331 std::optional<bool> isTurnedOn;
1332 if (onOrOff == AudioParameter::valueOn) {
1333 isTurnedOn = true;
1334 } else if (onOrOff == AudioParameter::valueOff) {
1335 isTurnedOn = false;
1336 }
1337 if (!isTurnedOn.has_value()) {
1338 AUGMENT_LOG(E, "setParameters: parameter key \"%s\" has invalid value \"%s\"",
1339 AudioParameter::keyScreenState, onOrOff.c_str());
1340 return BAD_VALUE;
1341 }
1342 return statusTFromBinderStatus(mModule->updateScreenState(isTurnedOn.value()));
1343 }));
Mikhail Naganove92c34b2023-05-31 14:24:48 -07001344 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301345 parameters, String8(AudioParameter::keyScreenRotation),
1346 [&, this](int rotationDegrees) -> status_t {
Mikhail Naganove92c34b2023-05-31 14:24:48 -07001347 IModule::ScreenRotation rotation;
1348 switch (rotationDegrees) {
Jaideep Sharma145313e2024-08-14 14:51:24 +05301349 case 0:
1350 rotation = IModule::ScreenRotation::DEG_0;
1351 break;
1352 case 90:
1353 rotation = IModule::ScreenRotation::DEG_90;
1354 break;
1355 case 180:
1356 rotation = IModule::ScreenRotation::DEG_180;
1357 break;
1358 case 270:
1359 rotation = IModule::ScreenRotation::DEG_270;
1360 break;
Mikhail Naganove92c34b2023-05-31 14:24:48 -07001361 default:
Jaideep Sharma145313e2024-08-14 14:51:24 +05301362 AUGMENT_LOG(E, "setParameters: parameter key \"%s\" has invalid value %d",
1363 AudioParameter::keyScreenRotation, rotationDegrees);
Mikhail Naganove92c34b2023-05-31 14:24:48 -07001364 return BAD_VALUE;
1365 }
1366 return statusTFromBinderStatus(mModule->updateScreenRotation(rotation));
1367 }));
1368 return OK;
1369}
1370
Mikhail Naganovb9a81312023-07-18 13:55:34 -07001371status_t DeviceHalAidl::filterAndUpdateTelephonyParameters(AudioParameter &parameters) {
Mikhail Naganovb9a81312023-07-18 13:55:34 -07001372 using TtyMode = ITelephony::TelecomConfig::TtyMode;
1373 ITelephony::TelecomConfig telConfig;
1374 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301375 parameters, String8(AudioParameter::keyTtyMode),
1376 [&telConfig, this](const String8& mode) {
1377 if (mode == AudioParameter::valueTtyModeOff) {
1378 telConfig.ttyMode = TtyMode::OFF;
1379 return OK;
1380 } else if (mode == AudioParameter::valueTtyModeFull) {
1381 telConfig.ttyMode = TtyMode::FULL;
1382 return OK;
1383 } else if (mode == AudioParameter::valueTtyModeHco) {
1384 telConfig.ttyMode = TtyMode::HCO;
1385 return OK;
1386 } else if (mode == AudioParameter::valueTtyModeVco) {
1387 telConfig.ttyMode = TtyMode::VCO;
1388 return OK;
1389 }
1390 AUGMENT_LOG(E, "setParameters: parameter key \"%s\" has invalid value \"%s\"",
1391 AudioParameter::keyTtyMode, mode.c_str());
1392 return BAD_VALUE;
1393 }));
Mikhail Naganovb9a81312023-07-18 13:55:34 -07001394 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301395 parameters, String8(AudioParameter::keyHacSetting),
1396 [&telConfig, this](const String8& onOrOff) {
1397 if (onOrOff == AudioParameter::valueHacOn) {
1398 telConfig.isHacEnabled = Boolean{.value = true};
1399 return OK;
1400 } else if (onOrOff == AudioParameter::valueHacOff) {
1401 telConfig.isHacEnabled = Boolean{.value = false};
1402 return OK;
1403 }
1404 AUGMENT_LOG(E, "setParameters: parameter key \"%s\" has invalid value \"%s\"",
1405 AudioParameter::keyHacSetting, onOrOff.c_str());
1406 return BAD_VALUE;
1407 }));
Mikhail Naganovb9a81312023-07-18 13:55:34 -07001408 if (mTelephony != nullptr && telConfig != ITelephony::TelecomConfig{}) {
1409 ITelephony::TelecomConfig newTelConfig;
Jaideep Sharma145313e2024-08-14 14:51:24 +05301410 return statusTFromBinderStatus(mTelephony->setTelecomConfig(telConfig, &newTelConfig));
Mikhail Naganovb9a81312023-07-18 13:55:34 -07001411 }
1412 return OK;
1413}
1414
Mikhail Naganovdfd594e2023-02-08 16:59:41 -08001415void DeviceHalAidl::clearCallbacks(void* cookie) {
Mikhail Naganov22578412024-08-16 16:50:34 -07001416 std::lock_guard l(mCallbacksLock);
Mikhail Naganovdfd594e2023-02-08 16:59:41 -08001417 mCallbacks.erase(cookie);
1418}
1419
1420sp<StreamOutHalInterfaceCallback> DeviceHalAidl::getStreamOutCallback(void* cookie) {
1421 return getCallbackImpl(cookie, &Callbacks::out);
1422}
1423
1424void DeviceHalAidl::setStreamOutCallback(
1425 void* cookie, const sp<StreamOutHalInterfaceCallback>& cb) {
1426 setCallbackImpl(cookie, &Callbacks::out, cb);
1427}
1428
1429sp<StreamOutHalInterfaceEventCallback> DeviceHalAidl::getStreamOutEventCallback(
1430 void* cookie) {
1431 return getCallbackImpl(cookie, &Callbacks::event);
1432}
1433
1434void DeviceHalAidl::setStreamOutEventCallback(
1435 void* cookie, const sp<StreamOutHalInterfaceEventCallback>& cb) {
1436 setCallbackImpl(cookie, &Callbacks::event, cb);
1437}
1438
1439sp<StreamOutHalInterfaceLatencyModeCallback> DeviceHalAidl::getStreamOutLatencyModeCallback(
1440 void* cookie) {
1441 return getCallbackImpl(cookie, &Callbacks::latency);
1442}
1443
1444void DeviceHalAidl::setStreamOutLatencyModeCallback(
1445 void* cookie, const sp<StreamOutHalInterfaceLatencyModeCallback>& cb) {
1446 setCallbackImpl(cookie, &Callbacks::latency, cb);
1447}
1448
Mikhail Naganov22578412024-08-16 16:50:34 -07001449template <class C>
Mikhail Naganovdfd594e2023-02-08 16:59:41 -08001450sp<C> DeviceHalAidl::getCallbackImpl(void* cookie, wp<C> DeviceHalAidl::Callbacks::* field) {
Mikhail Naganov22578412024-08-16 16:50:34 -07001451 wp<C> result;
1452 {
1453 std::lock_guard l(mCallbacksLock);
1454 if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
1455 result = (it->second).*field;
1456 }
Mikhail Naganovdfd594e2023-02-08 16:59:41 -08001457 }
Mikhail Naganov22578412024-08-16 16:50:34 -07001458 return result.promote();
Mikhail Naganovdfd594e2023-02-08 16:59:41 -08001459}
1460template<class C>
1461void DeviceHalAidl::setCallbackImpl(
1462 void* cookie, wp<C> DeviceHalAidl::Callbacks::* field, const sp<C>& cb) {
Mikhail Naganov22578412024-08-16 16:50:34 -07001463 std::lock_guard l(mCallbacksLock);
Mikhail Naganovdfd594e2023-02-08 16:59:41 -08001464 if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
1465 (it->second).*field = cb;
1466 }
1467}
1468
Mikhail Naganov31d46652023-01-10 18:29:25 +00001469} // namespace android