blob: 7575a6f36ef1839019e34e1413941821cc64166c [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>
Mikhail Naganov25bc9a22023-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 Naganov89a9f742023-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 Naganovccc82112023-04-27 18:14:15 -070039using aidl::android::media::audio::common::Boolean;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -080040using aidl::android::media::audio::common::AudioConfig;
41using aidl::android::media::audio::common::AudioDevice;
Mikhail Naganov89a9f742023-01-30 12:33:18 -080042using aidl::android::media::audio::common::AudioDeviceType;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -080043using aidl::android::media::audio::common::AudioIoFlags;
Mikhail Naganovdfd594e2023-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 Naganov5b1eed12023-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 Naganov5b1eed12023-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 Naganov5b1eed12023-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 Naganov5b1eed12023-01-25 11:29:11 -080063using aidl::android::hardware::audio::core::AudioPatch;
Mikhail Naganov289468a2023-03-29 10:06:15 -070064using aidl::android::hardware::audio::core::AudioRoute;
Mikhail Naganovccc82112023-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 Naganove93a0862023-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 Naganov5b1eed12023-01-25 11:29:11 -080075namespace {
76
Mikhail Naganovf83b9742023-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;
David Li9cf5e622023-03-21 00:51:10 +080086 return cpp;
87}
88
Mikhail Naganov1fba38c2023-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 Naganov5b1eed12023-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 Naganov1fba38c2023-05-03 17:45:36 -0700105 : ConversionHelperAidl("DeviceHalAidl"),
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700106 mInstance(instance), mModule(module), mVendorExt(vext),
Mikhail Naganovccc82112023-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 Naganov1fba38c2023-05-03 17:45:36 -0700113}
114
Mikhail Naganovf83b9742023-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 Naganovf83b9742023-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 Naganovf83b9742023-04-24 13:06:04 -0700123}
124
Mikhail Naganov1fba38c2023-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 Naganov1fba38c2023-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 Naganov1fba38c2023-05-03 17:45:36 -0700130 if (modes == nullptr) {
131 return BAD_VALUE;
132 }
Mikhail Naganov1fba38c2023-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 Naganov5b1eed12023-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 Naganov1fba38c2023-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 Naganov1fba38c2023-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 Naganovccc82112023-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 Naganovccc82112023-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 }
270 *values = result.toString();
271 return parseAndGetVendorParameters(mVendorExt, mModule, parameterKeys, values);
Shunkai Yao51202502022-12-12 06:11:46 +0000272}
273
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800274status_t DeviceHalAidl::getInputBufferSize(const struct audio_config* config, size_t* size) {
275 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800276 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700277 if (mModule == nullptr) return NO_INIT;
278 if (config == nullptr || size == nullptr) {
279 return BAD_VALUE;
280 }
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800281 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
282 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, true /*isInput*/));
283 AudioDevice aidlDevice;
284 aidlDevice.type.type = AudioDeviceType::IN_DEFAULT;
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800285 AudioSource aidlSource = AudioSource::DEFAULT;
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800286 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::input>(0);
287 AudioPortConfig mixPortConfig;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700288 Hal2AidlMapper::Cleanups cleanups(mMapperAccessor);
Mikhail Naganove93a0862023-03-15 17:06:59 -0700289 AudioPatch aidlPatch;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700290 {
291 std::lock_guard l(mLock);
292 RETURN_STATUS_IF_ERROR(mMapper.prepareToOpenStream(
293 0 /*handle*/, aidlDevice, aidlFlags, aidlSource,
294 &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
295 }
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800296 *size = aidlConfig.frameCount *
297 getFrameSizeInBytes(aidlConfig.base.format, aidlConfig.base.channelMask);
298 // Do not disarm cleanups to release temporary port configs.
299 return OK;
300}
301
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800302namespace {
303
304class StreamCallbackBase {
305 protected:
306 explicit StreamCallbackBase(const sp<CallbackBroker>& broker) : mBroker(broker) {}
307 public:
308 void* getCookie() const { return mCookie; }
309 void setCookie(void* cookie) { mCookie = cookie; }
310 sp<CallbackBroker> getBroker() const {
311 if (void* cookie = mCookie; cookie != nullptr) return mBroker.promote();
312 return nullptr;
313 }
314 private:
315 const wp<CallbackBroker> mBroker;
316 std::atomic<void*> mCookie;
317};
318
319template<class C>
320class StreamCallbackBaseHelper {
321 protected:
322 explicit StreamCallbackBaseHelper(const StreamCallbackBase& base) : mBase(base) {}
323 sp<C> getCb(const sp<CallbackBroker>& broker, void* cookie);
324 using CbRef = const sp<C>&;
325 ndk::ScopedAStatus runCb(const std::function<void(CbRef cb)>& f) {
326 if (auto cb = getCb(mBase.getBroker(), mBase.getCookie()); cb != nullptr) f(cb);
327 return ndk::ScopedAStatus::ok();
328 }
329 private:
330 const StreamCallbackBase& mBase;
331};
332
333template<>
334sp<StreamOutHalInterfaceCallback> StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>::getCb(
335 const sp<CallbackBroker>& broker, void* cookie) {
336 if (broker != nullptr) return broker->getStreamOutCallback(cookie);
337 return nullptr;
338}
339
340template<>
341sp<StreamOutHalInterfaceEventCallback>
342StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>::getCb(
343 const sp<CallbackBroker>& broker, void* cookie) {
344 if (broker != nullptr) return broker->getStreamOutEventCallback(cookie);
345 return nullptr;
346}
347
348template<>
349sp<StreamOutHalInterfaceLatencyModeCallback>
350StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>::getCb(
351 const sp<CallbackBroker>& broker, void* cookie) {
352 if (broker != nullptr) return broker->getStreamOutLatencyModeCallback(cookie);
353 return nullptr;
354}
355
356/*
357Note on the callback ownership.
358
359In the Binder ownership model, the server implementation is kept alive
360as long as there is any client (proxy object) alive. This is done by
361incrementing the refcount of the server-side object by the Binder framework.
362When it detects that the last client is gone, it decrements the refcount back.
363
364Thus, it is not needed to keep any references to StreamCallback on our
365side (after we have sent an instance to the client), because we are
366the server-side. The callback object will be kept alive as long as the HAL server
367holds a strong ref to IStreamCallback proxy.
368*/
369
370class OutputStreamCallbackAidl : public StreamCallbackBase,
371 public StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>,
372 public ::aidl::android::hardware::audio::core::BnStreamCallback {
373 public:
374 explicit OutputStreamCallbackAidl(const sp<CallbackBroker>& broker)
375 : StreamCallbackBase(broker),
376 StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>(
377 *static_cast<StreamCallbackBase*>(this)) {}
378 ndk::ScopedAStatus onTransferReady() override {
379 return runCb([](CbRef cb) { cb->onWriteReady(); });
380 }
381 ndk::ScopedAStatus onError() override {
382 return runCb([](CbRef cb) { cb->onError(); });
383 }
384 ndk::ScopedAStatus onDrainReady() override {
385 return runCb([](CbRef cb) { cb->onDrainReady(); });
386 }
387};
388
389class OutputStreamEventCallbackAidl :
390 public StreamCallbackBase,
391 public StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>,
392 public StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>,
393 public ::aidl::android::hardware::audio::core::BnStreamOutEventCallback {
394 public:
395 explicit OutputStreamEventCallbackAidl(const sp<CallbackBroker>& broker)
396 : StreamCallbackBase(broker),
397 StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>(
398 *static_cast<StreamCallbackBase*>(this)),
399 StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>(
400 *static_cast<StreamCallbackBase*>(this)) {}
401 ndk::ScopedAStatus onCodecFormatChanged(const std::vector<uint8_t>& in_audioMetadata) override {
402 std::basic_string<uint8_t> halMetadata(in_audioMetadata.begin(), in_audioMetadata.end());
403 return StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>::runCb(
404 [&halMetadata](auto cb) { cb->onCodecFormatChanged(halMetadata); });
405 }
406 ndk::ScopedAStatus onRecommendedLatencyModeChanged(
407 const std::vector<AudioLatencyMode>& in_modes) override {
408 auto halModes = VALUE_OR_FATAL(
409 ::aidl::android::convertContainer<std::vector<audio_latency_mode_t>>(
410 in_modes,
411 ::aidl::android::aidl2legacy_AudioLatencyMode_audio_latency_mode_t));
412 return StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>::runCb(
413 [&halModes](auto cb) { cb->onRecommendedLatencyModeChanged(halModes); });
414 }
415};
416
417} // namespace
418
Mikhail Naganov31d46652023-01-10 18:29:25 +0000419status_t DeviceHalAidl::openOutputStream(
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800420 audio_io_handle_t handle, audio_devices_t devices,
421 audio_output_flags_t flags, struct audio_config* config,
422 const char* address,
Mikhail Naganov31d46652023-01-10 18:29:25 +0000423 sp<StreamOutHalInterface>* outStream) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800424 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700425 TIME_CHECK();
426 if (mModule == nullptr) return NO_INIT;
427 if (outStream == nullptr || config == nullptr) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000428 return BAD_VALUE;
429 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700430 constexpr bool isInput = false;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800431 int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
432 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(handle));
433 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700434 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, isInput));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800435 AudioDevice aidlDevice = VALUE_OR_RETURN_STATUS(
436 ::aidl::android::legacy2aidl_audio_device_AudioDevice(devices, address));
437 int32_t aidlOutputFlags = VALUE_OR_RETURN_STATUS(
438 ::aidl::android::legacy2aidl_audio_output_flags_t_int32_t_mask(flags));
439 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::output>(aidlOutputFlags);
440 AudioPortConfig mixPortConfig;
Mikhail Naganove93a0862023-03-15 17:06:59 -0700441 AudioPatch aidlPatch;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700442 Hal2AidlMapper::Cleanups cleanups(mMapperAccessor);
443 {
444 std::lock_guard l(mLock);
445 RETURN_STATUS_IF_ERROR(mMapper.prepareToOpenStream(aidlHandle, aidlDevice, aidlFlags,
446 AudioSource::SYS_RESERVED_INVALID /*only needed for input*/,
447 &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
448 }
449 *config = VALUE_OR_RETURN_STATUS(
450 ::aidl::android::aidl2legacy_AudioConfig_audio_config_t(aidlConfig, isInput));
Mikhail Naganovca92a5c2023-12-07 14:00:48 -0800451 if (mixPortConfig.id == 0) return BAD_VALUE; // HAL suggests a different config.
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800452 ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamArguments args;
453 args.portConfigId = mixPortConfig.id;
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800454 const bool isOffload = isBitPositionFlagSet(
455 aidlOutputFlags, AudioOutputFlags::COMPRESS_OFFLOAD);
456 std::shared_ptr<OutputStreamCallbackAidl> streamCb;
457 if (isOffload) {
458 streamCb = ndk::SharedRefBase::make<OutputStreamCallbackAidl>(this);
459 }
460 auto eventCb = ndk::SharedRefBase::make<OutputStreamEventCallbackAidl>(this);
461 if (isOffload) {
462 args.offloadInfo = aidlConfig.offloadInfo;
463 args.callback = streamCb;
464 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800465 args.bufferSizeFrames = aidlConfig.frameCount;
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800466 args.eventCallback = eventCb;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800467 ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamReturn ret;
468 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openOutputStream(args, &ret)));
Mikhail Naganov712d71b2023-02-23 17:57:16 -0800469 StreamContextAidl context(ret.desc, isOffload);
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800470 if (!context.isValid()) {
471 ALOGE("%s: Failed to created a valid stream context from the descriptor: %s",
472 __func__, ret.desc.toString().c_str());
473 return NO_INIT;
474 }
Mikhail Naganove93a0862023-03-15 17:06:59 -0700475 *outStream = sp<StreamOutHalAidl>::make(*config, std::move(context), aidlPatch.latenciesMs[0],
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700476 std::move(ret.stream), mVendorExt, this /*callbackBroker*/);
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800477 void* cbCookie = (*outStream).get();
478 {
479 std::lock_guard l(mLock);
480 mCallbacks.emplace(cbCookie, Callbacks{});
Mikhail Naganov78f7f9a2023-11-16 15:49:23 -0800481 mMapper.addStream(*outStream, mixPortConfig.id, aidlPatch.id);
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800482 }
483 if (streamCb) streamCb->setCookie(cbCookie);
484 eventCb->setCookie(cbCookie);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800485 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000486 return OK;
487}
488
Mikhail Naganov31d46652023-01-10 18:29:25 +0000489status_t DeviceHalAidl::openInputStream(
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800490 audio_io_handle_t handle, audio_devices_t devices,
491 struct audio_config* config, audio_input_flags_t flags,
492 const char* address, audio_source_t source,
493 audio_devices_t outputDevice, const char* outputDeviceAddress,
Mikhail Naganov31d46652023-01-10 18:29:25 +0000494 sp<StreamInHalInterface>* inStream) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800495 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700496 TIME_CHECK();
497 if (mModule == nullptr) return NO_INIT;
498 if (inStream == nullptr || config == nullptr) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000499 return BAD_VALUE;
500 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700501 constexpr bool isInput = true;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800502 int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
503 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(handle));
504 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700505 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, isInput));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800506 AudioDevice aidlDevice = VALUE_OR_RETURN_STATUS(
507 ::aidl::android::legacy2aidl_audio_device_AudioDevice(devices, address));
508 int32_t aidlInputFlags = VALUE_OR_RETURN_STATUS(
509 ::aidl::android::legacy2aidl_audio_input_flags_t_int32_t_mask(flags));
510 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::input>(aidlInputFlags);
511 AudioSource aidlSource = VALUE_OR_RETURN_STATUS(
512 ::aidl::android::legacy2aidl_audio_source_t_AudioSource(source));
513 AudioPortConfig mixPortConfig;
Mikhail Naganove93a0862023-03-15 17:06:59 -0700514 AudioPatch aidlPatch;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700515 Hal2AidlMapper::Cleanups cleanups(mMapperAccessor);
516 {
517 std::lock_guard l(mLock);
518 RETURN_STATUS_IF_ERROR(mMapper.prepareToOpenStream(
519 aidlHandle, aidlDevice, aidlFlags, aidlSource,
520 &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
521 }
522 *config = VALUE_OR_RETURN_STATUS(
523 ::aidl::android::aidl2legacy_AudioConfig_audio_config_t(aidlConfig, isInput));
Mikhail Naganovca92a5c2023-12-07 14:00:48 -0800524 if (mixPortConfig.id == 0) return BAD_VALUE; // HAL suggests a different config.
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800525 ::aidl::android::hardware::audio::core::IModule::OpenInputStreamArguments args;
526 args.portConfigId = mixPortConfig.id;
527 RecordTrackMetadata aidlTrackMetadata{
528 .source = aidlSource, .gain = 1, .channelMask = aidlConfig.base.channelMask };
529 if (outputDevice != AUDIO_DEVICE_NONE) {
530 aidlTrackMetadata.destinationDevice = VALUE_OR_RETURN_STATUS(
531 ::aidl::android::legacy2aidl_audio_device_AudioDevice(
532 outputDevice, outputDeviceAddress));
533 }
534 args.sinkMetadata.tracks.push_back(std::move(aidlTrackMetadata));
535 args.bufferSizeFrames = aidlConfig.frameCount;
536 ::aidl::android::hardware::audio::core::IModule::OpenInputStreamReturn ret;
537 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openInputStream(args, &ret)));
Mikhail Naganov712d71b2023-02-23 17:57:16 -0800538 StreamContextAidl context(ret.desc, false /*isAsynchronous*/);
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800539 if (!context.isValid()) {
540 ALOGE("%s: Failed to created a valid stream context from the descriptor: %s",
541 __func__, ret.desc.toString().c_str());
542 return NO_INIT;
543 }
Mikhail Naganove93a0862023-03-15 17:06:59 -0700544 *inStream = sp<StreamInHalAidl>::make(*config, std::move(context), aidlPatch.latenciesMs[0],
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700545 std::move(ret.stream), mVendorExt, this /*micInfoProvider*/);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700546 {
547 std::lock_guard l(mLock);
Mikhail Naganov78f7f9a2023-11-16 15:49:23 -0800548 mMapper.addStream(*inStream, mixPortConfig.id, aidlPatch.id);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700549 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800550 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000551 return OK;
552}
553
554status_t DeviceHalAidl::supportsAudioPatches(bool* supportsPatches) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700555 if (supportsPatches == nullptr) {
556 return BAD_VALUE;
557 }
Shunkai Yao51202502022-12-12 06:11:46 +0000558 *supportsPatches = true;
559 return OK;
560}
561
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800562status_t DeviceHalAidl::createAudioPatch(unsigned int num_sources,
563 const struct audio_port_config* sources,
564 unsigned int num_sinks,
565 const struct audio_port_config* sinks,
566 audio_patch_handle_t* patch) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800567 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000568 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700569 if (mModule == nullptr) return NO_INIT;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800570 if (num_sinks > AUDIO_PATCH_PORTS_MAX || num_sources > AUDIO_PATCH_PORTS_MAX ||
571 sources == nullptr || sinks == nullptr || patch == nullptr) {
572 return BAD_VALUE;
573 }
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800574 // When the patch handle (*patch) is AUDIO_PATCH_HANDLE_NONE, it means
575 // the framework wants to create a new patch. The handle has to be generated
576 // by the HAL. Since handles generated this way can only be unique within
577 // a HAL module, the framework generates a globally unique handle, and maps
578 // it on the <HAL module, patch handle> pair.
579 // When the patch handle is set, it meant the framework intends to update
580 // an existing patch.
581 //
582 // This behavior corresponds to HAL module behavior, with the only difference
583 // that the HAL module uses `int32_t` for patch IDs. The following assert ensures
584 // that both the framework and the HAL use the same value for "no ID":
585 static_assert(AUDIO_PATCH_HANDLE_NONE == 0);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700586 int32_t aidlPatchId = static_cast<int32_t>(*patch);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800587
588 // Upon conversion, mix port configs contain audio configuration, while
589 // device port configs contain device address. This data is used to find
590 // or create HAL configs.
591 std::vector<AudioPortConfig> aidlSources, aidlSinks;
592 for (unsigned int i = 0; i < num_sources; ++i) {
593 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
594 sources[i].role, sources[i].type)) ==
595 ::aidl::android::AudioPortDirection::INPUT;
596 aidlSources.push_back(VALUE_OR_RETURN_STATUS(
597 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
598 sources[i], isInput, 0)));
599 }
600 for (unsigned int i = 0; i < num_sinks; ++i) {
601 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
602 sinks[i].role, sinks[i].type)) ==
603 ::aidl::android::AudioPortDirection::INPUT;
604 aidlSinks.push_back(VALUE_OR_RETURN_STATUS(
605 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
606 sinks[i], isInput, 0)));
607 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700608 Hal2AidlMapper::Cleanups cleanups(mMapperAccessor);
609 {
610 std::lock_guard l(mLock);
611 RETURN_STATUS_IF_ERROR(mMapper.createOrUpdatePatch(
612 aidlSources, aidlSinks, &aidlPatchId, &cleanups));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800613 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700614 *patch = static_cast<audio_patch_handle_t>(aidlPatchId);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800615 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000616 return OK;
617}
618
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800619status_t DeviceHalAidl::releaseAudioPatch(audio_patch_handle_t patch) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800620 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000621 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700622 if (mModule == nullptr) return NO_INIT;
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800623 static_assert(AUDIO_PATCH_HANDLE_NONE == 0);
624 if (patch == AUDIO_PATCH_HANDLE_NONE) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800625 return BAD_VALUE;
626 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700627 std::lock_guard l(mLock);
628 RETURN_STATUS_IF_ERROR(mMapper.releaseAudioPatch(static_cast<int32_t>(patch)));
Shunkai Yao51202502022-12-12 06:11:46 +0000629 return OK;
630}
631
Mikhail Naganove93a0862023-03-15 17:06:59 -0700632status_t DeviceHalAidl::getAudioPort(struct audio_port* port) {
Mikhail Naganove93a0862023-03-15 17:06:59 -0700633 if (port == nullptr) {
634 return BAD_VALUE;
635 }
636 audio_port_v7 portV7;
637 audio_populate_audio_port_v7(port, &portV7);
638 RETURN_STATUS_IF_ERROR(getAudioPort(&portV7));
639 return audio_populate_audio_port(&portV7, port) ? OK : BAD_VALUE;
640}
641
642status_t DeviceHalAidl::getAudioPort(struct audio_port_v7 *port) {
643 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
644 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700645 if (mModule == nullptr) return NO_INIT;
Mikhail Naganove93a0862023-03-15 17:06:59 -0700646 if (port == nullptr) {
647 return BAD_VALUE;
648 }
649 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(port->role, port->type)) ==
650 ::aidl::android::AudioPortDirection::INPUT;
651 auto aidlPort = VALUE_OR_RETURN_STATUS(
652 ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
653 if (aidlPort.ext.getTag() != AudioPortExt::device) {
654 ALOGE("%s: provided port is not a device port (module %s): %s",
655 __func__, mInstance.c_str(), aidlPort.toString().c_str());
656 return BAD_VALUE;
657 }
658 const auto& matchDevice = aidlPort.ext.get<AudioPortExt::device>().device;
659 // It seems that we don't have to call HAL since all valid ports have been added either
660 // during initialization, or while handling connection of an external device.
Mikhail Naganove93a0862023-03-15 17:06:59 -0700661 const int32_t fwkId = aidlPort.id;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700662 {
663 std::lock_guard l(mLock);
664 RETURN_STATUS_IF_ERROR(mMapper.getAudioPortCached(matchDevice, &aidlPort));
665 }
Mikhail Naganove93a0862023-03-15 17:06:59 -0700666 aidlPort.id = fwkId;
667 *port = VALUE_OR_RETURN_STATUS(::aidl::android::aidl2legacy_AudioPort_audio_port_v7(
668 aidlPort, isInput));
669 return OK;
670}
671
jiabin12537fc2023-10-12 17:56:08 +0000672status_t DeviceHalAidl::getAudioMixPort(const struct audio_port_v7 *devicePort,
673 struct audio_port_v7 *mixPort) {
674 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700675 TIME_CHECK();
676 if (mModule == nullptr) return NO_INIT;
677 if (devicePort == nullptr || mixPort == nullptr ||
678 devicePort->type != AUDIO_PORT_TYPE_DEVICE || mixPort->type != AUDIO_PORT_TYPE_MIX) {
jiabin12537fc2023-10-12 17:56:08 +0000679 return BAD_VALUE;
680 }
681 const int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
682 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(mixPort->ext.mix.handle));
jiabin12537fc2023-10-12 17:56:08 +0000683 AudioPort port;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700684 {
685 std::lock_guard l(mLock);
686 RETURN_STATUS_IF_ERROR(mMapper.getAudioMixPort(aidlHandle, &port));
jiabin12537fc2023-10-12 17:56:08 +0000687 }
688 const bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
689 mixPort->role, mixPort->type)) == ::aidl::android::AudioPortDirection::INPUT;
690 *mixPort = VALUE_OR_RETURN_STATUS(::aidl::android::aidl2legacy_AudioPort_audio_port_v7(
691 port, isInput));
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700692 return OK;
jiabin12537fc2023-10-12 17:56:08 +0000693}
694
Mikhail Naganove93a0862023-03-15 17:06:59 -0700695status_t DeviceHalAidl::setAudioPortConfig(const struct audio_port_config* config) {
696 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
697 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700698 if (mModule == nullptr) return NO_INIT;
Mikhail Naganove93a0862023-03-15 17:06:59 -0700699 if (config == nullptr) {
700 return BAD_VALUE;
701 }
702 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
703 config->role, config->type)) == ::aidl::android::AudioPortDirection::INPUT;
704 AudioPortConfig requestedPortConfig = VALUE_OR_RETURN_STATUS(
705 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
706 *config, isInput, 0 /*portId*/));
707 AudioPortConfig portConfig;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700708 std::lock_guard l(mLock);
Mikhail Naganovca92a5c2023-12-07 14:00:48 -0800709 return mMapper.setPortConfig(requestedPortConfig, std::set<int32_t>(), &portConfig);
Shunkai Yao51202502022-12-12 06:11:46 +0000710}
711
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800712MicrophoneInfoProvider::Info const* DeviceHalAidl::getMicrophoneInfo() {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700713 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
714 TIME_CHECK();
715 if (!mModule) return {};
716 std::lock_guard l(mLock);
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800717 if (mMicrophones.status == Microphones::Status::UNKNOWN) {
718 TIME_CHECK();
719 std::vector<MicrophoneInfo> aidlInfo;
720 status_t status = statusTFromBinderStatus(mModule->getMicrophones(&aidlInfo));
721 if (status == OK) {
722 mMicrophones.status = Microphones::Status::QUERIED;
723 mMicrophones.info = std::move(aidlInfo);
724 } else if (status == INVALID_OPERATION) {
725 mMicrophones.status = Microphones::Status::NOT_SUPPORTED;
726 } else {
727 ALOGE("%s: Unexpected status from 'IModule.getMicrophones': %d", __func__, status);
728 return {};
729 }
730 }
731 if (mMicrophones.status == Microphones::Status::QUERIED) {
732 return &mMicrophones.info;
733 }
734 return {}; // NOT_SUPPORTED
735}
736
Shunkai Yao51202502022-12-12 06:11:46 +0000737status_t DeviceHalAidl::getMicrophones(
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800738 std::vector<audio_microphone_characteristic_t>* microphones) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700739 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
740 TIME_CHECK();
741 if (mModule == nullptr) return NO_INIT;
742 if (microphones == nullptr) {
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800743 return BAD_VALUE;
744 }
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800745 auto staticInfo = getMicrophoneInfo();
746 if (!staticInfo) return INVALID_OPERATION;
747 std::vector<MicrophoneDynamicInfo> emptyDynamicInfo;
748 emptyDynamicInfo.reserve(staticInfo->size());
749 std::transform(staticInfo->begin(), staticInfo->end(), std::back_inserter(emptyDynamicInfo),
750 [](const auto& info) { return MicrophoneDynamicInfo{ .id = info.id }; });
751 *microphones = VALUE_OR_RETURN_STATUS(
752 ::aidl::android::convertContainers<std::vector<audio_microphone_characteristic_t>>(
753 *staticInfo, emptyDynamicInfo,
754 ::aidl::android::aidl2legacy_MicrophoneInfos_audio_microphone_characteristic_t)
755 );
Shunkai Yao51202502022-12-12 06:11:46 +0000756 return OK;
757}
758
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700759status_t DeviceHalAidl::addDeviceEffect(
760 const struct audio_port_config *device, sp<EffectHalInterface> effect) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700761 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700762 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700763 if (mModule == nullptr) return NO_INIT;
764 if (device == nullptr || effect == nullptr) {
Shunkai Yao51202502022-12-12 06:11:46 +0000765 return BAD_VALUE;
766 }
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700767 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
768 device->role, device->type)) == ::aidl::android::AudioPortDirection::INPUT;
769 auto requestedPortConfig = VALUE_OR_RETURN_STATUS(
770 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
771 *device, isInput, 0));
772 if (requestedPortConfig.ext.getTag() != AudioPortExt::Tag::device) {
773 ALOGE("%s: provided port config is not a device port config: %s",
774 __func__, requestedPortConfig.toString().c_str());
775 return BAD_VALUE;
776 }
777 AudioPortConfig devicePortConfig;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700778 Hal2AidlMapper::Cleanups cleanups(mMapperAccessor);
779 {
780 std::lock_guard l(mLock);
Mikhail Naganovca92a5c2023-12-07 14:00:48 -0800781 RETURN_STATUS_IF_ERROR(mMapper.setPortConfig(
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700782 requestedPortConfig, {} /*destinationPortIds*/, &devicePortConfig, &cleanups));
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700783 }
784 auto aidlEffect = sp<effect::EffectHalAidl>::cast(effect);
785 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->addDeviceEffect(
786 devicePortConfig.id, aidlEffect->getIEffect())));
787 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000788 return OK;
789}
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700790status_t DeviceHalAidl::removeDeviceEffect(
791 const struct audio_port_config *device, sp<EffectHalInterface> effect) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700792 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700793 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700794 if (mModule == nullptr) return NO_INIT;
795 if (device == nullptr || effect == nullptr) {
Shunkai Yao51202502022-12-12 06:11:46 +0000796 return BAD_VALUE;
797 }
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700798 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
799 device->role, device->type)) == ::aidl::android::AudioPortDirection::INPUT;
800 auto requestedPortConfig = VALUE_OR_RETURN_STATUS(
801 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
802 *device, isInput, 0));
803 if (requestedPortConfig.ext.getTag() != AudioPortExt::Tag::device) {
804 ALOGE("%s: provided port config is not a device port config: %s",
805 __func__, requestedPortConfig.toString().c_str());
806 return BAD_VALUE;
807 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700808 AudioPortConfig devicePortConfig;
809 {
810 std::lock_guard l(mLock);
811 RETURN_STATUS_IF_ERROR(mMapper.findPortConfig(
812 requestedPortConfig.ext.get<AudioPortExt::Tag::device>().device,
813 &devicePortConfig));
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700814 }
815 auto aidlEffect = sp<effect::EffectHalAidl>::cast(effect);
816 return statusTFromBinderStatus(mModule->removeDeviceEffect(
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700817 devicePortConfig.id, aidlEffect->getIEffect()));
Shunkai Yao51202502022-12-12 06:11:46 +0000818}
819
820status_t DeviceHalAidl::getMmapPolicyInfos(
David Li9cf5e622023-03-21 00:51:10 +0800821 media::audio::common::AudioMMapPolicyType policyType,
822 std::vector<media::audio::common::AudioMMapPolicyInfo>* policyInfos) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700823 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000824 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700825 if (mModule == nullptr) return NO_INIT;
Mikhail Naganov25bc9a22023-04-21 18:48:16 -0700826 AudioMMapPolicyType mmapPolicyType = VALUE_OR_RETURN_STATUS(
827 cpp2ndk_AudioMMapPolicyType(policyType));
David Li9cf5e622023-03-21 00:51:10 +0800828
829 std::vector<AudioMMapPolicyInfo> mmapPolicyInfos;
830
831 if (status_t status = statusTFromBinderStatus(
832 mModule->getMmapPolicyInfos(mmapPolicyType, &mmapPolicyInfos)); status != OK) {
833 return status;
834 }
835
836 *policyInfos = VALUE_OR_RETURN_STATUS(
837 convertContainer<std::vector<media::audio::common::AudioMMapPolicyInfo>>(
838 mmapPolicyInfos, ndk2cpp_AudioMMapPolicyInfo));
Shunkai Yao51202502022-12-12 06:11:46 +0000839 return OK;
840}
841
842int32_t DeviceHalAidl::getAAudioMixerBurstCount() {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700843 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000844 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700845 if (mModule == nullptr) return NO_INIT;
David Li9cf5e622023-03-21 00:51:10 +0800846 int32_t mixerBurstCount = 0;
847 if (mModule->getAAudioMixerBurstCount(&mixerBurstCount).isOk()) {
848 return mixerBurstCount;
849 }
850 return 0;
Shunkai Yao51202502022-12-12 06:11:46 +0000851}
852
853int32_t DeviceHalAidl::getAAudioHardwareBurstMinUsec() {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700854 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000855 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700856 if (mModule == nullptr) return NO_INIT;
David Li9cf5e622023-03-21 00:51:10 +0800857 int32_t hardwareBurstMinUsec = 0;
858 if (mModule->getAAudioHardwareBurstMinUsec(&hardwareBurstMinUsec).isOk()) {
859 return hardwareBurstMinUsec;
860 }
861 return 0;
Shunkai Yao51202502022-12-12 06:11:46 +0000862}
863
864error::Result<audio_hw_sync_t> DeviceHalAidl::getHwAvSync() {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700865 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000866 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700867 if (mModule == nullptr) return NO_INIT;
Mikhail Naganov08a62ab2023-03-14 17:11:51 -0700868 int32_t aidlHwAvSync;
869 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->generateHwAvSyncId(&aidlHwAvSync)));
870 return VALUE_OR_RETURN_STATUS(
871 ::aidl::android::aidl2legacy_int32_t_audio_hw_sync_t(aidlHwAvSync));
Shunkai Yao51202502022-12-12 06:11:46 +0000872}
873
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000874status_t DeviceHalAidl::dump(int fd, const Vector<String16>& args) {
875 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700876 if (mModule == nullptr) return NO_INIT;
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000877 return mModule->dump(fd, Args(args).args(), args.size());
David Li9cf5e622023-03-21 00:51:10 +0800878}
Shunkai Yao51202502022-12-12 06:11:46 +0000879
Eric Laurent7af6ee72023-06-29 11:44:54 +0200880status_t DeviceHalAidl::supportsBluetoothVariableLatency(bool* supports) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700881 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000882 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700883 if (mModule == nullptr) return NO_INIT;
Mikhail Naganov3ac95c92023-04-12 13:14:30 -0700884 if (supports == nullptr) {
885 return BAD_VALUE;
886 }
887 return statusTFromBinderStatus(mModule->supportsVariableLatency(supports));
Shunkai Yao51202502022-12-12 06:11:46 +0000888}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000889
Vlad Popa03bd5bc2023-01-17 16:16:51 +0100890status_t DeviceHalAidl::getSoundDoseInterface(const std::string& module,
891 ::ndk::SpAIBinder* soundDoseBinder) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700892 if (soundDoseBinder == nullptr) {
893 return BAD_VALUE;
894 }
Vlad Popa03bd5bc2023-01-17 16:16:51 +0100895 if (mSoundDose == nullptr) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700896 ALOGE("%s failed to retrieve the sound dose interface for module %s",
897 __func__, module.c_str());
898 return BAD_VALUE;
Vlad Popa03bd5bc2023-01-17 16:16:51 +0100899 }
900 *soundDoseBinder = mSoundDose->asBinder();
901 ALOGI("%s using audio AIDL HAL sound dose interface", __func__);
Vlad Popa03bd5bc2023-01-17 16:16:51 +0100902 return OK;
903}
jiabin872de702023-04-27 22:04:31 +0000904
905status_t DeviceHalAidl::prepareToDisconnectExternalDevice(const struct audio_port_v7* port) {
906 // There is not AIDL API defined for `prepareToDisconnectExternalDevice`.
907 // Call `setConnectedState` instead.
908 // TODO(b/279824103): call prepareToDisconnectExternalDevice when it is added.
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700909 RETURN_STATUS_IF_ERROR(setConnectedState(port, false /*connected*/));
910 std::lock_guard l(mLock);
911 mDeviceDisconnectionNotified.insert(port->id);
Mikhail Naganov66907492023-09-11 17:22:03 -0700912 // Return that there was no error as otherwise the disconnection procedure will not be
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700913 // considered complete for upper layers, and 'setConnectedState' will not be called again
914 return OK;
jiabin872de702023-04-27 22:04:31 +0000915}
916
Mikhail Naganove93a0862023-03-15 17:06:59 -0700917status_t DeviceHalAidl::setConnectedState(const struct audio_port_v7 *port, bool connected) {
Mikhail Naganovae9063d2023-11-07 16:43:51 -0800918 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganove93a0862023-03-15 17:06:59 -0700919 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700920 if (mModule == nullptr) return NO_INIT;
Mikhail Naganove93a0862023-03-15 17:06:59 -0700921 if (port == nullptr) {
922 return BAD_VALUE;
923 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700924 if (!connected) {
925 std::lock_guard l(mLock);
926 if (mDeviceDisconnectionNotified.erase(port->id) > 0) {
927 // For device disconnection, APM will first call `prepareToDisconnectExternalDevice`
928 // and then call `setConnectedState`. However, there is no API for
929 // `prepareToDisconnectExternalDevice` yet. In that case, `setConnectedState` will be
930 // called when calling `prepareToDisconnectExternalDevice`. Do not call to the HAL if
931 // previous call is successful. Also remove the cache here to avoid a large cache after
932 // a long run.
933 return OK;
934 }
jiabin872de702023-04-27 22:04:31 +0000935 }
Mikhail Naganove93a0862023-03-15 17:06:59 -0700936 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(port->role, port->type)) ==
937 ::aidl::android::AudioPortDirection::INPUT;
938 AudioPort aidlPort = VALUE_OR_RETURN_STATUS(
939 ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
940 if (aidlPort.ext.getTag() != AudioPortExt::device) {
941 ALOGE("%s: provided port is not a device port (module %s): %s",
942 __func__, mInstance.c_str(), aidlPort.toString().c_str());
943 return BAD_VALUE;
944 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700945 std::lock_guard l(mLock);
946 return mMapper.setDevicePortConnectedState(aidlPort, connected);
Mikhail Naganove93a0862023-03-15 17:06:59 -0700947}
948
949status_t DeviceHalAidl::setSimulateDeviceConnections(bool enabled) {
950 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700951 if (mModule == nullptr) return NO_INIT;
952 {
953 std::lock_guard l(mLock);
954 mMapper.resetUnusedPatchesAndPortConfigs();
955 }
Mikhail Naganove93a0862023-03-15 17:06:59 -0700956 ModuleDebug debug{ .simulateDeviceConnections = enabled };
957 status_t status = statusTFromBinderStatus(mModule->setModuleDebug(debug));
958 // This is important to log as it affects HAL behavior.
959 if (status == OK) {
960 ALOGI("%s: set enabled: %d", __func__, enabled);
961 } else {
962 ALOGW("%s: set enabled to %d failed: %d", __func__, enabled, status);
963 }
964 return status;
965}
966
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700967status_t DeviceHalAidl::filterAndRetrieveBtA2dpParameters(
968 AudioParameter &keys, AudioParameter *result) {
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700969 if (String8 key = String8(AudioParameter::keyReconfigA2dpSupported); keys.containsKey(key)) {
970 keys.remove(key);
David Lia7761ed2023-11-03 17:22:07 +0000971 if (mBluetoothA2dp != nullptr) {
972 bool supports;
973 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
974 mBluetoothA2dp->supportsOffloadReconfiguration(&supports)));
975 result->addInt(key, supports ? 1 : 0);
976 } else {
977 ALOGI("%s: no IBluetoothA2dp on %s", __func__, mInstance.c_str());
978 result->addInt(key, 0);
979 }
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700980 }
981 return OK;
982}
983
Mikhail Naganovccc82112023-04-27 18:14:15 -0700984status_t DeviceHalAidl::filterAndUpdateBtA2dpParameters(AudioParameter &parameters) {
Mikhail Naganovccc82112023-04-27 18:14:15 -0700985 std::optional<bool> a2dpEnabled;
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700986 std::optional<std::vector<VendorParameter>> reconfigureOffload;
Mikhail Naganovccc82112023-04-27 18:14:15 -0700987 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
988 parameters, String8(AudioParameter::keyBtA2dpSuspended),
989 [&a2dpEnabled](const String8& trueOrFalse) {
990 if (trueOrFalse == AudioParameter::valueTrue) {
991 a2dpEnabled = false; // 'suspended' == true
992 return OK;
993 } else if (trueOrFalse == AudioParameter::valueFalse) {
994 a2dpEnabled = true; // 'suspended' == false
995 return OK;
996 }
997 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
998 AudioParameter::keyBtA2dpSuspended, trueOrFalse.c_str());
999 return BAD_VALUE;
1000 }));
Mikhail Naganove7a26ad2023-05-25 17:36:48 -07001001 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1002 parameters, String8(AudioParameter::keyReconfigA2dp),
1003 [&](const String8& value) -> status_t {
1004 if (mVendorExt != nullptr) {
1005 std::vector<VendorParameter> result;
1006 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
1007 mVendorExt->parseBluetoothA2dpReconfigureOffload(
1008 std::string(value.c_str()), &result)));
1009 reconfigureOffload = std::move(result);
1010 } else {
1011 reconfigureOffload = std::vector<VendorParameter>();
1012 }
1013 return OK;
1014 }));
Mikhail Naganovccc82112023-04-27 18:14:15 -07001015 if (mBluetoothA2dp != nullptr && a2dpEnabled.has_value()) {
1016 return statusTFromBinderStatus(mBluetoothA2dp->setEnabled(a2dpEnabled.value()));
1017 }
Mikhail Naganove7a26ad2023-05-25 17:36:48 -07001018 if (mBluetoothA2dp != nullptr && reconfigureOffload.has_value()) {
1019 return statusTFromBinderStatus(mBluetoothA2dp->reconfigureOffload(
1020 reconfigureOffload.value()));
1021 }
Mikhail Naganovccc82112023-04-27 18:14:15 -07001022 return OK;
1023}
1024
1025status_t DeviceHalAidl::filterAndUpdateBtHfpParameters(AudioParameter &parameters) {
Mikhail Naganovccc82112023-04-27 18:14:15 -07001026 IBluetooth::HfpConfig hfpConfig;
1027 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1028 parameters, String8(AudioParameter::keyBtHfpEnable),
1029 [&hfpConfig](const String8& trueOrFalse) {
1030 if (trueOrFalse == AudioParameter::valueTrue) {
1031 hfpConfig.isEnabled = Boolean{ .value = true };
1032 return OK;
1033 } else if (trueOrFalse == AudioParameter::valueFalse) {
1034 hfpConfig.isEnabled = Boolean{ .value = false };
1035 return OK;
1036 }
1037 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1038 AudioParameter::keyBtHfpEnable, trueOrFalse.c_str());
1039 return BAD_VALUE;
1040 }));
1041 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
1042 parameters, String8(AudioParameter::keyBtHfpSamplingRate),
1043 [&hfpConfig](int sampleRate) {
1044 return sampleRate > 0 ?
1045 hfpConfig.sampleRate = Int{ .value = sampleRate }, OK : BAD_VALUE;
1046 }));
1047 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
1048 parameters, String8(AudioParameter::keyBtHfpVolume),
1049 [&hfpConfig](int volume0to15) {
1050 if (volume0to15 >= 0 && volume0to15 <= 15) {
1051 hfpConfig.volume = Float{ .value = volume0to15 / 15.0f };
1052 return OK;
1053 }
1054 return BAD_VALUE;
1055 }));
1056 if (mBluetooth != nullptr && hfpConfig != IBluetooth::HfpConfig{}) {
1057 IBluetooth::HfpConfig newHfpConfig;
1058 return statusTFromBinderStatus(mBluetooth->setHfpConfig(hfpConfig, &newHfpConfig));
1059 }
1060 return OK;
1061}
1062
1063status_t DeviceHalAidl::filterAndUpdateBtLeParameters(AudioParameter &parameters) {
Mikhail Naganovccc82112023-04-27 18:14:15 -07001064 std::optional<bool> leEnabled;
1065 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1066 parameters, String8(AudioParameter::keyBtLeSuspended),
1067 [&leEnabled](const String8& trueOrFalse) {
1068 if (trueOrFalse == AudioParameter::valueTrue) {
1069 leEnabled = false; // 'suspended' == true
1070 return OK;
1071 } else if (trueOrFalse == AudioParameter::valueFalse) {
1072 leEnabled = true; // 'suspended' == false
1073 return OK;
1074 }
1075 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1076 AudioParameter::keyBtLeSuspended, trueOrFalse.c_str());
1077 return BAD_VALUE;
1078 }));
1079 if (mBluetoothLe != nullptr && leEnabled.has_value()) {
1080 return statusTFromBinderStatus(mBluetoothLe->setEnabled(leEnabled.value()));
1081 }
1082 return OK;
1083}
1084
1085status_t DeviceHalAidl::filterAndUpdateBtScoParameters(AudioParameter &parameters) {
Mikhail Naganovccc82112023-04-27 18:14:15 -07001086 IBluetooth::ScoConfig scoConfig;
1087 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1088 parameters, String8(AudioParameter::keyBtSco),
1089 [&scoConfig](const String8& onOrOff) {
1090 if (onOrOff == AudioParameter::valueOn) {
1091 scoConfig.isEnabled = Boolean{ .value = true };
1092 return OK;
1093 } else if (onOrOff == AudioParameter::valueOff) {
1094 scoConfig.isEnabled = Boolean{ .value = false };
1095 return OK;
1096 }
1097 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1098 AudioParameter::keyBtSco, onOrOff.c_str());
1099 return BAD_VALUE;
1100 }));
1101 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1102 parameters, String8(AudioParameter::keyBtScoHeadsetName),
1103 [&scoConfig](const String8& name) {
1104 scoConfig.debugName = name;
1105 return OK;
1106 }));
1107 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1108 parameters, String8(AudioParameter::keyBtNrec),
1109 [&scoConfig](const String8& onOrOff) {
1110 if (onOrOff == AudioParameter::valueOn) {
1111 scoConfig.isNrecEnabled = Boolean{ .value = true };
1112 return OK;
1113 } else if (onOrOff == AudioParameter::valueOff) {
1114 scoConfig.isNrecEnabled = Boolean{ .value = false };
1115 return OK;
1116 }
1117 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1118 AudioParameter::keyBtNrec, onOrOff.c_str());
1119 return BAD_VALUE;
1120 }));
1121 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1122 parameters, String8(AudioParameter::keyBtScoWb),
1123 [&scoConfig](const String8& onOrOff) {
1124 if (onOrOff == AudioParameter::valueOn) {
1125 scoConfig.mode = IBluetooth::ScoConfig::Mode::SCO_WB;
1126 return OK;
1127 } else if (onOrOff == AudioParameter::valueOff) {
1128 scoConfig.mode = IBluetooth::ScoConfig::Mode::SCO;
1129 return OK;
1130 }
1131 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1132 AudioParameter::keyBtScoWb, onOrOff.c_str());
1133 return BAD_VALUE;
1134 }));
1135 if (mBluetooth != nullptr && scoConfig != IBluetooth::ScoConfig{}) {
1136 IBluetooth::ScoConfig newScoConfig;
1137 return statusTFromBinderStatus(mBluetooth->setScoConfig(scoConfig, &newScoConfig));
1138 }
1139 return OK;
1140}
1141
Mikhail Naganove92c34b2023-05-31 14:24:48 -07001142status_t DeviceHalAidl::filterAndUpdateScreenParameters(AudioParameter &parameters) {
Mikhail Naganove92c34b2023-05-31 14:24:48 -07001143 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1144 parameters, String8(AudioParameter::keyScreenState),
1145 [&](const String8& onOrOff) -> status_t {
1146 std::optional<bool> isTurnedOn;
1147 if (onOrOff == AudioParameter::valueOn) {
1148 isTurnedOn = true;
1149 } else if (onOrOff == AudioParameter::valueOff) {
1150 isTurnedOn = false;
1151 }
1152 if (!isTurnedOn.has_value()) {
1153 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1154 AudioParameter::keyScreenState, onOrOff.c_str());
1155 return BAD_VALUE;
1156 }
1157 return statusTFromBinderStatus(
1158 mModule->updateScreenState(isTurnedOn.value()));
1159 }));
1160 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
1161 parameters, String8(AudioParameter::keyScreenRotation),
1162 [&](int rotationDegrees) -> status_t {
1163 IModule::ScreenRotation rotation;
1164 switch (rotationDegrees) {
1165 case 0: rotation = IModule::ScreenRotation::DEG_0; break;
1166 case 90: rotation = IModule::ScreenRotation::DEG_90; break;
1167 case 180: rotation = IModule::ScreenRotation::DEG_180; break;
1168 case 270: rotation = IModule::ScreenRotation::DEG_270; break;
1169 default:
1170 ALOGE("setParameters: parameter key \"%s\" has invalid value %d",
1171 AudioParameter::keyScreenRotation, rotationDegrees);
1172 return BAD_VALUE;
1173 }
1174 return statusTFromBinderStatus(mModule->updateScreenRotation(rotation));
1175 }));
1176 return OK;
1177}
1178
Mikhail Naganovb9a81312023-07-18 13:55:34 -07001179status_t DeviceHalAidl::filterAndUpdateTelephonyParameters(AudioParameter &parameters) {
Mikhail Naganovb9a81312023-07-18 13:55:34 -07001180 using TtyMode = ITelephony::TelecomConfig::TtyMode;
1181 ITelephony::TelecomConfig telConfig;
1182 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1183 parameters, String8(AudioParameter::keyTtyMode),
1184 [&telConfig](const String8& mode) {
1185 if (mode == AudioParameter::valueTtyModeOff) {
1186 telConfig.ttyMode = TtyMode::OFF;
1187 return OK;
1188 } else if (mode == AudioParameter::valueTtyModeFull) {
1189 telConfig.ttyMode = TtyMode::FULL;
1190 return OK;
1191 } else if (mode == AudioParameter::valueTtyModeHco) {
1192 telConfig.ttyMode = TtyMode::HCO;
1193 return OK;
1194 } else if (mode == AudioParameter::valueTtyModeVco) {
1195 telConfig.ttyMode = TtyMode::VCO;
1196 return OK;
1197 }
1198 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1199 AudioParameter::keyTtyMode, mode.c_str());
1200 return BAD_VALUE;
1201 }));
1202 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1203 parameters, String8(AudioParameter::keyHacSetting),
1204 [&telConfig](const String8& onOrOff) {
1205 if (onOrOff == AudioParameter::valueHacOn) {
1206 telConfig.isHacEnabled = Boolean{ .value = true };
1207 return OK;
1208 } else if (onOrOff == AudioParameter::valueHacOff) {
1209 telConfig.isHacEnabled = Boolean{ .value = false };
1210 return OK;
1211 }
1212 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1213 AudioParameter::keyHacSetting, onOrOff.c_str());
1214 return BAD_VALUE;
1215 }));
1216 if (mTelephony != nullptr && telConfig != ITelephony::TelecomConfig{}) {
1217 ITelephony::TelecomConfig newTelConfig;
1218 return statusTFromBinderStatus(
1219 mTelephony->setTelecomConfig(telConfig, &newTelConfig));
1220 }
1221 return OK;
1222}
1223
Mikhail Naganovdfd594e2023-02-08 16:59:41 -08001224void DeviceHalAidl::clearCallbacks(void* cookie) {
1225 std::lock_guard l(mLock);
1226 mCallbacks.erase(cookie);
1227}
1228
1229sp<StreamOutHalInterfaceCallback> DeviceHalAidl::getStreamOutCallback(void* cookie) {
1230 return getCallbackImpl(cookie, &Callbacks::out);
1231}
1232
1233void DeviceHalAidl::setStreamOutCallback(
1234 void* cookie, const sp<StreamOutHalInterfaceCallback>& cb) {
1235 setCallbackImpl(cookie, &Callbacks::out, cb);
1236}
1237
1238sp<StreamOutHalInterfaceEventCallback> DeviceHalAidl::getStreamOutEventCallback(
1239 void* cookie) {
1240 return getCallbackImpl(cookie, &Callbacks::event);
1241}
1242
1243void DeviceHalAidl::setStreamOutEventCallback(
1244 void* cookie, const sp<StreamOutHalInterfaceEventCallback>& cb) {
1245 setCallbackImpl(cookie, &Callbacks::event, cb);
1246}
1247
1248sp<StreamOutHalInterfaceLatencyModeCallback> DeviceHalAidl::getStreamOutLatencyModeCallback(
1249 void* cookie) {
1250 return getCallbackImpl(cookie, &Callbacks::latency);
1251}
1252
1253void DeviceHalAidl::setStreamOutLatencyModeCallback(
1254 void* cookie, const sp<StreamOutHalInterfaceLatencyModeCallback>& cb) {
1255 setCallbackImpl(cookie, &Callbacks::latency, cb);
1256}
1257
1258template<class C>
1259sp<C> DeviceHalAidl::getCallbackImpl(void* cookie, wp<C> DeviceHalAidl::Callbacks::* field) {
1260 std::lock_guard l(mLock);
1261 if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
1262 return ((it->second).*field).promote();
1263 }
1264 return nullptr;
1265}
1266template<class C>
1267void DeviceHalAidl::setCallbackImpl(
1268 void* cookie, wp<C> DeviceHalAidl::Callbacks::* field, const sp<C>& cb) {
1269 std::lock_guard l(mLock);
1270 if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
1271 (it->second).*field = cb;
1272 }
1273}
1274
Mikhail Naganov31d46652023-01-10 18:29:25 +00001275} // namespace android