blob: 6a6557c670c0717cb0e1c91f6003c1e94afeeb1a [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"
Vlad Popa03bd5bc2023-01-17 16:16:51 +010018// #define LOG_NDEBUG 0
Shunkai Yao51202502022-12-12 06:11:46 +000019
Mikhail Naganovf56ce782023-01-25 11:29:11 -080020#include <algorithm>
Mikhail Naganovf56ce782023-01-25 11:29:11 -080021
Mikhail Naganovb0c55252023-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>
Mikhail Naganovbfbb75b2023-04-21 18:48:16 -070027#include <media/AidlConversionNdkCpp.h>
Mikhail Naganovfab697c2023-01-11 19:33:13 +000028#include <media/AidlConversionUtil.h>
Mikhail Naganov31d46652023-01-10 18:29:25 +000029#include <mediautils/TimeCheck.h>
Mikhail Naganovae9063d2023-11-07 16:43:51 -080030#include <system/audio.h>
Mikhail Naganov8bd806e2023-01-30 12:33:18 -080031#include <Utils.h>
Mikhail Naganov31d46652023-01-10 18:29:25 +000032#include <utils/Log.h>
Shunkai Yao51202502022-12-12 06:11:46 +000033
Mikhail Naganov31d46652023-01-10 18:29:25 +000034#include "DeviceHalAidl.h"
Mikhail Naganova82a69d2023-06-14 16:31:32 -070035#include "EffectHalAidl.h"
Mikhail Naganov31d46652023-01-10 18:29:25 +000036#include "StreamHalAidl.h"
37
Mikhail Naganovfab697c2023-01-11 19:33:13 +000038using aidl::android::aidl_utils::statusTFromBinderStatus;
Mikhail Naganov27382bb2023-04-27 18:14:15 -070039using aidl::android::media::audio::common::Boolean;
Mikhail Naganovf56ce782023-01-25 11:29:11 -080040using aidl::android::media::audio::common::AudioConfig;
41using aidl::android::media::audio::common::AudioDevice;
Mikhail Naganov8bd806e2023-01-30 12:33:18 -080042using aidl::android::media::audio::common::AudioDeviceType;
Mikhail Naganovf56ce782023-01-25 11:29:11 -080043using aidl::android::media::audio::common::AudioIoFlags;
Mikhail Naganovb0c55252023-02-08 16:59:41 -080044using aidl::android::media::audio::common::AudioLatencyMode;
David Li9cf5e622023-03-21 00:51:10 +080045using aidl::android::media::audio::common::AudioMMapPolicy;
46using aidl::android::media::audio::common::AudioMMapPolicyInfo;
47using aidl::android::media::audio::common::AudioMMapPolicyType;
Mikhail Naganovfab697c2023-01-11 19:33:13 +000048using aidl::android::media::audio::common::AudioMode;
Mikhail Naganovf56ce782023-01-25 11:29:11 -080049using aidl::android::media::audio::common::AudioOutputFlags;
50using aidl::android::media::audio::common::AudioPort;
51using aidl::android::media::audio::common::AudioPortConfig;
David Li9cf5e622023-03-21 00:51:10 +080052using aidl::android::media::audio::common::AudioPortExt;
Mikhail Naganovf56ce782023-01-25 11:29:11 -080053using aidl::android::media::audio::common::AudioSource;
Mikhail Naganovfab697c2023-01-11 19:33:13 +000054using aidl::android::media::audio::common::Float;
David Li9cf5e622023-03-21 00:51:10 +080055using aidl::android::media::audio::common::Int;
56using aidl::android::media::audio::common::MicrophoneDynamicInfo;
57using aidl::android::media::audio::common::MicrophoneInfo;
Mikhail Naganove7a26ad2023-05-25 17:36:48 -070058using aidl::android::media::audio::IHalAdapterVendorExtension;
Mikhail Naganov6352e822023-03-09 18:22:36 -080059using aidl::android::hardware::audio::common::getFrameSizeInBytes;
60using aidl::android::hardware::audio::common::isBitPositionFlagSet;
Mikhail Naganovf56ce782023-01-25 11:29:11 -080061using aidl::android::hardware::audio::common::RecordTrackMetadata;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -070062using aidl::android::hardware::audio::core::sounddose::ISoundDose;
Mikhail Naganovf56ce782023-01-25 11:29:11 -080063using aidl::android::hardware::audio::core::AudioPatch;
Mikhail Naganovecfafb72023-03-29 10:06:15 -070064using aidl::android::hardware::audio::core::AudioRoute;
Mikhail Naganov27382bb2023-04-27 18:14:15 -070065using aidl::android::hardware::audio::core::IBluetooth;
66using aidl::android::hardware::audio::core::IBluetoothA2dp;
67using aidl::android::hardware::audio::core::IBluetoothLe;
Mikhail Naganovfab697c2023-01-11 19:33:13 +000068using aidl::android::hardware::audio::core::IModule;
69using aidl::android::hardware::audio::core::ITelephony;
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -070070using aidl::android::hardware::audio::core::ModuleDebug;
Mikhail Naganove7a26ad2023-05-25 17:36:48 -070071using aidl::android::hardware::audio::core::VendorParameter;
Mikhail Naganov31d46652023-01-10 18:29:25 +000072
73namespace android {
74
Mikhail Naganovf56ce782023-01-25 11:29:11 -080075namespace {
76
Mikhail Naganov2d814892023-04-24 13:06:04 -070077// Note: these converters are for types defined in different AIDL files. Although these
78// AIDL files are copies of each other, however formally these are different types
79// thus we don't use a conversion via a parcelable.
80ConversionResult<media::AudioRoute> ndk2cpp_AudioRoute(const AudioRoute& ndk) {
81 media::AudioRoute cpp;
82 cpp.sourcePortIds.insert(
83 cpp.sourcePortIds.end(), ndk.sourcePortIds.begin(), ndk.sourcePortIds.end());
84 cpp.sinkPortId = ndk.sinkPortId;
85 cpp.isExclusive = ndk.isExclusive;
86 return cpp;
87}
88
Mikhail Naganovffd97712023-05-03 17:45:36 -070089template<typename T>
90std::shared_ptr<T> retrieveSubInterface(const std::shared_ptr<IModule>& module,
91 ::ndk::ScopedAStatus (IModule::*getT)(std::shared_ptr<T>*)) {
92 if (module != nullptr) {
93 std::shared_ptr<T> instance;
94 if (auto status = (module.get()->*getT)(&instance); status.isOk()) {
95 return instance;
96 }
97 }
98 return nullptr;
99}
100
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800101} // namespace
102
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700103DeviceHalAidl::DeviceHalAidl(const std::string& instance, const std::shared_ptr<IModule>& module,
104 const std::shared_ptr<IHalAdapterVendorExtension>& vext)
Mikhail Naganovffd97712023-05-03 17:45:36 -0700105 : ConversionHelperAidl("DeviceHalAidl"),
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700106 mInstance(instance), mModule(module), mVendorExt(vext),
Mikhail Naganov27382bb2023-04-27 18:14:15 -0700107 mTelephony(retrieveSubInterface<ITelephony>(module, &IModule::getTelephony)),
108 mBluetooth(retrieveSubInterface<IBluetooth>(module, &IModule::getBluetooth)),
109 mBluetoothA2dp(retrieveSubInterface<IBluetoothA2dp>(module, &IModule::getBluetoothA2dp)),
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700110 mBluetoothLe(retrieveSubInterface<IBluetoothLe>(module, &IModule::getBluetoothLe)),
111 mSoundDose(retrieveSubInterface<ISoundDose>(module, &IModule::getSoundDose)),
112 mMapper(instance, module), mMapperAccessor(mMapper, mLock) {
Mikhail Naganovffd97712023-05-03 17:45:36 -0700113}
114
Mikhail Naganov2d814892023-04-24 13:06:04 -0700115status_t DeviceHalAidl::getAudioPorts(std::vector<media::audio::common::AudioPort> *ports) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700116 std::lock_guard l(mLock);
117 return mMapper.getAudioPorts(ports, ndk2cpp_AudioPort);
Mikhail Naganov2d814892023-04-24 13:06:04 -0700118}
119
120status_t DeviceHalAidl::getAudioRoutes(std::vector<media::AudioRoute> *routes) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700121 std::lock_guard l(mLock);
122 return mMapper.getAudioRoutes(routes, ndk2cpp_AudioRoute);
Mikhail Naganov2d814892023-04-24 13:06:04 -0700123}
124
Mikhail Naganovffd97712023-05-03 17:45:36 -0700125status_t DeviceHalAidl::getSupportedModes(std::vector<media::audio::common::AudioMode> *modes) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700126 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganovffd97712023-05-03 17:45:36 -0700127 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700128 if (mModule == nullptr) return NO_INIT;
129 if (mTelephony == nullptr) return INVALID_OPERATION;
Mikhail Naganovffd97712023-05-03 17:45:36 -0700130 if (modes == nullptr) {
131 return BAD_VALUE;
132 }
Mikhail Naganovffd97712023-05-03 17:45:36 -0700133 std::vector<AudioMode> aidlModes;
134 RETURN_STATUS_IF_ERROR(
135 statusTFromBinderStatus(mTelephony->getSupportedAudioModes(&aidlModes)));
136 *modes = VALUE_OR_RETURN_STATUS(
137 ::aidl::android::convertContainer<std::vector<media::audio::common::AudioMode>>(
138 aidlModes, ndk2cpp_AudioMode));
139 return OK;
140}
141
Mikhail Naganov31d46652023-01-10 18:29:25 +0000142status_t DeviceHalAidl::getSupportedDevices(uint32_t*) {
143 // Obsolete.
144 return INVALID_OPERATION;
Shunkai Yao51202502022-12-12 06:11:46 +0000145}
146
147status_t DeviceHalAidl::initCheck() {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700148 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800149 TIME_CHECK();
Mikhail Naganov31d46652023-01-10 18:29:25 +0000150 if (mModule == nullptr) return NO_INIT;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700151 std::lock_guard l(mLock);
152 return mMapper.initialize();
Shunkai Yao51202502022-12-12 06:11:46 +0000153}
154
155status_t DeviceHalAidl::setVoiceVolume(float volume) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700156 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000157 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700158 if (mModule == nullptr) return NO_INIT;
Mikhail Naganovffd97712023-05-03 17:45:36 -0700159 if (mTelephony == nullptr) return INVALID_OPERATION;
160 ITelephony::TelecomConfig inConfig{ .voiceVolume = Float{volume} }, outConfig;
161 RETURN_STATUS_IF_ERROR(
162 statusTFromBinderStatus(mTelephony->setTelecomConfig(inConfig, &outConfig)));
163 ALOGW_IF(outConfig.voiceVolume.has_value() && volume != outConfig.voiceVolume.value().value,
164 "%s: the resulting voice volume %f is not the same as requested %f",
165 __func__, outConfig.voiceVolume.value().value, volume);
166 return OK;
Shunkai Yao51202502022-12-12 06:11:46 +0000167}
168
169status_t DeviceHalAidl::setMasterVolume(float volume) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700170 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000171 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700172 if (mModule == nullptr) return NO_INIT;
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000173 return statusTFromBinderStatus(mModule->setMasterVolume(volume));
Shunkai Yao51202502022-12-12 06:11:46 +0000174}
175
176status_t DeviceHalAidl::getMasterVolume(float *volume) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700177 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000178 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700179 if (mModule == nullptr) return NO_INIT;
180 if (volume == nullptr) {
181 return BAD_VALUE;
182 }
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000183 return statusTFromBinderStatus(mModule->getMasterVolume(volume));
Shunkai Yao51202502022-12-12 06:11:46 +0000184}
185
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000186status_t DeviceHalAidl::setMode(audio_mode_t mode) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700187 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000188 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700189 if (mModule == nullptr) return NO_INIT;
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000190 AudioMode audioMode = VALUE_OR_FATAL(::aidl::android::legacy2aidl_audio_mode_t_AudioMode(mode));
Mikhail Naganovffd97712023-05-03 17:45:36 -0700191 if (mTelephony != nullptr) {
192 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mTelephony->switchAudioMode(audioMode)));
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000193 }
194 return statusTFromBinderStatus(mModule->updateAudioMode(audioMode));
Shunkai Yao51202502022-12-12 06:11:46 +0000195}
196
197status_t DeviceHalAidl::setMicMute(bool state) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700198 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000199 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700200 if (mModule == nullptr) return NO_INIT;
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000201 return statusTFromBinderStatus(mModule->setMicMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000202}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000203
Shunkai Yao51202502022-12-12 06:11:46 +0000204status_t DeviceHalAidl::getMicMute(bool *state) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700205 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000206 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700207 if (mModule == nullptr) return NO_INIT;
208 if (state == nullptr) {
209 return BAD_VALUE;
210 }
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000211 return statusTFromBinderStatus(mModule->getMicMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000212}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000213
Shunkai Yao51202502022-12-12 06:11:46 +0000214status_t DeviceHalAidl::setMasterMute(bool state) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700215 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000216 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700217 if (mModule == nullptr) return NO_INIT;
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000218 return statusTFromBinderStatus(mModule->setMasterMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000219}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000220
Shunkai Yao51202502022-12-12 06:11:46 +0000221status_t DeviceHalAidl::getMasterMute(bool *state) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700222 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000223 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700224 if (mModule == nullptr) return NO_INIT;
225 if (state == nullptr) {
226 return BAD_VALUE;
227 }
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000228 return statusTFromBinderStatus(mModule->getMasterMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000229}
230
Mikhail Naganov27382bb2023-04-27 18:14:15 -0700231status_t DeviceHalAidl::setParameters(const String8& kvPairs) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700232 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
233 TIME_CHECK();
234 if (mModule == nullptr) return NO_INIT;
Mikhail Naganov27382bb2023-04-27 18:14:15 -0700235 AudioParameter parameters(kvPairs);
236 ALOGD("%s: parameters: \"%s\"", __func__, parameters.toString().c_str());
237
238 if (status_t status = filterAndUpdateBtA2dpParameters(parameters); status != OK) {
239 ALOGW("%s: filtering or updating BT A2DP parameters failed: %d", __func__, status);
240 }
241 if (status_t status = filterAndUpdateBtHfpParameters(parameters); status != OK) {
242 ALOGW("%s: filtering or updating BT HFP parameters failed: %d", __func__, status);
243 }
244 if (status_t status = filterAndUpdateBtLeParameters(parameters); status != OK) {
245 ALOGW("%s: filtering or updating BT LE parameters failed: %d", __func__, status);
246 }
247 if (status_t status = filterAndUpdateBtScoParameters(parameters); status != OK) {
248 ALOGW("%s: filtering or updating BT SCO parameters failed: %d", __func__, status);
249 }
Mikhail Naganove92c34b2023-05-31 14:24:48 -0700250 if (status_t status = filterAndUpdateScreenParameters(parameters); status != OK) {
251 ALOGW("%s: filtering or updating screen parameters failed: %d", __func__, status);
252 }
Mikhail Naganovb9a81312023-07-18 13:55:34 -0700253 if (status_t status = filterAndUpdateTelephonyParameters(parameters); status != OK) {
254 ALOGW("%s: filtering or updating telephony parameters failed: %d", __func__, status);
255 }
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700256 return parseAndSetVendorParameters(mVendorExt, mModule, parameters);
Shunkai Yao51202502022-12-12 06:11:46 +0000257}
258
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700259status_t DeviceHalAidl::getParameters(const String8& keys, String8 *values) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700260 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000261 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700262 if (mModule == nullptr) return NO_INIT;
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700263 if (values == nullptr) {
264 return BAD_VALUE;
265 }
266 AudioParameter parameterKeys(keys), result;
267 if (status_t status = filterAndRetrieveBtA2dpParameters(parameterKeys, &result); status != OK) {
268 ALOGW("%s: filtering or retrieving BT A2DP parameters failed: %d", __func__, status);
269 }
Eric Laurent7e3c0832023-11-30 15:04:50 +0100270 if (status_t status = filterAndRetrieveBtLeParameters(parameterKeys, &result); status != OK) {
271 ALOGW("%s: filtering or retrieving BT LE parameters failed: %d", __func__, status);
272 }
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700273 *values = result.toString();
274 return parseAndGetVendorParameters(mVendorExt, mModule, parameterKeys, values);
Shunkai Yao51202502022-12-12 06:11:46 +0000275}
276
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800277status_t DeviceHalAidl::getInputBufferSize(const struct audio_config* config, size_t* size) {
278 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800279 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700280 if (mModule == nullptr) return NO_INIT;
281 if (config == nullptr || size == nullptr) {
282 return BAD_VALUE;
283 }
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800284 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
285 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, true /*isInput*/));
286 AudioDevice aidlDevice;
287 aidlDevice.type.type = AudioDeviceType::IN_DEFAULT;
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800288 AudioSource aidlSource = AudioSource::DEFAULT;
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800289 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::input>(0);
290 AudioPortConfig mixPortConfig;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700291 Hal2AidlMapper::Cleanups cleanups(mMapperAccessor);
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700292 AudioPatch aidlPatch;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700293 {
294 std::lock_guard l(mLock);
295 RETURN_STATUS_IF_ERROR(mMapper.prepareToOpenStream(
296 0 /*handle*/, aidlDevice, aidlFlags, aidlSource,
297 &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
298 }
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800299 *size = aidlConfig.frameCount *
300 getFrameSizeInBytes(aidlConfig.base.format, aidlConfig.base.channelMask);
301 // Do not disarm cleanups to release temporary port configs.
302 return OK;
303}
304
Mikhail Naganovb0c55252023-02-08 16:59:41 -0800305namespace {
306
307class StreamCallbackBase {
308 protected:
309 explicit StreamCallbackBase(const sp<CallbackBroker>& broker) : mBroker(broker) {}
310 public:
311 void* getCookie() const { return mCookie; }
312 void setCookie(void* cookie) { mCookie = cookie; }
313 sp<CallbackBroker> getBroker() const {
314 if (void* cookie = mCookie; cookie != nullptr) return mBroker.promote();
315 return nullptr;
316 }
317 private:
318 const wp<CallbackBroker> mBroker;
319 std::atomic<void*> mCookie;
320};
321
322template<class C>
323class StreamCallbackBaseHelper {
324 protected:
325 explicit StreamCallbackBaseHelper(const StreamCallbackBase& base) : mBase(base) {}
326 sp<C> getCb(const sp<CallbackBroker>& broker, void* cookie);
327 using CbRef = const sp<C>&;
328 ndk::ScopedAStatus runCb(const std::function<void(CbRef cb)>& f) {
329 if (auto cb = getCb(mBase.getBroker(), mBase.getCookie()); cb != nullptr) f(cb);
330 return ndk::ScopedAStatus::ok();
331 }
332 private:
333 const StreamCallbackBase& mBase;
334};
335
336template<>
337sp<StreamOutHalInterfaceCallback> StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>::getCb(
338 const sp<CallbackBroker>& broker, void* cookie) {
339 if (broker != nullptr) return broker->getStreamOutCallback(cookie);
340 return nullptr;
341}
342
343template<>
344sp<StreamOutHalInterfaceEventCallback>
345StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>::getCb(
346 const sp<CallbackBroker>& broker, void* cookie) {
347 if (broker != nullptr) return broker->getStreamOutEventCallback(cookie);
348 return nullptr;
349}
350
351template<>
352sp<StreamOutHalInterfaceLatencyModeCallback>
353StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>::getCb(
354 const sp<CallbackBroker>& broker, void* cookie) {
355 if (broker != nullptr) return broker->getStreamOutLatencyModeCallback(cookie);
356 return nullptr;
357}
358
359/*
360Note on the callback ownership.
361
362In the Binder ownership model, the server implementation is kept alive
363as long as there is any client (proxy object) alive. This is done by
364incrementing the refcount of the server-side object by the Binder framework.
365When it detects that the last client is gone, it decrements the refcount back.
366
367Thus, it is not needed to keep any references to StreamCallback on our
368side (after we have sent an instance to the client), because we are
369the server-side. The callback object will be kept alive as long as the HAL server
370holds a strong ref to IStreamCallback proxy.
371*/
372
373class OutputStreamCallbackAidl : public StreamCallbackBase,
374 public StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>,
375 public ::aidl::android::hardware::audio::core::BnStreamCallback {
376 public:
377 explicit OutputStreamCallbackAidl(const sp<CallbackBroker>& broker)
378 : StreamCallbackBase(broker),
379 StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>(
380 *static_cast<StreamCallbackBase*>(this)) {}
381 ndk::ScopedAStatus onTransferReady() override {
382 return runCb([](CbRef cb) { cb->onWriteReady(); });
383 }
384 ndk::ScopedAStatus onError() override {
385 return runCb([](CbRef cb) { cb->onError(); });
386 }
387 ndk::ScopedAStatus onDrainReady() override {
388 return runCb([](CbRef cb) { cb->onDrainReady(); });
389 }
390};
391
392class OutputStreamEventCallbackAidl :
393 public StreamCallbackBase,
394 public StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>,
395 public StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>,
396 public ::aidl::android::hardware::audio::core::BnStreamOutEventCallback {
397 public:
398 explicit OutputStreamEventCallbackAidl(const sp<CallbackBroker>& broker)
399 : StreamCallbackBase(broker),
400 StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>(
401 *static_cast<StreamCallbackBase*>(this)),
402 StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>(
403 *static_cast<StreamCallbackBase*>(this)) {}
404 ndk::ScopedAStatus onCodecFormatChanged(const std::vector<uint8_t>& in_audioMetadata) override {
405 std::basic_string<uint8_t> halMetadata(in_audioMetadata.begin(), in_audioMetadata.end());
406 return StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>::runCb(
407 [&halMetadata](auto cb) { cb->onCodecFormatChanged(halMetadata); });
408 }
409 ndk::ScopedAStatus onRecommendedLatencyModeChanged(
410 const std::vector<AudioLatencyMode>& in_modes) override {
411 auto halModes = VALUE_OR_FATAL(
412 ::aidl::android::convertContainer<std::vector<audio_latency_mode_t>>(
413 in_modes,
414 ::aidl::android::aidl2legacy_AudioLatencyMode_audio_latency_mode_t));
415 return StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>::runCb(
416 [&halModes](auto cb) { cb->onRecommendedLatencyModeChanged(halModes); });
417 }
418};
419
420} // namespace
421
Mikhail Naganov31d46652023-01-10 18:29:25 +0000422status_t DeviceHalAidl::openOutputStream(
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800423 audio_io_handle_t handle, audio_devices_t devices,
424 audio_output_flags_t flags, struct audio_config* config,
425 const char* address,
Mikhail Naganov31d46652023-01-10 18:29:25 +0000426 sp<StreamOutHalInterface>* outStream) {
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800427 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700428 TIME_CHECK();
429 if (mModule == nullptr) return NO_INIT;
430 if (outStream == nullptr || config == nullptr) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000431 return BAD_VALUE;
432 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700433 constexpr bool isInput = false;
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800434 int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
435 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(handle));
436 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700437 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, isInput));
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800438 AudioDevice aidlDevice = VALUE_OR_RETURN_STATUS(
439 ::aidl::android::legacy2aidl_audio_device_AudioDevice(devices, address));
440 int32_t aidlOutputFlags = VALUE_OR_RETURN_STATUS(
441 ::aidl::android::legacy2aidl_audio_output_flags_t_int32_t_mask(flags));
442 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::output>(aidlOutputFlags);
443 AudioPortConfig mixPortConfig;
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700444 AudioPatch aidlPatch;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700445 Hal2AidlMapper::Cleanups cleanups(mMapperAccessor);
446 {
447 std::lock_guard l(mLock);
448 RETURN_STATUS_IF_ERROR(mMapper.prepareToOpenStream(aidlHandle, aidlDevice, aidlFlags,
449 AudioSource::SYS_RESERVED_INVALID /*only needed for input*/,
450 &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
451 }
452 *config = VALUE_OR_RETURN_STATUS(
453 ::aidl::android::aidl2legacy_AudioConfig_audio_config_t(aidlConfig, isInput));
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800454 ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamArguments args;
455 args.portConfigId = mixPortConfig.id;
Mikhail Naganovb0c55252023-02-08 16:59:41 -0800456 const bool isOffload = isBitPositionFlagSet(
457 aidlOutputFlags, AudioOutputFlags::COMPRESS_OFFLOAD);
458 std::shared_ptr<OutputStreamCallbackAidl> streamCb;
459 if (isOffload) {
460 streamCb = ndk::SharedRefBase::make<OutputStreamCallbackAidl>(this);
461 }
462 auto eventCb = ndk::SharedRefBase::make<OutputStreamEventCallbackAidl>(this);
463 if (isOffload) {
464 args.offloadInfo = aidlConfig.offloadInfo;
465 args.callback = streamCb;
466 }
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800467 args.bufferSizeFrames = aidlConfig.frameCount;
Mikhail Naganovb0c55252023-02-08 16:59:41 -0800468 args.eventCallback = eventCb;
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800469 ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamReturn ret;
470 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openOutputStream(args, &ret)));
Mikhail Naganov712d71b2023-02-23 17:57:16 -0800471 StreamContextAidl context(ret.desc, isOffload);
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800472 if (!context.isValid()) {
473 ALOGE("%s: Failed to created a valid stream context from the descriptor: %s",
474 __func__, ret.desc.toString().c_str());
475 return NO_INIT;
476 }
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700477 *outStream = sp<StreamOutHalAidl>::make(*config, std::move(context), aidlPatch.latenciesMs[0],
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700478 std::move(ret.stream), mVendorExt, this /*callbackBroker*/);
Mikhail Naganovb0c55252023-02-08 16:59:41 -0800479 void* cbCookie = (*outStream).get();
480 {
481 std::lock_guard l(mLock);
482 mCallbacks.emplace(cbCookie, Callbacks{});
Mikhail Naganov78f7f9a2023-11-16 15:49:23 -0800483 mMapper.addStream(*outStream, mixPortConfig.id, aidlPatch.id);
Mikhail Naganovb0c55252023-02-08 16:59:41 -0800484 }
485 if (streamCb) streamCb->setCookie(cbCookie);
486 eventCb->setCookie(cbCookie);
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800487 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000488 return OK;
489}
490
Mikhail Naganov31d46652023-01-10 18:29:25 +0000491status_t DeviceHalAidl::openInputStream(
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800492 audio_io_handle_t handle, audio_devices_t devices,
493 struct audio_config* config, audio_input_flags_t flags,
494 const char* address, audio_source_t source,
495 audio_devices_t outputDevice, const char* outputDeviceAddress,
Mikhail Naganov31d46652023-01-10 18:29:25 +0000496 sp<StreamInHalInterface>* inStream) {
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800497 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700498 TIME_CHECK();
499 if (mModule == nullptr) return NO_INIT;
500 if (inStream == nullptr || config == nullptr) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000501 return BAD_VALUE;
502 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700503 constexpr bool isInput = true;
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800504 int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
505 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(handle));
506 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700507 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, isInput));
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800508 AudioDevice aidlDevice = VALUE_OR_RETURN_STATUS(
509 ::aidl::android::legacy2aidl_audio_device_AudioDevice(devices, address));
510 int32_t aidlInputFlags = VALUE_OR_RETURN_STATUS(
511 ::aidl::android::legacy2aidl_audio_input_flags_t_int32_t_mask(flags));
512 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::input>(aidlInputFlags);
513 AudioSource aidlSource = VALUE_OR_RETURN_STATUS(
514 ::aidl::android::legacy2aidl_audio_source_t_AudioSource(source));
515 AudioPortConfig mixPortConfig;
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700516 AudioPatch aidlPatch;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700517 Hal2AidlMapper::Cleanups cleanups(mMapperAccessor);
518 {
519 std::lock_guard l(mLock);
520 RETURN_STATUS_IF_ERROR(mMapper.prepareToOpenStream(
521 aidlHandle, aidlDevice, aidlFlags, aidlSource,
522 &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
523 }
524 *config = VALUE_OR_RETURN_STATUS(
525 ::aidl::android::aidl2legacy_AudioConfig_audio_config_t(aidlConfig, isInput));
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800526 ::aidl::android::hardware::audio::core::IModule::OpenInputStreamArguments args;
527 args.portConfigId = mixPortConfig.id;
528 RecordTrackMetadata aidlTrackMetadata{
529 .source = aidlSource, .gain = 1, .channelMask = aidlConfig.base.channelMask };
530 if (outputDevice != AUDIO_DEVICE_NONE) {
531 aidlTrackMetadata.destinationDevice = VALUE_OR_RETURN_STATUS(
532 ::aidl::android::legacy2aidl_audio_device_AudioDevice(
533 outputDevice, outputDeviceAddress));
534 }
535 args.sinkMetadata.tracks.push_back(std::move(aidlTrackMetadata));
536 args.bufferSizeFrames = aidlConfig.frameCount;
537 ::aidl::android::hardware::audio::core::IModule::OpenInputStreamReturn ret;
538 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openInputStream(args, &ret)));
Mikhail Naganov712d71b2023-02-23 17:57:16 -0800539 StreamContextAidl context(ret.desc, false /*isAsynchronous*/);
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800540 if (!context.isValid()) {
541 ALOGE("%s: Failed to created a valid stream context from the descriptor: %s",
542 __func__, ret.desc.toString().c_str());
543 return NO_INIT;
544 }
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700545 *inStream = sp<StreamInHalAidl>::make(*config, std::move(context), aidlPatch.latenciesMs[0],
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700546 std::move(ret.stream), mVendorExt, this /*micInfoProvider*/);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700547 {
548 std::lock_guard l(mLock);
Mikhail Naganov78f7f9a2023-11-16 15:49:23 -0800549 mMapper.addStream(*inStream, mixPortConfig.id, aidlPatch.id);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700550 }
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800551 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000552 return OK;
553}
554
555status_t DeviceHalAidl::supportsAudioPatches(bool* supportsPatches) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700556 if (supportsPatches == nullptr) {
557 return BAD_VALUE;
558 }
Shunkai Yao51202502022-12-12 06:11:46 +0000559 *supportsPatches = true;
560 return OK;
561}
562
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800563status_t DeviceHalAidl::createAudioPatch(unsigned int num_sources,
564 const struct audio_port_config* sources,
565 unsigned int num_sinks,
566 const struct audio_port_config* sinks,
567 audio_patch_handle_t* patch) {
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800568 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000569 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700570 if (mModule == nullptr) return NO_INIT;
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800571 if (num_sinks > AUDIO_PATCH_PORTS_MAX || num_sources > AUDIO_PATCH_PORTS_MAX ||
572 sources == nullptr || sinks == nullptr || patch == nullptr) {
573 return BAD_VALUE;
574 }
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800575 // When the patch handle (*patch) is AUDIO_PATCH_HANDLE_NONE, it means
576 // the framework wants to create a new patch. The handle has to be generated
577 // by the HAL. Since handles generated this way can only be unique within
578 // a HAL module, the framework generates a globally unique handle, and maps
579 // it on the <HAL module, patch handle> pair.
580 // When the patch handle is set, it meant the framework intends to update
581 // an existing patch.
582 //
583 // This behavior corresponds to HAL module behavior, with the only difference
584 // that the HAL module uses `int32_t` for patch IDs. The following assert ensures
585 // that both the framework and the HAL use the same value for "no ID":
586 static_assert(AUDIO_PATCH_HANDLE_NONE == 0);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700587 int32_t aidlPatchId = static_cast<int32_t>(*patch);
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800588
589 // Upon conversion, mix port configs contain audio configuration, while
590 // device port configs contain device address. This data is used to find
591 // or create HAL configs.
592 std::vector<AudioPortConfig> aidlSources, aidlSinks;
593 for (unsigned int i = 0; i < num_sources; ++i) {
594 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
595 sources[i].role, sources[i].type)) ==
596 ::aidl::android::AudioPortDirection::INPUT;
597 aidlSources.push_back(VALUE_OR_RETURN_STATUS(
598 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
599 sources[i], isInput, 0)));
600 }
601 for (unsigned int i = 0; i < num_sinks; ++i) {
602 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
603 sinks[i].role, sinks[i].type)) ==
604 ::aidl::android::AudioPortDirection::INPUT;
605 aidlSinks.push_back(VALUE_OR_RETURN_STATUS(
606 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
607 sinks[i], isInput, 0)));
608 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700609 Hal2AidlMapper::Cleanups cleanups(mMapperAccessor);
610 {
611 std::lock_guard l(mLock);
612 RETURN_STATUS_IF_ERROR(mMapper.createOrUpdatePatch(
613 aidlSources, aidlSinks, &aidlPatchId, &cleanups));
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800614 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700615 *patch = static_cast<audio_patch_handle_t>(aidlPatchId);
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800616 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000617 return OK;
618}
619
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800620status_t DeviceHalAidl::releaseAudioPatch(audio_patch_handle_t patch) {
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800621 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000622 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700623 if (mModule == nullptr) return NO_INIT;
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800624 static_assert(AUDIO_PATCH_HANDLE_NONE == 0);
625 if (patch == AUDIO_PATCH_HANDLE_NONE) {
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800626 return BAD_VALUE;
627 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700628 std::lock_guard l(mLock);
629 RETURN_STATUS_IF_ERROR(mMapper.releaseAudioPatch(static_cast<int32_t>(patch)));
Shunkai Yao51202502022-12-12 06:11:46 +0000630 return OK;
631}
632
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700633status_t DeviceHalAidl::getAudioPort(struct audio_port* port) {
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700634 if (port == nullptr) {
635 return BAD_VALUE;
636 }
637 audio_port_v7 portV7;
638 audio_populate_audio_port_v7(port, &portV7);
639 RETURN_STATUS_IF_ERROR(getAudioPort(&portV7));
640 return audio_populate_audio_port(&portV7, port) ? OK : BAD_VALUE;
641}
642
643status_t DeviceHalAidl::getAudioPort(struct audio_port_v7 *port) {
644 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
645 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700646 if (mModule == nullptr) return NO_INIT;
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700647 if (port == nullptr) {
648 return BAD_VALUE;
649 }
650 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(port->role, port->type)) ==
651 ::aidl::android::AudioPortDirection::INPUT;
652 auto aidlPort = VALUE_OR_RETURN_STATUS(
653 ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
654 if (aidlPort.ext.getTag() != AudioPortExt::device) {
655 ALOGE("%s: provided port is not a device port (module %s): %s",
656 __func__, mInstance.c_str(), aidlPort.toString().c_str());
657 return BAD_VALUE;
658 }
659 const auto& matchDevice = aidlPort.ext.get<AudioPortExt::device>().device;
660 // It seems that we don't have to call HAL since all valid ports have been added either
661 // during initialization, or while handling connection of an external device.
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700662 const int32_t fwkId = aidlPort.id;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700663 {
664 std::lock_guard l(mLock);
665 RETURN_STATUS_IF_ERROR(mMapper.getAudioPortCached(matchDevice, &aidlPort));
666 }
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700667 aidlPort.id = fwkId;
668 *port = VALUE_OR_RETURN_STATUS(::aidl::android::aidl2legacy_AudioPort_audio_port_v7(
669 aidlPort, isInput));
670 return OK;
671}
672
jiabin12537fc2023-10-12 17:56:08 +0000673status_t DeviceHalAidl::getAudioMixPort(const struct audio_port_v7 *devicePort,
674 struct audio_port_v7 *mixPort) {
675 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700676 TIME_CHECK();
677 if (mModule == nullptr) return NO_INIT;
678 if (devicePort == nullptr || mixPort == nullptr ||
679 devicePort->type != AUDIO_PORT_TYPE_DEVICE || mixPort->type != AUDIO_PORT_TYPE_MIX) {
jiabin12537fc2023-10-12 17:56:08 +0000680 return BAD_VALUE;
681 }
682 const int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
683 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(mixPort->ext.mix.handle));
jiabin12537fc2023-10-12 17:56:08 +0000684 AudioPort port;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700685 {
686 std::lock_guard l(mLock);
687 RETURN_STATUS_IF_ERROR(mMapper.getAudioMixPort(aidlHandle, &port));
jiabin12537fc2023-10-12 17:56:08 +0000688 }
689 const bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
690 mixPort->role, mixPort->type)) == ::aidl::android::AudioPortDirection::INPUT;
691 *mixPort = VALUE_OR_RETURN_STATUS(::aidl::android::aidl2legacy_AudioPort_audio_port_v7(
692 port, isInput));
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700693 return OK;
jiabin12537fc2023-10-12 17:56:08 +0000694}
695
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700696status_t DeviceHalAidl::setAudioPortConfig(const struct audio_port_config* config) {
697 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
698 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700699 if (mModule == nullptr) return NO_INIT;
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700700 if (config == nullptr) {
701 return BAD_VALUE;
702 }
703 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
704 config->role, config->type)) == ::aidl::android::AudioPortDirection::INPUT;
705 AudioPortConfig requestedPortConfig = VALUE_OR_RETURN_STATUS(
706 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
707 *config, isInput, 0 /*portId*/));
708 AudioPortConfig portConfig;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700709 std::lock_guard l(mLock);
710 return mMapper.findOrCreatePortConfig(
711 requestedPortConfig, std::set<int32_t>(), &portConfig);
Shunkai Yao51202502022-12-12 06:11:46 +0000712}
713
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800714MicrophoneInfoProvider::Info const* DeviceHalAidl::getMicrophoneInfo() {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700715 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
716 TIME_CHECK();
717 if (!mModule) return {};
718 std::lock_guard l(mLock);
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800719 if (mMicrophones.status == Microphones::Status::UNKNOWN) {
720 TIME_CHECK();
721 std::vector<MicrophoneInfo> aidlInfo;
722 status_t status = statusTFromBinderStatus(mModule->getMicrophones(&aidlInfo));
723 if (status == OK) {
724 mMicrophones.status = Microphones::Status::QUERIED;
725 mMicrophones.info = std::move(aidlInfo);
726 } else if (status == INVALID_OPERATION) {
727 mMicrophones.status = Microphones::Status::NOT_SUPPORTED;
728 } else {
729 ALOGE("%s: Unexpected status from 'IModule.getMicrophones': %d", __func__, status);
730 return {};
731 }
732 }
733 if (mMicrophones.status == Microphones::Status::QUERIED) {
734 return &mMicrophones.info;
735 }
736 return {}; // NOT_SUPPORTED
737}
738
Shunkai Yao51202502022-12-12 06:11:46 +0000739status_t DeviceHalAidl::getMicrophones(
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800740 std::vector<audio_microphone_characteristic_t>* microphones) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700741 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
742 TIME_CHECK();
743 if (mModule == nullptr) return NO_INIT;
744 if (microphones == nullptr) {
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800745 return BAD_VALUE;
746 }
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800747 auto staticInfo = getMicrophoneInfo();
748 if (!staticInfo) return INVALID_OPERATION;
749 std::vector<MicrophoneDynamicInfo> emptyDynamicInfo;
750 emptyDynamicInfo.reserve(staticInfo->size());
751 std::transform(staticInfo->begin(), staticInfo->end(), std::back_inserter(emptyDynamicInfo),
752 [](const auto& info) { return MicrophoneDynamicInfo{ .id = info.id }; });
753 *microphones = VALUE_OR_RETURN_STATUS(
754 ::aidl::android::convertContainers<std::vector<audio_microphone_characteristic_t>>(
755 *staticInfo, emptyDynamicInfo,
756 ::aidl::android::aidl2legacy_MicrophoneInfos_audio_microphone_characteristic_t)
757 );
Shunkai Yao51202502022-12-12 06:11:46 +0000758 return OK;
759}
760
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700761status_t DeviceHalAidl::addDeviceEffect(
762 const struct audio_port_config *device, sp<EffectHalInterface> effect) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700763 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700764 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700765 if (mModule == nullptr) return NO_INIT;
766 if (device == nullptr || effect == nullptr) {
Shunkai Yao51202502022-12-12 06:11:46 +0000767 return BAD_VALUE;
768 }
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700769 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
770 device->role, device->type)) == ::aidl::android::AudioPortDirection::INPUT;
771 auto requestedPortConfig = VALUE_OR_RETURN_STATUS(
772 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
773 *device, isInput, 0));
774 if (requestedPortConfig.ext.getTag() != AudioPortExt::Tag::device) {
775 ALOGE("%s: provided port config is not a device port config: %s",
776 __func__, requestedPortConfig.toString().c_str());
777 return BAD_VALUE;
778 }
779 AudioPortConfig devicePortConfig;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700780 Hal2AidlMapper::Cleanups cleanups(mMapperAccessor);
781 {
782 std::lock_guard l(mLock);
783 RETURN_STATUS_IF_ERROR(mMapper.findOrCreatePortConfig(
784 requestedPortConfig, {} /*destinationPortIds*/, &devicePortConfig, &cleanups));
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700785 }
786 auto aidlEffect = sp<effect::EffectHalAidl>::cast(effect);
787 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->addDeviceEffect(
788 devicePortConfig.id, aidlEffect->getIEffect())));
789 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000790 return OK;
791}
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700792status_t DeviceHalAidl::removeDeviceEffect(
793 const struct audio_port_config *device, sp<EffectHalInterface> effect) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700794 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700795 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700796 if (mModule == nullptr) return NO_INIT;
797 if (device == nullptr || effect == nullptr) {
Shunkai Yao51202502022-12-12 06:11:46 +0000798 return BAD_VALUE;
799 }
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700800 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
801 device->role, device->type)) == ::aidl::android::AudioPortDirection::INPUT;
802 auto requestedPortConfig = VALUE_OR_RETURN_STATUS(
803 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
804 *device, isInput, 0));
805 if (requestedPortConfig.ext.getTag() != AudioPortExt::Tag::device) {
806 ALOGE("%s: provided port config is not a device port config: %s",
807 __func__, requestedPortConfig.toString().c_str());
808 return BAD_VALUE;
809 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700810 AudioPortConfig devicePortConfig;
811 {
812 std::lock_guard l(mLock);
813 RETURN_STATUS_IF_ERROR(mMapper.findPortConfig(
814 requestedPortConfig.ext.get<AudioPortExt::Tag::device>().device,
815 &devicePortConfig));
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700816 }
817 auto aidlEffect = sp<effect::EffectHalAidl>::cast(effect);
818 return statusTFromBinderStatus(mModule->removeDeviceEffect(
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700819 devicePortConfig.id, aidlEffect->getIEffect()));
Shunkai Yao51202502022-12-12 06:11:46 +0000820}
821
822status_t DeviceHalAidl::getMmapPolicyInfos(
David Li9cf5e622023-03-21 00:51:10 +0800823 media::audio::common::AudioMMapPolicyType policyType,
824 std::vector<media::audio::common::AudioMMapPolicyInfo>* policyInfos) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700825 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000826 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700827 if (mModule == nullptr) return NO_INIT;
Mikhail Naganovbfbb75b2023-04-21 18:48:16 -0700828 AudioMMapPolicyType mmapPolicyType = VALUE_OR_RETURN_STATUS(
829 cpp2ndk_AudioMMapPolicyType(policyType));
David Li9cf5e622023-03-21 00:51:10 +0800830
831 std::vector<AudioMMapPolicyInfo> mmapPolicyInfos;
832
833 if (status_t status = statusTFromBinderStatus(
834 mModule->getMmapPolicyInfos(mmapPolicyType, &mmapPolicyInfos)); status != OK) {
835 return status;
836 }
837
838 *policyInfos = VALUE_OR_RETURN_STATUS(
839 convertContainer<std::vector<media::audio::common::AudioMMapPolicyInfo>>(
840 mmapPolicyInfos, ndk2cpp_AudioMMapPolicyInfo));
Shunkai Yao51202502022-12-12 06:11:46 +0000841 return OK;
842}
843
844int32_t DeviceHalAidl::getAAudioMixerBurstCount() {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700845 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000846 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700847 if (mModule == nullptr) return NO_INIT;
David Li9cf5e622023-03-21 00:51:10 +0800848 int32_t mixerBurstCount = 0;
849 if (mModule->getAAudioMixerBurstCount(&mixerBurstCount).isOk()) {
850 return mixerBurstCount;
851 }
852 return 0;
Shunkai Yao51202502022-12-12 06:11:46 +0000853}
854
855int32_t DeviceHalAidl::getAAudioHardwareBurstMinUsec() {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700856 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000857 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700858 if (mModule == nullptr) return NO_INIT;
David Li9cf5e622023-03-21 00:51:10 +0800859 int32_t hardwareBurstMinUsec = 0;
860 if (mModule->getAAudioHardwareBurstMinUsec(&hardwareBurstMinUsec).isOk()) {
861 return hardwareBurstMinUsec;
862 }
863 return 0;
Shunkai Yao51202502022-12-12 06:11:46 +0000864}
865
866error::Result<audio_hw_sync_t> DeviceHalAidl::getHwAvSync() {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700867 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000868 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700869 if (mModule == nullptr) return NO_INIT;
Mikhail Naganov08a62ab2023-03-14 17:11:51 -0700870 int32_t aidlHwAvSync;
871 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->generateHwAvSyncId(&aidlHwAvSync)));
872 return VALUE_OR_RETURN_STATUS(
873 ::aidl::android::aidl2legacy_int32_t_audio_hw_sync_t(aidlHwAvSync));
Shunkai Yao51202502022-12-12 06:11:46 +0000874}
875
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000876status_t DeviceHalAidl::dump(int fd, const Vector<String16>& args) {
877 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700878 if (mModule == nullptr) return NO_INIT;
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000879 return mModule->dump(fd, Args(args).args(), args.size());
David Li9cf5e622023-03-21 00:51:10 +0800880}
Shunkai Yao51202502022-12-12 06:11:46 +0000881
Eric Laurent8ed6d792023-06-29 11:44:54 +0200882status_t DeviceHalAidl::supportsBluetoothVariableLatency(bool* supports) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700883 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000884 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700885 if (mModule == nullptr) return NO_INIT;
Mikhail Naganov3ac95c92023-04-12 13:14:30 -0700886 if (supports == nullptr) {
887 return BAD_VALUE;
888 }
889 return statusTFromBinderStatus(mModule->supportsVariableLatency(supports));
Shunkai Yao51202502022-12-12 06:11:46 +0000890}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000891
Vlad Popa03bd5bc2023-01-17 16:16:51 +0100892status_t DeviceHalAidl::getSoundDoseInterface(const std::string& module,
893 ::ndk::SpAIBinder* soundDoseBinder) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700894 if (soundDoseBinder == nullptr) {
895 return BAD_VALUE;
896 }
Vlad Popa03bd5bc2023-01-17 16:16:51 +0100897 if (mSoundDose == nullptr) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700898 ALOGE("%s failed to retrieve the sound dose interface for module %s",
899 __func__, module.c_str());
900 return BAD_VALUE;
Vlad Popa03bd5bc2023-01-17 16:16:51 +0100901 }
Vlad Popae1f33902023-10-30 19:48:25 -0700902
903 if (mSoundDose == nullptr) {
904 ALOGE("%s failed to return the sound dose interface for module %s: not implemented",
905 __func__,
906 module.c_str());
907 return NO_INIT;
908 }
909
Vlad Popa03bd5bc2023-01-17 16:16:51 +0100910 *soundDoseBinder = mSoundDose->asBinder();
911 ALOGI("%s using audio AIDL HAL sound dose interface", __func__);
Vlad Popa03bd5bc2023-01-17 16:16:51 +0100912 return OK;
913}
914
jiabinc0048632023-04-27 22:04:31 +0000915status_t DeviceHalAidl::prepareToDisconnectExternalDevice(const struct audio_port_v7* port) {
916 // There is not AIDL API defined for `prepareToDisconnectExternalDevice`.
917 // Call `setConnectedState` instead.
918 // TODO(b/279824103): call prepareToDisconnectExternalDevice when it is added.
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700919 RETURN_STATUS_IF_ERROR(setConnectedState(port, false /*connected*/));
920 std::lock_guard l(mLock);
921 mDeviceDisconnectionNotified.insert(port->id);
Mikhail Naganov66907492023-09-11 17:22:03 -0700922 // Return that there was no error as otherwise the disconnection procedure will not be
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700923 // considered complete for upper layers, and 'setConnectedState' will not be called again
924 return OK;
jiabinc0048632023-04-27 22:04:31 +0000925}
926
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700927status_t DeviceHalAidl::setConnectedState(const struct audio_port_v7 *port, bool connected) {
Mikhail Naganovae9063d2023-11-07 16:43:51 -0800928 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700929 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700930 if (mModule == nullptr) return NO_INIT;
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700931 if (port == nullptr) {
932 return BAD_VALUE;
933 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700934 if (!connected) {
935 std::lock_guard l(mLock);
936 if (mDeviceDisconnectionNotified.erase(port->id) > 0) {
937 // For device disconnection, APM will first call `prepareToDisconnectExternalDevice`
938 // and then call `setConnectedState`. However, there is no API for
939 // `prepareToDisconnectExternalDevice` yet. In that case, `setConnectedState` will be
940 // called when calling `prepareToDisconnectExternalDevice`. Do not call to the HAL if
941 // previous call is successful. Also remove the cache here to avoid a large cache after
942 // a long run.
943 return OK;
944 }
jiabinc0048632023-04-27 22:04:31 +0000945 }
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700946 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(port->role, port->type)) ==
947 ::aidl::android::AudioPortDirection::INPUT;
948 AudioPort aidlPort = VALUE_OR_RETURN_STATUS(
949 ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
950 if (aidlPort.ext.getTag() != AudioPortExt::device) {
951 ALOGE("%s: provided port is not a device port (module %s): %s",
952 __func__, mInstance.c_str(), aidlPort.toString().c_str());
953 return BAD_VALUE;
954 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700955 std::lock_guard l(mLock);
956 return mMapper.setDevicePortConnectedState(aidlPort, connected);
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700957}
958
959status_t DeviceHalAidl::setSimulateDeviceConnections(bool enabled) {
960 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700961 if (mModule == nullptr) return NO_INIT;
962 {
963 std::lock_guard l(mLock);
964 mMapper.resetUnusedPatchesAndPortConfigs();
965 }
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700966 ModuleDebug debug{ .simulateDeviceConnections = enabled };
967 status_t status = statusTFromBinderStatus(mModule->setModuleDebug(debug));
968 // This is important to log as it affects HAL behavior.
969 if (status == OK) {
970 ALOGI("%s: set enabled: %d", __func__, enabled);
971 } else {
972 ALOGW("%s: set enabled to %d failed: %d", __func__, enabled, status);
973 }
974 return status;
975}
976
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700977status_t DeviceHalAidl::filterAndRetrieveBtA2dpParameters(
978 AudioParameter &keys, AudioParameter *result) {
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700979 if (String8 key = String8(AudioParameter::keyReconfigA2dpSupported); keys.containsKey(key)) {
980 keys.remove(key);
David Li8bb0cea2023-11-03 12:46:38 +0800981 if (mBluetoothA2dp != nullptr) {
982 bool supports;
983 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
984 mBluetoothA2dp->supportsOffloadReconfiguration(&supports)));
985 result->addInt(key, supports ? 1 : 0);
986 } else {
987 ALOGI("%s: no IBluetoothA2dp on %s", __func__, mInstance.c_str());
988 result->addInt(key, 0);
989 }
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700990 }
991 return OK;
992}
993
Eric Laurent7e3c0832023-11-30 15:04:50 +0100994status_t DeviceHalAidl::filterAndRetrieveBtLeParameters(
995 AudioParameter &keys, AudioParameter *result) {
996 if (String8 key = String8(AudioParameter::keyReconfigLeSupported); keys.containsKey(key)) {
997 keys.remove(key);
998 if (mBluetoothLe != nullptr) {
999 bool supports;
1000 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
1001 mBluetoothLe->supportsOffloadReconfiguration(&supports)));
1002 result->addInt(key, supports ? 1 : 0);
1003 } else {
1004 ALOGI("%s: no mBluetoothLe on %s", __func__, mInstance.c_str());
1005 result->addInt(key, 0);
1006 }
1007 }
1008 return OK;
1009}
1010
Mikhail Naganov27382bb2023-04-27 18:14:15 -07001011status_t DeviceHalAidl::filterAndUpdateBtA2dpParameters(AudioParameter &parameters) {
Mikhail Naganov27382bb2023-04-27 18:14:15 -07001012 std::optional<bool> a2dpEnabled;
Mikhail Naganove7a26ad2023-05-25 17:36:48 -07001013 std::optional<std::vector<VendorParameter>> reconfigureOffload;
Mikhail Naganov27382bb2023-04-27 18:14:15 -07001014 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1015 parameters, String8(AudioParameter::keyBtA2dpSuspended),
1016 [&a2dpEnabled](const String8& trueOrFalse) {
1017 if (trueOrFalse == AudioParameter::valueTrue) {
1018 a2dpEnabled = false; // 'suspended' == true
1019 return OK;
1020 } else if (trueOrFalse == AudioParameter::valueFalse) {
1021 a2dpEnabled = true; // 'suspended' == false
1022 return OK;
1023 }
1024 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1025 AudioParameter::keyBtA2dpSuspended, trueOrFalse.c_str());
1026 return BAD_VALUE;
1027 }));
Mikhail Naganove7a26ad2023-05-25 17:36:48 -07001028 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1029 parameters, String8(AudioParameter::keyReconfigA2dp),
1030 [&](const String8& value) -> status_t {
1031 if (mVendorExt != nullptr) {
1032 std::vector<VendorParameter> result;
1033 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
1034 mVendorExt->parseBluetoothA2dpReconfigureOffload(
1035 std::string(value.c_str()), &result)));
1036 reconfigureOffload = std::move(result);
1037 } else {
1038 reconfigureOffload = std::vector<VendorParameter>();
1039 }
1040 return OK;
1041 }));
Mikhail Naganov27382bb2023-04-27 18:14:15 -07001042 if (mBluetoothA2dp != nullptr && a2dpEnabled.has_value()) {
1043 return statusTFromBinderStatus(mBluetoothA2dp->setEnabled(a2dpEnabled.value()));
1044 }
Mikhail Naganove7a26ad2023-05-25 17:36:48 -07001045 if (mBluetoothA2dp != nullptr && reconfigureOffload.has_value()) {
1046 return statusTFromBinderStatus(mBluetoothA2dp->reconfigureOffload(
1047 reconfigureOffload.value()));
1048 }
Mikhail Naganov27382bb2023-04-27 18:14:15 -07001049 return OK;
1050}
1051
1052status_t DeviceHalAidl::filterAndUpdateBtHfpParameters(AudioParameter &parameters) {
Mikhail Naganov27382bb2023-04-27 18:14:15 -07001053 IBluetooth::HfpConfig hfpConfig;
1054 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1055 parameters, String8(AudioParameter::keyBtHfpEnable),
1056 [&hfpConfig](const String8& trueOrFalse) {
1057 if (trueOrFalse == AudioParameter::valueTrue) {
1058 hfpConfig.isEnabled = Boolean{ .value = true };
1059 return OK;
1060 } else if (trueOrFalse == AudioParameter::valueFalse) {
1061 hfpConfig.isEnabled = Boolean{ .value = false };
1062 return OK;
1063 }
1064 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1065 AudioParameter::keyBtHfpEnable, trueOrFalse.c_str());
1066 return BAD_VALUE;
1067 }));
1068 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
1069 parameters, String8(AudioParameter::keyBtHfpSamplingRate),
1070 [&hfpConfig](int sampleRate) {
1071 return sampleRate > 0 ?
1072 hfpConfig.sampleRate = Int{ .value = sampleRate }, OK : BAD_VALUE;
1073 }));
1074 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
1075 parameters, String8(AudioParameter::keyBtHfpVolume),
1076 [&hfpConfig](int volume0to15) {
1077 if (volume0to15 >= 0 && volume0to15 <= 15) {
1078 hfpConfig.volume = Float{ .value = volume0to15 / 15.0f };
1079 return OK;
1080 }
1081 return BAD_VALUE;
1082 }));
1083 if (mBluetooth != nullptr && hfpConfig != IBluetooth::HfpConfig{}) {
1084 IBluetooth::HfpConfig newHfpConfig;
1085 return statusTFromBinderStatus(mBluetooth->setHfpConfig(hfpConfig, &newHfpConfig));
1086 }
1087 return OK;
1088}
1089
1090status_t DeviceHalAidl::filterAndUpdateBtLeParameters(AudioParameter &parameters) {
Mikhail Naganov27382bb2023-04-27 18:14:15 -07001091 std::optional<bool> leEnabled;
Eric Laurent7e3c0832023-11-30 15:04:50 +01001092 std::optional<std::vector<VendorParameter>> reconfigureOffload;
Mikhail Naganov27382bb2023-04-27 18:14:15 -07001093 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1094 parameters, String8(AudioParameter::keyBtLeSuspended),
1095 [&leEnabled](const String8& trueOrFalse) {
1096 if (trueOrFalse == AudioParameter::valueTrue) {
1097 leEnabled = false; // 'suspended' == true
1098 return OK;
1099 } else if (trueOrFalse == AudioParameter::valueFalse) {
1100 leEnabled = true; // 'suspended' == false
1101 return OK;
1102 }
1103 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1104 AudioParameter::keyBtLeSuspended, trueOrFalse.c_str());
1105 return BAD_VALUE;
1106 }));
Eric Laurent7e3c0832023-11-30 15:04:50 +01001107 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1108 parameters, String8(AudioParameter::keyReconfigLe),
1109 [&](const String8& value) -> status_t {
1110 if (mVendorExt != nullptr) {
1111 std::vector<VendorParameter> result;
1112 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
1113 mVendorExt->parseBluetoothLeReconfigureOffload(
1114 std::string(value.c_str()), &result)));
1115 reconfigureOffload = std::move(result);
1116 } else {
1117 reconfigureOffload = std::vector<VendorParameter>();
1118 }
1119 return OK;
1120 }));
Mikhail Naganov27382bb2023-04-27 18:14:15 -07001121 if (mBluetoothLe != nullptr && leEnabled.has_value()) {
1122 return statusTFromBinderStatus(mBluetoothLe->setEnabled(leEnabled.value()));
1123 }
Eric Laurent7e3c0832023-11-30 15:04:50 +01001124 if (mBluetoothLe != nullptr && reconfigureOffload.has_value()) {
1125 return statusTFromBinderStatus(mBluetoothLe->reconfigureOffload(
1126 reconfigureOffload.value()));
1127 }
Mikhail Naganov27382bb2023-04-27 18:14:15 -07001128 return OK;
1129}
1130
1131status_t DeviceHalAidl::filterAndUpdateBtScoParameters(AudioParameter &parameters) {
Mikhail Naganov27382bb2023-04-27 18:14:15 -07001132 IBluetooth::ScoConfig scoConfig;
1133 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1134 parameters, String8(AudioParameter::keyBtSco),
1135 [&scoConfig](const String8& onOrOff) {
1136 if (onOrOff == AudioParameter::valueOn) {
1137 scoConfig.isEnabled = Boolean{ .value = true };
1138 return OK;
1139 } else if (onOrOff == AudioParameter::valueOff) {
1140 scoConfig.isEnabled = Boolean{ .value = false };
1141 return OK;
1142 }
1143 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1144 AudioParameter::keyBtSco, onOrOff.c_str());
1145 return BAD_VALUE;
1146 }));
1147 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1148 parameters, String8(AudioParameter::keyBtScoHeadsetName),
1149 [&scoConfig](const String8& name) {
1150 scoConfig.debugName = name;
1151 return OK;
1152 }));
1153 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1154 parameters, String8(AudioParameter::keyBtNrec),
1155 [&scoConfig](const String8& onOrOff) {
1156 if (onOrOff == AudioParameter::valueOn) {
1157 scoConfig.isNrecEnabled = Boolean{ .value = true };
1158 return OK;
1159 } else if (onOrOff == AudioParameter::valueOff) {
1160 scoConfig.isNrecEnabled = Boolean{ .value = false };
1161 return OK;
1162 }
1163 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1164 AudioParameter::keyBtNrec, onOrOff.c_str());
1165 return BAD_VALUE;
1166 }));
1167 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1168 parameters, String8(AudioParameter::keyBtScoWb),
1169 [&scoConfig](const String8& onOrOff) {
1170 if (onOrOff == AudioParameter::valueOn) {
1171 scoConfig.mode = IBluetooth::ScoConfig::Mode::SCO_WB;
1172 return OK;
1173 } else if (onOrOff == AudioParameter::valueOff) {
1174 scoConfig.mode = IBluetooth::ScoConfig::Mode::SCO;
1175 return OK;
1176 }
1177 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1178 AudioParameter::keyBtScoWb, onOrOff.c_str());
1179 return BAD_VALUE;
1180 }));
1181 if (mBluetooth != nullptr && scoConfig != IBluetooth::ScoConfig{}) {
1182 IBluetooth::ScoConfig newScoConfig;
1183 return statusTFromBinderStatus(mBluetooth->setScoConfig(scoConfig, &newScoConfig));
1184 }
1185 return OK;
1186}
1187
Mikhail Naganove92c34b2023-05-31 14:24:48 -07001188status_t DeviceHalAidl::filterAndUpdateScreenParameters(AudioParameter &parameters) {
Mikhail Naganove92c34b2023-05-31 14:24:48 -07001189 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1190 parameters, String8(AudioParameter::keyScreenState),
1191 [&](const String8& onOrOff) -> status_t {
1192 std::optional<bool> isTurnedOn;
1193 if (onOrOff == AudioParameter::valueOn) {
1194 isTurnedOn = true;
1195 } else if (onOrOff == AudioParameter::valueOff) {
1196 isTurnedOn = false;
1197 }
1198 if (!isTurnedOn.has_value()) {
1199 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1200 AudioParameter::keyScreenState, onOrOff.c_str());
1201 return BAD_VALUE;
1202 }
1203 return statusTFromBinderStatus(
1204 mModule->updateScreenState(isTurnedOn.value()));
1205 }));
1206 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
1207 parameters, String8(AudioParameter::keyScreenRotation),
1208 [&](int rotationDegrees) -> status_t {
1209 IModule::ScreenRotation rotation;
1210 switch (rotationDegrees) {
1211 case 0: rotation = IModule::ScreenRotation::DEG_0; break;
1212 case 90: rotation = IModule::ScreenRotation::DEG_90; break;
1213 case 180: rotation = IModule::ScreenRotation::DEG_180; break;
1214 case 270: rotation = IModule::ScreenRotation::DEG_270; break;
1215 default:
1216 ALOGE("setParameters: parameter key \"%s\" has invalid value %d",
1217 AudioParameter::keyScreenRotation, rotationDegrees);
1218 return BAD_VALUE;
1219 }
1220 return statusTFromBinderStatus(mModule->updateScreenRotation(rotation));
1221 }));
1222 return OK;
1223}
1224
Mikhail Naganovb9a81312023-07-18 13:55:34 -07001225status_t DeviceHalAidl::filterAndUpdateTelephonyParameters(AudioParameter &parameters) {
Mikhail Naganovb9a81312023-07-18 13:55:34 -07001226 using TtyMode = ITelephony::TelecomConfig::TtyMode;
1227 ITelephony::TelecomConfig telConfig;
1228 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1229 parameters, String8(AudioParameter::keyTtyMode),
1230 [&telConfig](const String8& mode) {
1231 if (mode == AudioParameter::valueTtyModeOff) {
1232 telConfig.ttyMode = TtyMode::OFF;
1233 return OK;
1234 } else if (mode == AudioParameter::valueTtyModeFull) {
1235 telConfig.ttyMode = TtyMode::FULL;
1236 return OK;
1237 } else if (mode == AudioParameter::valueTtyModeHco) {
1238 telConfig.ttyMode = TtyMode::HCO;
1239 return OK;
1240 } else if (mode == AudioParameter::valueTtyModeVco) {
1241 telConfig.ttyMode = TtyMode::VCO;
1242 return OK;
1243 }
1244 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1245 AudioParameter::keyTtyMode, mode.c_str());
1246 return BAD_VALUE;
1247 }));
1248 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1249 parameters, String8(AudioParameter::keyHacSetting),
1250 [&telConfig](const String8& onOrOff) {
1251 if (onOrOff == AudioParameter::valueHacOn) {
1252 telConfig.isHacEnabled = Boolean{ .value = true };
1253 return OK;
1254 } else if (onOrOff == AudioParameter::valueHacOff) {
1255 telConfig.isHacEnabled = Boolean{ .value = false };
1256 return OK;
1257 }
1258 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1259 AudioParameter::keyHacSetting, onOrOff.c_str());
1260 return BAD_VALUE;
1261 }));
1262 if (mTelephony != nullptr && telConfig != ITelephony::TelecomConfig{}) {
1263 ITelephony::TelecomConfig newTelConfig;
1264 return statusTFromBinderStatus(
1265 mTelephony->setTelecomConfig(telConfig, &newTelConfig));
1266 }
1267 return OK;
1268}
1269
Mikhail Naganovb0c55252023-02-08 16:59:41 -08001270void DeviceHalAidl::clearCallbacks(void* cookie) {
1271 std::lock_guard l(mLock);
1272 mCallbacks.erase(cookie);
1273}
1274
1275sp<StreamOutHalInterfaceCallback> DeviceHalAidl::getStreamOutCallback(void* cookie) {
1276 return getCallbackImpl(cookie, &Callbacks::out);
1277}
1278
1279void DeviceHalAidl::setStreamOutCallback(
1280 void* cookie, const sp<StreamOutHalInterfaceCallback>& cb) {
1281 setCallbackImpl(cookie, &Callbacks::out, cb);
1282}
1283
1284sp<StreamOutHalInterfaceEventCallback> DeviceHalAidl::getStreamOutEventCallback(
1285 void* cookie) {
1286 return getCallbackImpl(cookie, &Callbacks::event);
1287}
1288
1289void DeviceHalAidl::setStreamOutEventCallback(
1290 void* cookie, const sp<StreamOutHalInterfaceEventCallback>& cb) {
1291 setCallbackImpl(cookie, &Callbacks::event, cb);
1292}
1293
1294sp<StreamOutHalInterfaceLatencyModeCallback> DeviceHalAidl::getStreamOutLatencyModeCallback(
1295 void* cookie) {
1296 return getCallbackImpl(cookie, &Callbacks::latency);
1297}
1298
1299void DeviceHalAidl::setStreamOutLatencyModeCallback(
1300 void* cookie, const sp<StreamOutHalInterfaceLatencyModeCallback>& cb) {
1301 setCallbackImpl(cookie, &Callbacks::latency, cb);
1302}
1303
1304template<class C>
1305sp<C> DeviceHalAidl::getCallbackImpl(void* cookie, wp<C> DeviceHalAidl::Callbacks::* field) {
1306 std::lock_guard l(mLock);
1307 if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
1308 return ((it->second).*field).promote();
1309 }
1310 return nullptr;
1311}
1312template<class C>
1313void DeviceHalAidl::setCallbackImpl(
1314 void* cookie, wp<C> DeviceHalAidl::Callbacks::* field, const sp<C>& cb) {
1315 std::lock_guard l(mLock);
1316 if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
1317 (it->second).*field = cb;
1318 }
1319}
1320
Mikhail Naganov31d46652023-01-10 18:29:25 +00001321} // namespace android