blob: f301a778af2d04eed84a0a9169232d18f017e065 [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) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530143 LOG_ENTRY();
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() {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530167 LOG_ENTRY();
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) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530199 LOG_ENTRY();
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) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530230 LOG_ENTRY();
231
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) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530250 LOG_ENTRY();
251
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) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530309 LOG_ENTRY();
310
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);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700465 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530466 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700467 if (outStream == nullptr || config == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530468 AUGMENT_LOG(E, "invalid outStream or config");
Mikhail Naganov31d46652023-01-10 18:29:25 +0000469 return BAD_VALUE;
470 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700471 constexpr bool isInput = false;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800472 int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
473 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(handle));
474 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700475 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, isInput));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800476 AudioDevice aidlDevice = VALUE_OR_RETURN_STATUS(
477 ::aidl::android::legacy2aidl_audio_device_AudioDevice(devices, address));
478 int32_t aidlOutputFlags = VALUE_OR_RETURN_STATUS(
479 ::aidl::android::legacy2aidl_audio_output_flags_t_int32_t_mask(flags));
Haofan Wangbf44e092024-07-07 15:29:38 -0700480 SourceMetadata aidlMetadata = VALUE_OR_RETURN_STATUS(
481 ::aidl::android::legacy2aidl_SourceMetadata(sourceMetadata));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800482 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::output>(aidlOutputFlags);
483 AudioPortConfig mixPortConfig;
Mikhail Naganove93a0862023-03-15 17:06:59 -0700484 AudioPatch aidlPatch;
Haofan Wangbf44e092024-07-07 15:29:38 -0700485
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700486 Hal2AidlMapper::Cleanups cleanups(mMapperAccessor);
487 {
488 std::lock_guard l(mLock);
489 RETURN_STATUS_IF_ERROR(mMapper.prepareToOpenStream(aidlHandle, aidlDevice, aidlFlags,
490 AudioSource::SYS_RESERVED_INVALID /*only needed for input*/,
491 &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
492 }
493 *config = VALUE_OR_RETURN_STATUS(
494 ::aidl::android::aidl2legacy_AudioConfig_audio_config_t(aidlConfig, isInput));
Mikhail Naganovca92a5c2023-12-07 14:00:48 -0800495 if (mixPortConfig.id == 0) return BAD_VALUE; // HAL suggests a different config.
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800496 ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamArguments args;
497 args.portConfigId = mixPortConfig.id;
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800498 const bool isOffload = isBitPositionFlagSet(
499 aidlOutputFlags, AudioOutputFlags::COMPRESS_OFFLOAD);
Kuowei Li3b9a69d2024-06-07 17:54:32 +0800500 const bool isHwAvSync = isBitPositionFlagSet(
501 aidlOutputFlags, AudioOutputFlags::HW_AV_SYNC);
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800502 std::shared_ptr<OutputStreamCallbackAidl> streamCb;
503 if (isOffload) {
504 streamCb = ndk::SharedRefBase::make<OutputStreamCallbackAidl>(this);
505 }
506 auto eventCb = ndk::SharedRefBase::make<OutputStreamEventCallbackAidl>(this);
Kuowei Li3b9a69d2024-06-07 17:54:32 +0800507 if (isOffload || isHwAvSync) {
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800508 args.offloadInfo = aidlConfig.offloadInfo;
Kuowei Li3b9a69d2024-06-07 17:54:32 +0800509 }
510 if (isOffload) {
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800511 args.callback = streamCb;
512 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800513 args.bufferSizeFrames = aidlConfig.frameCount;
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800514 args.eventCallback = eventCb;
Haofan Wangbf44e092024-07-07 15:29:38 -0700515 args.sourceMetadata = aidlMetadata;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800516 ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamReturn ret;
517 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openOutputStream(args, &ret)));
Jaideep Sharma145313e2024-08-14 14:51:24 +0530518 StreamContextAidl context(ret.desc, isOffload, aidlHandle);
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800519 if (!context.isValid()) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530520 AUGMENT_LOG(E, "Failed to created a valid stream context from the descriptor: %s",
521 ret.desc.toString().c_str());
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800522 return NO_INIT;
523 }
Mikhail Naganov23224a12024-03-28 02:15:21 +0000524 auto stream = sp<StreamOutHalAidl>::make(*config, std::move(context), aidlPatch.latenciesMs[0],
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700525 std::move(ret.stream), mVendorExt, this /*callbackBroker*/);
Mikhail Naganov23224a12024-03-28 02:15:21 +0000526 *outStream = stream;
527 /* StreamOutHalInterface* */ void* cbCookie = (*outStream).get();
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800528 {
Mikhail Naganov22578412024-08-16 16:50:34 -0700529 std::lock_guard l(mCallbacksLock);
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800530 mCallbacks.emplace(cbCookie, Callbacks{});
Mikhail Naganov22578412024-08-16 16:50:34 -0700531 }
532 {
533 std::lock_guard l(mLock);
Mikhail Naganov78f7f9a2023-11-16 15:49:23 -0800534 mMapper.addStream(*outStream, mixPortConfig.id, aidlPatch.id);
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800535 }
Mikhail Naganov23224a12024-03-28 02:15:21 +0000536 if (streamCb) {
537 streamCb->setCookie(cbCookie);
538 // Although StreamOutHalAidl implements StreamOutHalInterfaceCallback,
539 // we always go via the CallbackBroker for consistency.
540 setStreamOutCallback(cbCookie, stream);
541 }
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800542 eventCb->setCookie(cbCookie);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800543 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000544 return OK;
545}
546
Mikhail Naganov31d46652023-01-10 18:29:25 +0000547status_t DeviceHalAidl::openInputStream(
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800548 audio_io_handle_t handle, audio_devices_t devices,
549 struct audio_config* config, audio_input_flags_t flags,
550 const char* address, audio_source_t source,
551 audio_devices_t outputDevice, const char* outputDeviceAddress,
Mikhail Naganov31d46652023-01-10 18:29:25 +0000552 sp<StreamInHalInterface>* inStream) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530553 AUGMENT_LOG(D, "handle: %d devices %0x flags %0x", handle, devices, flags);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700554 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530555 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700556 if (inStream == nullptr || config == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530557 AUGMENT_LOG(E, "invalid inStream or config");
Mikhail Naganov31d46652023-01-10 18:29:25 +0000558 return BAD_VALUE;
559 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700560 constexpr bool isInput = true;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800561 int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
562 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(handle));
563 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700564 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, isInput));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800565 AudioDevice aidlDevice = VALUE_OR_RETURN_STATUS(
566 ::aidl::android::legacy2aidl_audio_device_AudioDevice(devices, address));
567 int32_t aidlInputFlags = VALUE_OR_RETURN_STATUS(
568 ::aidl::android::legacy2aidl_audio_input_flags_t_int32_t_mask(flags));
569 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::input>(aidlInputFlags);
570 AudioSource aidlSource = VALUE_OR_RETURN_STATUS(
571 ::aidl::android::legacy2aidl_audio_source_t_AudioSource(source));
572 AudioPortConfig mixPortConfig;
Mikhail Naganove93a0862023-03-15 17:06:59 -0700573 AudioPatch aidlPatch;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700574 Hal2AidlMapper::Cleanups cleanups(mMapperAccessor);
575 {
576 std::lock_guard l(mLock);
577 RETURN_STATUS_IF_ERROR(mMapper.prepareToOpenStream(
578 aidlHandle, aidlDevice, aidlFlags, aidlSource,
579 &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
580 }
581 *config = VALUE_OR_RETURN_STATUS(
582 ::aidl::android::aidl2legacy_AudioConfig_audio_config_t(aidlConfig, isInput));
Mikhail Naganovca92a5c2023-12-07 14:00:48 -0800583 if (mixPortConfig.id == 0) return BAD_VALUE; // HAL suggests a different config.
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800584 ::aidl::android::hardware::audio::core::IModule::OpenInputStreamArguments args;
585 args.portConfigId = mixPortConfig.id;
586 RecordTrackMetadata aidlTrackMetadata{
587 .source = aidlSource, .gain = 1, .channelMask = aidlConfig.base.channelMask };
588 if (outputDevice != AUDIO_DEVICE_NONE) {
589 aidlTrackMetadata.destinationDevice = VALUE_OR_RETURN_STATUS(
590 ::aidl::android::legacy2aidl_audio_device_AudioDevice(
591 outputDevice, outputDeviceAddress));
592 }
593 args.sinkMetadata.tracks.push_back(std::move(aidlTrackMetadata));
594 args.bufferSizeFrames = aidlConfig.frameCount;
595 ::aidl::android::hardware::audio::core::IModule::OpenInputStreamReturn ret;
596 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openInputStream(args, &ret)));
Jaideep Sharma145313e2024-08-14 14:51:24 +0530597 StreamContextAidl context(ret.desc, false /*isAsynchronous*/, aidlHandle);
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800598 if (!context.isValid()) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530599 AUGMENT_LOG(E, "Failed to created a valid stream context from the descriptor: %s",
600 ret.desc.toString().c_str());
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800601 return NO_INIT;
602 }
Mikhail Naganove93a0862023-03-15 17:06:59 -0700603 *inStream = sp<StreamInHalAidl>::make(*config, std::move(context), aidlPatch.latenciesMs[0],
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700604 std::move(ret.stream), mVendorExt, this /*micInfoProvider*/);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700605 {
606 std::lock_guard l(mLock);
Mikhail Naganov78f7f9a2023-11-16 15:49:23 -0800607 mMapper.addStream(*inStream, mixPortConfig.id, aidlPatch.id);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700608 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800609 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000610 return OK;
611}
612
613status_t DeviceHalAidl::supportsAudioPatches(bool* supportsPatches) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530614 LOG_ENTRY_V();
615 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700616 if (supportsPatches == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530617 AUGMENT_LOG(E, "uninitialized supportsPatches");
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700618 return BAD_VALUE;
619 }
Shunkai Yao51202502022-12-12 06:11:46 +0000620 *supportsPatches = true;
621 return OK;
622}
623
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800624status_t DeviceHalAidl::createAudioPatch(unsigned int num_sources,
625 const struct audio_port_config* sources,
626 unsigned int num_sinks,
627 const struct audio_port_config* sinks,
628 audio_patch_handle_t* patch) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530629 AUGMENT_LOG(D, "sources: %d sinks %d", num_sources, num_sinks);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000630 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530631 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
632 if (num_sinks > AUDIO_PATCH_PORTS_MAX || num_sources > AUDIO_PATCH_PORTS_MAX) {
633 AUGMENT_LOG(E, "invalid sources %d or sinks %d ", num_sources, num_sinks);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800634 return BAD_VALUE;
635 }
Jaideep Sharma145313e2024-08-14 14:51:24 +0530636
637 if (sources == nullptr || sinks == nullptr || patch == nullptr) {
638 AUGMENT_LOG(E, "uninitialized sources %d or sinks %d or patches %d", (sources == nullptr),
639 (sinks == nullptr), (patch == nullptr));
640 return BAD_VALUE;
641 }
642
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800643 // When the patch handle (*patch) is AUDIO_PATCH_HANDLE_NONE, it means
644 // the framework wants to create a new patch. The handle has to be generated
645 // by the HAL. Since handles generated this way can only be unique within
646 // a HAL module, the framework generates a globally unique handle, and maps
647 // it on the <HAL module, patch handle> pair.
648 // When the patch handle is set, it meant the framework intends to update
649 // an existing patch.
650 //
651 // This behavior corresponds to HAL module behavior, with the only difference
652 // that the HAL module uses `int32_t` for patch IDs. The following assert ensures
653 // that both the framework and the HAL use the same value for "no ID":
654 static_assert(AUDIO_PATCH_HANDLE_NONE == 0);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800655
656 // Upon conversion, mix port configs contain audio configuration, while
657 // device port configs contain device address. This data is used to find
658 // or create HAL configs.
659 std::vector<AudioPortConfig> aidlSources, aidlSinks;
660 for (unsigned int i = 0; i < num_sources; ++i) {
661 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
662 sources[i].role, sources[i].type)) ==
663 ::aidl::android::AudioPortDirection::INPUT;
664 aidlSources.push_back(VALUE_OR_RETURN_STATUS(
665 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
666 sources[i], isInput, 0)));
667 }
668 for (unsigned int i = 0; i < num_sinks; ++i) {
669 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
670 sinks[i].role, sinks[i].type)) ==
671 ::aidl::android::AudioPortDirection::INPUT;
672 aidlSinks.push_back(VALUE_OR_RETURN_STATUS(
673 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
674 sinks[i], isInput, 0)));
675 }
Mikhail Naganova317a802024-03-15 18:03:10 +0000676 int32_t aidlPatchId = static_cast<int32_t>(*patch);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700677 Hal2AidlMapper::Cleanups cleanups(mMapperAccessor);
678 {
679 std::lock_guard l(mLock);
Mikhail Naganova317a802024-03-15 18:03:10 +0000680 // Check for patches that only exist for the framework, or have different HAL patch ID.
681 if (int32_t aidlHalPatchId = mMapper.findFwkPatch(aidlPatchId); aidlHalPatchId != 0) {
682 if (aidlHalPatchId == aidlPatchId) {
683 // This patch was previously released by the HAL. Thus we need to pass '0'
684 // to the HAL to obtain a new patch.
685 int32_t newAidlPatchId = 0;
686 RETURN_STATUS_IF_ERROR(mMapper.createOrUpdatePatch(
687 aidlSources, aidlSinks, &newAidlPatchId, &cleanups));
688 mMapper.updateFwkPatch(aidlPatchId, newAidlPatchId);
689 } else {
690 RETURN_STATUS_IF_ERROR(mMapper.createOrUpdatePatch(
691 aidlSources, aidlSinks, &aidlHalPatchId, &cleanups));
692 }
693 } else {
694 RETURN_STATUS_IF_ERROR(mMapper.createOrUpdatePatch(
695 aidlSources, aidlSinks, &aidlPatchId, &cleanups));
696 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800697 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700698 *patch = static_cast<audio_patch_handle_t>(aidlPatchId);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800699 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000700 return OK;
701}
702
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800703status_t DeviceHalAidl::releaseAudioPatch(audio_patch_handle_t patch) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530704 AUGMENT_LOG(D, "patch: %d", patch);
705
Mikhail Naganov31d46652023-01-10 18:29:25 +0000706 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530707 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800708 static_assert(AUDIO_PATCH_HANDLE_NONE == 0);
709 if (patch == AUDIO_PATCH_HANDLE_NONE) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800710 return BAD_VALUE;
711 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700712 std::lock_guard l(mLock);
Mikhail Naganova317a802024-03-15 18:03:10 +0000713 // Check for patches that only exist for the framework, or have different HAL patch ID.
714 int32_t aidlPatchId = static_cast<int32_t>(patch);
715 if (int32_t aidlHalPatchId = mMapper.findFwkPatch(aidlPatchId); aidlHalPatchId != 0) {
716 if (aidlHalPatchId == aidlPatchId) {
717 // This patch was previously released by the HAL, just need to finish its removal.
718 mMapper.eraseFwkPatch(aidlPatchId);
719 return OK;
720 } else {
721 // This patch has a HAL patch ID which is different
722 aidlPatchId = aidlHalPatchId;
723 }
724 }
725 RETURN_STATUS_IF_ERROR(mMapper.releaseAudioPatch(aidlPatchId));
Shunkai Yao51202502022-12-12 06:11:46 +0000726 return OK;
727}
728
Mikhail Naganove93a0862023-03-15 17:06:59 -0700729status_t DeviceHalAidl::getAudioPort(struct audio_port* port) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530730 LOG_ENTRY_V();
731 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganove93a0862023-03-15 17:06:59 -0700732 if (port == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530733 AUGMENT_LOG(E, "port not initialized");
Mikhail Naganove93a0862023-03-15 17:06:59 -0700734 return BAD_VALUE;
735 }
736 audio_port_v7 portV7;
737 audio_populate_audio_port_v7(port, &portV7);
738 RETURN_STATUS_IF_ERROR(getAudioPort(&portV7));
739 return audio_populate_audio_port(&portV7, port) ? OK : BAD_VALUE;
740}
741
742status_t DeviceHalAidl::getAudioPort(struct audio_port_v7 *port) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530743 LOG_ENTRY();
744
Mikhail Naganove93a0862023-03-15 17:06:59 -0700745 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530746 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganove93a0862023-03-15 17:06:59 -0700747 if (port == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530748 AUGMENT_LOG(E, "port not initialized");
Mikhail Naganove93a0862023-03-15 17:06:59 -0700749 return BAD_VALUE;
750 }
751 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(port->role, port->type)) ==
752 ::aidl::android::AudioPortDirection::INPUT;
753 auto aidlPort = VALUE_OR_RETURN_STATUS(
754 ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
755 if (aidlPort.ext.getTag() != AudioPortExt::device) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530756 AUGMENT_LOG(E, "provided port is not a device port %s", aidlPort.toString().c_str());
Mikhail Naganove93a0862023-03-15 17:06:59 -0700757 return BAD_VALUE;
758 }
759 const auto& matchDevice = aidlPort.ext.get<AudioPortExt::device>().device;
760 // It seems that we don't have to call HAL since all valid ports have been added either
761 // during initialization, or while handling connection of an external device.
Mikhail Naganove93a0862023-03-15 17:06:59 -0700762 const int32_t fwkId = aidlPort.id;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700763 {
764 std::lock_guard l(mLock);
765 RETURN_STATUS_IF_ERROR(mMapper.getAudioPortCached(matchDevice, &aidlPort));
766 }
Mikhail Naganove93a0862023-03-15 17:06:59 -0700767 aidlPort.id = fwkId;
768 *port = VALUE_OR_RETURN_STATUS(::aidl::android::aidl2legacy_AudioPort_audio_port_v7(
769 aidlPort, isInput));
770 return OK;
771}
772
jiabin12537fc2023-10-12 17:56:08 +0000773status_t DeviceHalAidl::getAudioMixPort(const struct audio_port_v7 *devicePort,
774 struct audio_port_v7 *mixPort) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530775 LOG_ENTRY();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700776 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530777 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
778
779 if (devicePort == nullptr || mixPort == nullptr || devicePort->type != AUDIO_PORT_TYPE_DEVICE ||
780 mixPort->type != AUDIO_PORT_TYPE_MIX) {
781 AUGMENT_LOG(E, "invalid device or mix port");
jiabin12537fc2023-10-12 17:56:08 +0000782 return BAD_VALUE;
783 }
784 const int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
785 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(mixPort->ext.mix.handle));
jiabin12537fc2023-10-12 17:56:08 +0000786 AudioPort port;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700787 {
788 std::lock_guard l(mLock);
789 RETURN_STATUS_IF_ERROR(mMapper.getAudioMixPort(aidlHandle, &port));
jiabin12537fc2023-10-12 17:56:08 +0000790 }
791 const bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
792 mixPort->role, mixPort->type)) == ::aidl::android::AudioPortDirection::INPUT;
793 *mixPort = VALUE_OR_RETURN_STATUS(::aidl::android::aidl2legacy_AudioPort_audio_port_v7(
794 port, isInput));
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700795 return OK;
jiabin12537fc2023-10-12 17:56:08 +0000796}
797
Mikhail Naganove93a0862023-03-15 17:06:59 -0700798status_t DeviceHalAidl::setAudioPortConfig(const struct audio_port_config* config) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530799 LOG_ENTRY();
800
Mikhail Naganove93a0862023-03-15 17:06:59 -0700801 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530802 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganove93a0862023-03-15 17:06:59 -0700803 if (config == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530804 AUGMENT_LOG(E, "config not initialized");
Mikhail Naganove93a0862023-03-15 17:06:59 -0700805 return BAD_VALUE;
806 }
807 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
808 config->role, config->type)) == ::aidl::android::AudioPortDirection::INPUT;
809 AudioPortConfig requestedPortConfig = VALUE_OR_RETURN_STATUS(
810 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
811 *config, isInput, 0 /*portId*/));
812 AudioPortConfig portConfig;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700813 std::lock_guard l(mLock);
Mikhail Naganovca92a5c2023-12-07 14:00:48 -0800814 return mMapper.setPortConfig(requestedPortConfig, std::set<int32_t>(), &portConfig);
Shunkai Yao51202502022-12-12 06:11:46 +0000815}
816
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800817MicrophoneInfoProvider::Info const* DeviceHalAidl::getMicrophoneInfo() {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530818 LOG_ENTRY();
819
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700820 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530821 RETURN_IF_MODULE_NOT_INIT({});
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700822 std::lock_guard l(mLock);
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800823 if (mMicrophones.status == Microphones::Status::UNKNOWN) {
824 TIME_CHECK();
825 std::vector<MicrophoneInfo> aidlInfo;
826 status_t status = statusTFromBinderStatus(mModule->getMicrophones(&aidlInfo));
827 if (status == OK) {
828 mMicrophones.status = Microphones::Status::QUERIED;
829 mMicrophones.info = std::move(aidlInfo);
830 } else if (status == INVALID_OPERATION) {
831 mMicrophones.status = Microphones::Status::NOT_SUPPORTED;
832 } else {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530833 AUGMENT_LOG(E, "Unexpected status from HAL: %d", status);
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800834 return {};
835 }
836 }
837 if (mMicrophones.status == Microphones::Status::QUERIED) {
838 return &mMicrophones.info;
839 }
840 return {}; // NOT_SUPPORTED
841}
842
Shunkai Yao51202502022-12-12 06:11:46 +0000843status_t DeviceHalAidl::getMicrophones(
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800844 std::vector<audio_microphone_characteristic_t>* microphones) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530845 LOG_ENTRY();
846
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700847 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530848 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700849 if (microphones == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530850 AUGMENT_LOG(E, "microphones not initialized");
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800851 return BAD_VALUE;
852 }
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800853 auto staticInfo = getMicrophoneInfo();
854 if (!staticInfo) return INVALID_OPERATION;
855 std::vector<MicrophoneDynamicInfo> emptyDynamicInfo;
856 emptyDynamicInfo.reserve(staticInfo->size());
857 std::transform(staticInfo->begin(), staticInfo->end(), std::back_inserter(emptyDynamicInfo),
858 [](const auto& info) { return MicrophoneDynamicInfo{ .id = info.id }; });
859 *microphones = VALUE_OR_RETURN_STATUS(
860 ::aidl::android::convertContainers<std::vector<audio_microphone_characteristic_t>>(
861 *staticInfo, emptyDynamicInfo,
862 ::aidl::android::aidl2legacy_MicrophoneInfos_audio_microphone_characteristic_t)
863 );
Shunkai Yao51202502022-12-12 06:11:46 +0000864 return OK;
865}
866
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700867status_t DeviceHalAidl::addDeviceEffect(
868 const struct audio_port_config *device, sp<EffectHalInterface> effect) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530869 LOG_ENTRY();
870
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700871 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530872 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700873 if (device == nullptr || effect == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530874 AUGMENT_LOG(E, "device or effect not initialized");
Shunkai Yao51202502022-12-12 06:11:46 +0000875 return BAD_VALUE;
876 }
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700877 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
878 device->role, device->type)) == ::aidl::android::AudioPortDirection::INPUT;
879 auto requestedPortConfig = VALUE_OR_RETURN_STATUS(
880 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
881 *device, isInput, 0));
882 if (requestedPortConfig.ext.getTag() != AudioPortExt::Tag::device) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530883 AUGMENT_LOG(E, "provided port config is not a device port config: %s",
884 requestedPortConfig.toString().c_str());
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700885 return BAD_VALUE;
886 }
887 AudioPortConfig devicePortConfig;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700888 Hal2AidlMapper::Cleanups cleanups(mMapperAccessor);
889 {
890 std::lock_guard l(mLock);
Mikhail Naganovca92a5c2023-12-07 14:00:48 -0800891 RETURN_STATUS_IF_ERROR(mMapper.setPortConfig(
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700892 requestedPortConfig, {} /*destinationPortIds*/, &devicePortConfig, &cleanups));
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700893 }
894 auto aidlEffect = sp<effect::EffectHalAidl>::cast(effect);
895 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->addDeviceEffect(
896 devicePortConfig.id, aidlEffect->getIEffect())));
897 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000898 return OK;
899}
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700900status_t DeviceHalAidl::removeDeviceEffect(
901 const struct audio_port_config *device, sp<EffectHalInterface> effect) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530902 LOG_ENTRY();
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700903 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530904 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700905 if (device == nullptr || effect == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530906 AUGMENT_LOG(E, "device or effect not initialized");
Shunkai Yao51202502022-12-12 06:11:46 +0000907 return BAD_VALUE;
908 }
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700909 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
910 device->role, device->type)) == ::aidl::android::AudioPortDirection::INPUT;
911 auto requestedPortConfig = VALUE_OR_RETURN_STATUS(
912 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
913 *device, isInput, 0));
914 if (requestedPortConfig.ext.getTag() != AudioPortExt::Tag::device) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530915 AUGMENT_LOG(E, "provided port config is not a device port config: %s",
916 requestedPortConfig.toString().c_str());
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700917 return BAD_VALUE;
918 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700919 AudioPortConfig devicePortConfig;
920 {
921 std::lock_guard l(mLock);
922 RETURN_STATUS_IF_ERROR(mMapper.findPortConfig(
923 requestedPortConfig.ext.get<AudioPortExt::Tag::device>().device,
924 &devicePortConfig));
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700925 }
926 auto aidlEffect = sp<effect::EffectHalAidl>::cast(effect);
927 return statusTFromBinderStatus(mModule->removeDeviceEffect(
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700928 devicePortConfig.id, aidlEffect->getIEffect()));
Shunkai Yao51202502022-12-12 06:11:46 +0000929}
930
931status_t DeviceHalAidl::getMmapPolicyInfos(
David Li9cf5e622023-03-21 00:51:10 +0800932 media::audio::common::AudioMMapPolicyType policyType,
933 std::vector<media::audio::common::AudioMMapPolicyInfo>* policyInfos) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530934 LOG_ENTRY();
935
Mikhail Naganov31d46652023-01-10 18:29:25 +0000936 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530937 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
938
939 AudioMMapPolicyType mmapPolicyType =
940 VALUE_OR_RETURN_STATUS(cpp2ndk_AudioMMapPolicyType(policyType));
David Li9cf5e622023-03-21 00:51:10 +0800941
942 std::vector<AudioMMapPolicyInfo> mmapPolicyInfos;
943
944 if (status_t status = statusTFromBinderStatus(
945 mModule->getMmapPolicyInfos(mmapPolicyType, &mmapPolicyInfos)); status != OK) {
946 return status;
947 }
948
949 *policyInfos = VALUE_OR_RETURN_STATUS(
950 convertContainer<std::vector<media::audio::common::AudioMMapPolicyInfo>>(
951 mmapPolicyInfos, ndk2cpp_AudioMMapPolicyInfo));
Shunkai Yao51202502022-12-12 06:11:46 +0000952 return OK;
953}
954
955int32_t DeviceHalAidl::getAAudioMixerBurstCount() {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530956 LOG_ENTRY();
957
Mikhail Naganov31d46652023-01-10 18:29:25 +0000958 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530959 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
David Li9cf5e622023-03-21 00:51:10 +0800960 int32_t mixerBurstCount = 0;
961 if (mModule->getAAudioMixerBurstCount(&mixerBurstCount).isOk()) {
962 return mixerBurstCount;
963 }
964 return 0;
Shunkai Yao51202502022-12-12 06:11:46 +0000965}
966
967int32_t DeviceHalAidl::getAAudioHardwareBurstMinUsec() {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530968 LOG_ENTRY();
969
Mikhail Naganov31d46652023-01-10 18:29:25 +0000970 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530971 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
David Li9cf5e622023-03-21 00:51:10 +0800972 int32_t hardwareBurstMinUsec = 0;
973 if (mModule->getAAudioHardwareBurstMinUsec(&hardwareBurstMinUsec).isOk()) {
974 return hardwareBurstMinUsec;
975 }
976 return 0;
Shunkai Yao51202502022-12-12 06:11:46 +0000977}
978
979error::Result<audio_hw_sync_t> DeviceHalAidl::getHwAvSync() {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530980 LOG_ENTRY();
981
Mikhail Naganov31d46652023-01-10 18:29:25 +0000982 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +0530983 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganov08a62ab2023-03-14 17:11:51 -0700984 int32_t aidlHwAvSync;
985 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->generateHwAvSyncId(&aidlHwAvSync)));
986 return VALUE_OR_RETURN_STATUS(
987 ::aidl::android::aidl2legacy_int32_t_audio_hw_sync_t(aidlHwAvSync));
Shunkai Yao51202502022-12-12 06:11:46 +0000988}
989
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000990status_t DeviceHalAidl::dump(int fd, const Vector<String16>& args) {
991 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700992 if (mModule == nullptr) return NO_INIT;
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000993 return mModule->dump(fd, Args(args).args(), args.size());
David Li9cf5e622023-03-21 00:51:10 +0800994}
Shunkai Yao51202502022-12-12 06:11:46 +0000995
Eric Laurent7af6ee72023-06-29 11:44:54 +0200996status_t DeviceHalAidl::supportsBluetoothVariableLatency(bool* supports) {
Jaideep Sharma145313e2024-08-14 14:51:24 +0530997 LOG_ENTRY();
998
Mikhail Naganov31d46652023-01-10 18:29:25 +0000999 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +05301000 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganov3ac95c92023-04-12 13:14:30 -07001001 if (supports == nullptr) {
1002 return BAD_VALUE;
1003 }
1004 return statusTFromBinderStatus(mModule->supportsVariableLatency(supports));
Shunkai Yao51202502022-12-12 06:11:46 +00001005}
Mikhail Naganov31d46652023-01-10 18:29:25 +00001006
Jaideep Sharma145313e2024-08-14 14:51:24 +05301007status_t DeviceHalAidl::getSoundDoseInterface([[maybe_unused]] const std::string& module,
1008 ::ndk::SpAIBinder* soundDoseBinder) {
1009 LOG_ENTRY_V();
1010 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
1011
Mikhail Naganovac9d4e72023-10-23 12:00:09 -07001012 if (soundDoseBinder == nullptr) {
1013 return BAD_VALUE;
1014 }
Vlad Popa03bd5bc2023-01-17 16:16:51 +01001015 if (mSoundDose == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +05301016 AUGMENT_LOG(E, "failed to retrieve the sound dose interface");
Mikhail Naganovac9d4e72023-10-23 12:00:09 -07001017 return BAD_VALUE;
Vlad Popa03bd5bc2023-01-17 16:16:51 +01001018 }
Vlad Popae1f33902023-10-30 19:48:25 -07001019
1020 if (mSoundDose == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +05301021 AUGMENT_LOG(E, "failed to return the sound dose interface not implemented");
Vlad Popae1f33902023-10-30 19:48:25 -07001022 return NO_INIT;
1023 }
1024
Vlad Popa03bd5bc2023-01-17 16:16:51 +01001025 *soundDoseBinder = mSoundDose->asBinder();
Jaideep Sharma145313e2024-08-14 14:51:24 +05301026 AUGMENT_LOG(I, "using audio AIDL HAL sound dose interface");
Vlad Popa03bd5bc2023-01-17 16:16:51 +01001027 return OK;
1028}
jiabin872de702023-04-27 22:04:31 +00001029
1030status_t DeviceHalAidl::prepareToDisconnectExternalDevice(const struct audio_port_v7* port) {
Jaideep Sharma145313e2024-08-14 14:51:24 +05301031 LOG_ENTRY_V();
jiabin62750c22023-12-21 22:06:07 +00001032 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +05301033 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
jiabin62750c22023-12-21 22:06:07 +00001034 if (port == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +05301035 AUGMENT_LOG(E, "port not initialized");
jiabin62750c22023-12-21 22:06:07 +00001036 return BAD_VALUE;
1037 }
Jaideep Sharma145313e2024-08-14 14:51:24 +05301038 const bool isInput =
1039 VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(port->role, port->type)) ==
1040 ::aidl::android::AudioPortDirection::INPUT;
jiabin62750c22023-12-21 22:06:07 +00001041 AudioPort aidlPort = VALUE_OR_RETURN_STATUS(
1042 ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
1043 if (aidlPort.ext.getTag() != AudioPortExt::device) {
Jaideep Sharma145313e2024-08-14 14:51:24 +05301044 AUGMENT_LOG(E, "provided port is not a device port: %s", aidlPort.toString().c_str());
jiabin62750c22023-12-21 22:06:07 +00001045 return BAD_VALUE;
1046 }
Jaideep Sharma145313e2024-08-14 14:51:24 +05301047
1048 AUGMENT_LOG(D, "device %s", aidlPort.toString().c_str());
1049
jiabin62750c22023-12-21 22:06:07 +00001050 status_t status = NO_ERROR;
1051 {
1052 std::lock_guard l(mLock);
1053 status = mMapper.prepareToDisconnectExternalDevice(aidlPort);
1054 }
1055 if (status == UNKNOWN_TRANSACTION) {
1056 // If there is not AIDL API defined for `prepareToDisconnectExternalDevice`.
1057 // Call `setConnectedState` instead.
1058 RETURN_STATUS_IF_ERROR(setConnectedState(port, false /*connected*/));
1059 std::lock_guard l(mLock);
1060 mDeviceDisconnectionNotified.insert(port->id);
1061 // Return that there was no error as otherwise the disconnection procedure will not be
1062 // considered complete for upper layers, and 'setConnectedState' will not be called again
1063 return OK;
1064 } else {
1065 return status;
1066 }
jiabin872de702023-04-27 22:04:31 +00001067}
1068
Mikhail Naganove93a0862023-03-15 17:06:59 -07001069status_t DeviceHalAidl::setConnectedState(const struct audio_port_v7 *port, bool connected) {
Jaideep Sharma145313e2024-08-14 14:51:24 +05301070 LOG_ENTRY_V();
Mikhail Naganove93a0862023-03-15 17:06:59 -07001071 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +05301072 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganove93a0862023-03-15 17:06:59 -07001073 if (port == nullptr) {
Jaideep Sharma145313e2024-08-14 14:51:24 +05301074 AUGMENT_LOG(E, "port not initialized");
Mikhail Naganove93a0862023-03-15 17:06:59 -07001075 return BAD_VALUE;
1076 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -07001077 if (!connected) {
1078 std::lock_guard l(mLock);
1079 if (mDeviceDisconnectionNotified.erase(port->id) > 0) {
1080 // For device disconnection, APM will first call `prepareToDisconnectExternalDevice`
jiabin62750c22023-12-21 22:06:07 +00001081 // and then call `setConnectedState`. If `prepareToDisconnectExternalDevice` doesn't
1082 // exit, `setConnectedState` will be called when calling
1083 // `prepareToDisconnectExternalDevice`. Do not call to the HAL if previous call is
1084 // successful. Also remove the cache here to avoid a large cache after a long run.
Mikhail Naganovac9d4e72023-10-23 12:00:09 -07001085 return OK;
1086 }
jiabin872de702023-04-27 22:04:31 +00001087 }
Mikhail Naganove93a0862023-03-15 17:06:59 -07001088 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(port->role, port->type)) ==
1089 ::aidl::android::AudioPortDirection::INPUT;
1090 AudioPort aidlPort = VALUE_OR_RETURN_STATUS(
1091 ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
1092 if (aidlPort.ext.getTag() != AudioPortExt::device) {
Jaideep Sharma145313e2024-08-14 14:51:24 +05301093 AUGMENT_LOG(E, "provided port is not a device port: %s", aidlPort.toString().c_str());
Mikhail Naganove93a0862023-03-15 17:06:59 -07001094 return BAD_VALUE;
1095 }
Jaideep Sharma145313e2024-08-14 14:51:24 +05301096 AUGMENT_LOG(D, "connected %d port: %s", connected, aidlPort.toString().c_str());
Mikhail Naganovac9d4e72023-10-23 12:00:09 -07001097 std::lock_guard l(mLock);
1098 return mMapper.setDevicePortConnectedState(aidlPort, connected);
Mikhail Naganove93a0862023-03-15 17:06:59 -07001099}
1100
1101status_t DeviceHalAidl::setSimulateDeviceConnections(bool enabled) {
Jaideep Sharma145313e2024-08-14 14:51:24 +05301102 LOG_ENTRY_V();
Mikhail Naganove93a0862023-03-15 17:06:59 -07001103 TIME_CHECK();
Jaideep Sharma145313e2024-08-14 14:51:24 +05301104 RETURN_IF_MODULE_NOT_INIT(NO_INIT);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -07001105 {
1106 std::lock_guard l(mLock);
Mikhail Naganova317a802024-03-15 18:03:10 +00001107 mMapper.resetUnusedPatchesAndPortConfigs();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -07001108 }
Mikhail Naganove93a0862023-03-15 17:06:59 -07001109 ModuleDebug debug{ .simulateDeviceConnections = enabled };
1110 status_t status = statusTFromBinderStatus(mModule->setModuleDebug(debug));
1111 // This is important to log as it affects HAL behavior.
1112 if (status == OK) {
Jaideep Sharma145313e2024-08-14 14:51:24 +05301113 AUGMENT_LOG(I, "set enabled: %d", enabled);
Mikhail Naganove93a0862023-03-15 17:06:59 -07001114 } else {
Jaideep Sharma145313e2024-08-14 14:51:24 +05301115 AUGMENT_LOG(W, "set enabled to %d failed: %d", enabled, status);
Mikhail Naganove93a0862023-03-15 17:06:59 -07001116 }
1117 return status;
1118}
1119
Mikhail Naganove7a26ad2023-05-25 17:36:48 -07001120status_t DeviceHalAidl::filterAndRetrieveBtA2dpParameters(
1121 AudioParameter &keys, AudioParameter *result) {
Mikhail Naganove7a26ad2023-05-25 17:36:48 -07001122 if (String8 key = String8(AudioParameter::keyReconfigA2dpSupported); keys.containsKey(key)) {
1123 keys.remove(key);
David Lia7761ed2023-11-03 17:22:07 +00001124 if (mBluetoothA2dp != nullptr) {
1125 bool supports;
1126 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
1127 mBluetoothA2dp->supportsOffloadReconfiguration(&supports)));
1128 result->addInt(key, supports ? 1 : 0);
1129 } else {
Jaideep Sharma145313e2024-08-14 14:51:24 +05301130 AUGMENT_LOG(I, "no IBluetoothA2dp");
David Lia7761ed2023-11-03 17:22:07 +00001131 result->addInt(key, 0);
1132 }
Mikhail Naganove7a26ad2023-05-25 17:36:48 -07001133 }
1134 return OK;
1135}
1136
Eric Laurent7e3c0832023-11-30 15:04:50 +01001137status_t DeviceHalAidl::filterAndRetrieveBtLeParameters(
1138 AudioParameter &keys, AudioParameter *result) {
1139 if (String8 key = String8(AudioParameter::keyReconfigLeSupported); keys.containsKey(key)) {
1140 keys.remove(key);
1141 if (mBluetoothLe != nullptr) {
1142 bool supports;
1143 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
1144 mBluetoothLe->supportsOffloadReconfiguration(&supports)));
1145 result->addInt(key, supports ? 1 : 0);
1146 } else {
Jaideep Sharma145313e2024-08-14 14:51:24 +05301147 AUGMENT_LOG(I, "no mBluetoothLe");
Eric Laurent7e3c0832023-11-30 15:04:50 +01001148 result->addInt(key, 0);
1149 }
1150 }
1151 return OK;
1152}
1153
Mikhail Naganovccc82112023-04-27 18:14:15 -07001154status_t DeviceHalAidl::filterAndUpdateBtA2dpParameters(AudioParameter &parameters) {
Mikhail Naganovccc82112023-04-27 18:14:15 -07001155 std::optional<bool> a2dpEnabled;
Mikhail Naganove7a26ad2023-05-25 17:36:48 -07001156 std::optional<std::vector<VendorParameter>> reconfigureOffload;
Mikhail Naganovccc82112023-04-27 18:14:15 -07001157 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301158 parameters, String8(AudioParameter::keyBtA2dpSuspended),
1159 [&a2dpEnabled, this](const String8& trueOrFalse) {
1160 if (trueOrFalse == AudioParameter::valueTrue) {
1161 a2dpEnabled = false; // 'suspended' == true
1162 return OK;
1163 } else if (trueOrFalse == AudioParameter::valueFalse) {
1164 a2dpEnabled = true; // 'suspended' == false
1165 return OK;
1166 }
1167 AUGMENT_LOG(E, "setParameters: parameter key \"%s\" has invalid value \"%s\"",
1168 AudioParameter::keyBtA2dpSuspended, trueOrFalse.c_str());
1169 return BAD_VALUE;
1170 }));
Mikhail Naganove7a26ad2023-05-25 17:36:48 -07001171 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301172 parameters, String8(AudioParameter::keyReconfigA2dp),
1173 [&](const String8& value) -> status_t {
1174 std::vector<VendorParameter> result;
1175 RETURN_STATUS_IF_ERROR(
1176 statusTFromBinderStatus(mVendorExt->parseBluetoothA2dpReconfigureOffload(
1177 std::string(value.c_str()), &result)));
1178 reconfigureOffload = std::move(result);
1179 return OK;
1180 }));
Mikhail Naganovccc82112023-04-27 18:14:15 -07001181 if (mBluetoothA2dp != nullptr && a2dpEnabled.has_value()) {
1182 return statusTFromBinderStatus(mBluetoothA2dp->setEnabled(a2dpEnabled.value()));
1183 }
Mikhail Naganove7a26ad2023-05-25 17:36:48 -07001184 if (mBluetoothA2dp != nullptr && reconfigureOffload.has_value()) {
1185 return statusTFromBinderStatus(mBluetoothA2dp->reconfigureOffload(
1186 reconfigureOffload.value()));
1187 }
Mikhail Naganovccc82112023-04-27 18:14:15 -07001188 return OK;
1189}
1190
1191status_t DeviceHalAidl::filterAndUpdateBtHfpParameters(AudioParameter &parameters) {
Mikhail Naganovccc82112023-04-27 18:14:15 -07001192 IBluetooth::HfpConfig hfpConfig;
1193 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301194 parameters, String8(AudioParameter::keyBtHfpEnable),
1195 [&hfpConfig, this](const String8& trueOrFalse) {
1196 if (trueOrFalse == AudioParameter::valueTrue) {
1197 hfpConfig.isEnabled = Boolean{.value = true};
1198 return OK;
1199 } else if (trueOrFalse == AudioParameter::valueFalse) {
1200 hfpConfig.isEnabled = Boolean{.value = false};
1201 return OK;
1202 }
1203 AUGMENT_LOG(E, "setParameters: parameter key \"%s\" has invalid value \"%s\"",
1204 AudioParameter::keyBtHfpEnable, trueOrFalse.c_str());
1205 return BAD_VALUE;
1206 }));
Mikhail Naganovccc82112023-04-27 18:14:15 -07001207 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301208 parameters, String8(AudioParameter::keyBtHfpSamplingRate),
1209 [&hfpConfig](int sampleRate) {
1210 return sampleRate > 0 ? hfpConfig.sampleRate = Int{.value = sampleRate},
1211 OK : BAD_VALUE;
1212 }));
Mikhail Naganovccc82112023-04-27 18:14:15 -07001213 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301214 parameters, String8(AudioParameter::keyBtHfpVolume), [&hfpConfig](int volume0to15) {
1215 if (volume0to15 >= 0 && volume0to15 <= 15) {
1216 hfpConfig.volume = Float{.value = volume0to15 / 15.0f};
1217 return OK;
1218 }
1219 return BAD_VALUE;
1220 }));
Mikhail Naganovccc82112023-04-27 18:14:15 -07001221 if (mBluetooth != nullptr && hfpConfig != IBluetooth::HfpConfig{}) {
1222 IBluetooth::HfpConfig newHfpConfig;
1223 return statusTFromBinderStatus(mBluetooth->setHfpConfig(hfpConfig, &newHfpConfig));
1224 }
1225 return OK;
1226}
1227
1228status_t DeviceHalAidl::filterAndUpdateBtLeParameters(AudioParameter &parameters) {
Mikhail Naganovccc82112023-04-27 18:14:15 -07001229 std::optional<bool> leEnabled;
Eric Laurent7e3c0832023-11-30 15:04:50 +01001230 std::optional<std::vector<VendorParameter>> reconfigureOffload;
Mikhail Naganovccc82112023-04-27 18:14:15 -07001231 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301232 parameters, String8(AudioParameter::keyBtLeSuspended),
1233 [&leEnabled, this](const String8& trueOrFalse) {
1234 if (trueOrFalse == AudioParameter::valueTrue) {
1235 leEnabled = false; // 'suspended' == true
1236 return OK;
1237 } else if (trueOrFalse == AudioParameter::valueFalse) {
1238 leEnabled = true; // 'suspended' == false
1239 return OK;
1240 }
1241 AUGMENT_LOG(E, "setParameters: parameter key \"%s\" has invalid value \"%s\"",
1242 AudioParameter::keyBtLeSuspended, trueOrFalse.c_str());
1243 return BAD_VALUE;
1244 }));
Eric Laurent7e3c0832023-11-30 15:04:50 +01001245 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301246 parameters, String8(AudioParameter::keyReconfigLe),
1247 [&](const String8& value) -> status_t {
1248 if (mVendorExt != nullptr) {
1249 std::vector<VendorParameter> result;
1250 RETURN_STATUS_IF_ERROR(
1251 statusTFromBinderStatus(mVendorExt->parseBluetoothLeReconfigureOffload(
1252 std::string(value.c_str()), &result)));
1253 reconfigureOffload = std::move(result);
1254 } else {
1255 reconfigureOffload = std::vector<VendorParameter>();
1256 }
1257 return OK;
1258 }));
Mikhail Naganovccc82112023-04-27 18:14:15 -07001259 if (mBluetoothLe != nullptr && leEnabled.has_value()) {
1260 return statusTFromBinderStatus(mBluetoothLe->setEnabled(leEnabled.value()));
1261 }
Eric Laurent7e3c0832023-11-30 15:04:50 +01001262 if (mBluetoothLe != nullptr && reconfigureOffload.has_value()) {
Jaideep Sharma145313e2024-08-14 14:51:24 +05301263 return statusTFromBinderStatus(
1264 mBluetoothLe->reconfigureOffload(reconfigureOffload.value()));
Eric Laurent7e3c0832023-11-30 15:04:50 +01001265 }
Mikhail Naganovccc82112023-04-27 18:14:15 -07001266 return OK;
1267}
1268
1269status_t DeviceHalAidl::filterAndUpdateBtScoParameters(AudioParameter &parameters) {
Mikhail Naganovccc82112023-04-27 18:14:15 -07001270 IBluetooth::ScoConfig scoConfig;
1271 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301272 parameters, String8(AudioParameter::keyBtSco),
1273 [&scoConfig, this](const String8& onOrOff) {
1274 if (onOrOff == AudioParameter::valueOn) {
1275 scoConfig.isEnabled = Boolean{.value = true};
1276 return OK;
1277 } else if (onOrOff == AudioParameter::valueOff) {
1278 scoConfig.isEnabled = Boolean{.value = false};
1279 return OK;
1280 }
1281 AUGMENT_LOG(E, "setParameters: parameter key \"%s\" has invalid value \"%s\"",
1282 AudioParameter::keyBtSco, onOrOff.c_str());
1283 return BAD_VALUE;
1284 }));
Mikhail Naganovccc82112023-04-27 18:14:15 -07001285 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301286 parameters, String8(AudioParameter::keyBtScoHeadsetName),
1287 [&scoConfig](const String8& name) {
1288 scoConfig.debugName = name;
1289 return OK;
1290 }));
Mikhail Naganovccc82112023-04-27 18:14:15 -07001291 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301292 parameters, String8(AudioParameter::keyBtNrec),
1293 [&scoConfig, this](const String8& onOrOff) {
1294 if (onOrOff == AudioParameter::valueOn) {
1295 scoConfig.isNrecEnabled = Boolean{.value = true};
1296 return OK;
1297 } else if (onOrOff == AudioParameter::valueOff) {
1298 scoConfig.isNrecEnabled = Boolean{.value = false};
1299 return OK;
1300 }
1301 AUGMENT_LOG(E, "setParameters: parameter key \"%s\" has invalid value \"%s\"",
1302 AudioParameter::keyBtNrec, onOrOff.c_str());
1303 return BAD_VALUE;
1304 }));
Mikhail Naganovccc82112023-04-27 18:14:15 -07001305 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301306 parameters, String8(AudioParameter::keyBtScoWb),
1307 [&scoConfig, this](const String8& onOrOff) {
1308 if (onOrOff == AudioParameter::valueOn) {
1309 scoConfig.mode = IBluetooth::ScoConfig::Mode::SCO_WB;
1310 return OK;
1311 } else if (onOrOff == AudioParameter::valueOff) {
1312 scoConfig.mode = IBluetooth::ScoConfig::Mode::SCO;
1313 return OK;
1314 }
1315 AUGMENT_LOG(E, "setParameters: parameter key \"%s\" has invalid value \"%s\"",
1316 AudioParameter::keyBtScoWb, onOrOff.c_str());
1317 return BAD_VALUE;
1318 }));
Mikhail Naganovccc82112023-04-27 18:14:15 -07001319 if (mBluetooth != nullptr && scoConfig != IBluetooth::ScoConfig{}) {
1320 IBluetooth::ScoConfig newScoConfig;
1321 return statusTFromBinderStatus(mBluetooth->setScoConfig(scoConfig, &newScoConfig));
1322 }
1323 return OK;
1324}
1325
Mikhail Naganove92c34b2023-05-31 14:24:48 -07001326status_t DeviceHalAidl::filterAndUpdateScreenParameters(AudioParameter &parameters) {
Mikhail Naganove92c34b2023-05-31 14:24:48 -07001327 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301328 parameters, String8(AudioParameter::keyScreenState),
1329 [&, this](const String8& onOrOff) -> status_t {
1330 std::optional<bool> isTurnedOn;
1331 if (onOrOff == AudioParameter::valueOn) {
1332 isTurnedOn = true;
1333 } else if (onOrOff == AudioParameter::valueOff) {
1334 isTurnedOn = false;
1335 }
1336 if (!isTurnedOn.has_value()) {
1337 AUGMENT_LOG(E, "setParameters: parameter key \"%s\" has invalid value \"%s\"",
1338 AudioParameter::keyScreenState, onOrOff.c_str());
1339 return BAD_VALUE;
1340 }
1341 return statusTFromBinderStatus(mModule->updateScreenState(isTurnedOn.value()));
1342 }));
Mikhail Naganove92c34b2023-05-31 14:24:48 -07001343 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301344 parameters, String8(AudioParameter::keyScreenRotation),
1345 [&, this](int rotationDegrees) -> status_t {
Mikhail Naganove92c34b2023-05-31 14:24:48 -07001346 IModule::ScreenRotation rotation;
1347 switch (rotationDegrees) {
Jaideep Sharma145313e2024-08-14 14:51:24 +05301348 case 0:
1349 rotation = IModule::ScreenRotation::DEG_0;
1350 break;
1351 case 90:
1352 rotation = IModule::ScreenRotation::DEG_90;
1353 break;
1354 case 180:
1355 rotation = IModule::ScreenRotation::DEG_180;
1356 break;
1357 case 270:
1358 rotation = IModule::ScreenRotation::DEG_270;
1359 break;
Mikhail Naganove92c34b2023-05-31 14:24:48 -07001360 default:
Jaideep Sharma145313e2024-08-14 14:51:24 +05301361 AUGMENT_LOG(E, "setParameters: parameter key \"%s\" has invalid value %d",
1362 AudioParameter::keyScreenRotation, rotationDegrees);
Mikhail Naganove92c34b2023-05-31 14:24:48 -07001363 return BAD_VALUE;
1364 }
1365 return statusTFromBinderStatus(mModule->updateScreenRotation(rotation));
1366 }));
1367 return OK;
1368}
1369
Mikhail Naganovb9a81312023-07-18 13:55:34 -07001370status_t DeviceHalAidl::filterAndUpdateTelephonyParameters(AudioParameter &parameters) {
Mikhail Naganovb9a81312023-07-18 13:55:34 -07001371 using TtyMode = ITelephony::TelecomConfig::TtyMode;
1372 ITelephony::TelecomConfig telConfig;
1373 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301374 parameters, String8(AudioParameter::keyTtyMode),
1375 [&telConfig, this](const String8& mode) {
1376 if (mode == AudioParameter::valueTtyModeOff) {
1377 telConfig.ttyMode = TtyMode::OFF;
1378 return OK;
1379 } else if (mode == AudioParameter::valueTtyModeFull) {
1380 telConfig.ttyMode = TtyMode::FULL;
1381 return OK;
1382 } else if (mode == AudioParameter::valueTtyModeHco) {
1383 telConfig.ttyMode = TtyMode::HCO;
1384 return OK;
1385 } else if (mode == AudioParameter::valueTtyModeVco) {
1386 telConfig.ttyMode = TtyMode::VCO;
1387 return OK;
1388 }
1389 AUGMENT_LOG(E, "setParameters: parameter key \"%s\" has invalid value \"%s\"",
1390 AudioParameter::keyTtyMode, mode.c_str());
1391 return BAD_VALUE;
1392 }));
Mikhail Naganovb9a81312023-07-18 13:55:34 -07001393 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
Jaideep Sharma145313e2024-08-14 14:51:24 +05301394 parameters, String8(AudioParameter::keyHacSetting),
1395 [&telConfig, this](const String8& onOrOff) {
1396 if (onOrOff == AudioParameter::valueHacOn) {
1397 telConfig.isHacEnabled = Boolean{.value = true};
1398 return OK;
1399 } else if (onOrOff == AudioParameter::valueHacOff) {
1400 telConfig.isHacEnabled = Boolean{.value = false};
1401 return OK;
1402 }
1403 AUGMENT_LOG(E, "setParameters: parameter key \"%s\" has invalid value \"%s\"",
1404 AudioParameter::keyHacSetting, onOrOff.c_str());
1405 return BAD_VALUE;
1406 }));
Mikhail Naganovb9a81312023-07-18 13:55:34 -07001407 if (mTelephony != nullptr && telConfig != ITelephony::TelecomConfig{}) {
1408 ITelephony::TelecomConfig newTelConfig;
Jaideep Sharma145313e2024-08-14 14:51:24 +05301409 return statusTFromBinderStatus(mTelephony->setTelecomConfig(telConfig, &newTelConfig));
Mikhail Naganovb9a81312023-07-18 13:55:34 -07001410 }
1411 return OK;
1412}
1413
Mikhail Naganovdfd594e2023-02-08 16:59:41 -08001414void DeviceHalAidl::clearCallbacks(void* cookie) {
Mikhail Naganov22578412024-08-16 16:50:34 -07001415 std::lock_guard l(mCallbacksLock);
Mikhail Naganovdfd594e2023-02-08 16:59:41 -08001416 mCallbacks.erase(cookie);
1417}
1418
1419sp<StreamOutHalInterfaceCallback> DeviceHalAidl::getStreamOutCallback(void* cookie) {
1420 return getCallbackImpl(cookie, &Callbacks::out);
1421}
1422
1423void DeviceHalAidl::setStreamOutCallback(
1424 void* cookie, const sp<StreamOutHalInterfaceCallback>& cb) {
1425 setCallbackImpl(cookie, &Callbacks::out, cb);
1426}
1427
1428sp<StreamOutHalInterfaceEventCallback> DeviceHalAidl::getStreamOutEventCallback(
1429 void* cookie) {
1430 return getCallbackImpl(cookie, &Callbacks::event);
1431}
1432
1433void DeviceHalAidl::setStreamOutEventCallback(
1434 void* cookie, const sp<StreamOutHalInterfaceEventCallback>& cb) {
1435 setCallbackImpl(cookie, &Callbacks::event, cb);
1436}
1437
1438sp<StreamOutHalInterfaceLatencyModeCallback> DeviceHalAidl::getStreamOutLatencyModeCallback(
1439 void* cookie) {
1440 return getCallbackImpl(cookie, &Callbacks::latency);
1441}
1442
1443void DeviceHalAidl::setStreamOutLatencyModeCallback(
1444 void* cookie, const sp<StreamOutHalInterfaceLatencyModeCallback>& cb) {
1445 setCallbackImpl(cookie, &Callbacks::latency, cb);
1446}
1447
Mikhail Naganov22578412024-08-16 16:50:34 -07001448template <class C>
Mikhail Naganovdfd594e2023-02-08 16:59:41 -08001449sp<C> DeviceHalAidl::getCallbackImpl(void* cookie, wp<C> DeviceHalAidl::Callbacks::* field) {
Mikhail Naganov22578412024-08-16 16:50:34 -07001450 wp<C> result;
1451 {
1452 std::lock_guard l(mCallbacksLock);
1453 if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
1454 result = (it->second).*field;
1455 }
Mikhail Naganovdfd594e2023-02-08 16:59:41 -08001456 }
Mikhail Naganov22578412024-08-16 16:50:34 -07001457 return result.promote();
Mikhail Naganovdfd594e2023-02-08 16:59:41 -08001458}
1459template<class C>
1460void DeviceHalAidl::setCallbackImpl(
1461 void* cookie, wp<C> DeviceHalAidl::Callbacks::* field, const sp<C>& cb) {
Mikhail Naganov22578412024-08-16 16:50:34 -07001462 std::lock_guard l(mCallbacksLock);
Mikhail Naganovdfd594e2023-02-08 16:59:41 -08001463 if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
1464 (it->second).*field = cb;
1465 }
1466}
1467
Mikhail Naganov31d46652023-01-10 18:29:25 +00001468} // namespace android