blob: 8a843ed8456b1dc18527f194ae76a141f63eca9a [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 Naganov5b1eed12023-01-25 11:29:11 -0800451 ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamArguments args;
452 args.portConfigId = mixPortConfig.id;
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800453 const bool isOffload = isBitPositionFlagSet(
454 aidlOutputFlags, AudioOutputFlags::COMPRESS_OFFLOAD);
455 std::shared_ptr<OutputStreamCallbackAidl> streamCb;
456 if (isOffload) {
457 streamCb = ndk::SharedRefBase::make<OutputStreamCallbackAidl>(this);
458 }
459 auto eventCb = ndk::SharedRefBase::make<OutputStreamEventCallbackAidl>(this);
460 if (isOffload) {
461 args.offloadInfo = aidlConfig.offloadInfo;
462 args.callback = streamCb;
463 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800464 args.bufferSizeFrames = aidlConfig.frameCount;
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800465 args.eventCallback = eventCb;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800466 ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamReturn ret;
467 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openOutputStream(args, &ret)));
Mikhail Naganov712d71b2023-02-23 17:57:16 -0800468 StreamContextAidl context(ret.desc, isOffload);
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800469 if (!context.isValid()) {
470 ALOGE("%s: Failed to created a valid stream context from the descriptor: %s",
471 __func__, ret.desc.toString().c_str());
472 return NO_INIT;
473 }
Mikhail Naganove93a0862023-03-15 17:06:59 -0700474 *outStream = sp<StreamOutHalAidl>::make(*config, std::move(context), aidlPatch.latenciesMs[0],
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700475 std::move(ret.stream), mVendorExt, this /*callbackBroker*/);
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800476 void* cbCookie = (*outStream).get();
477 {
478 std::lock_guard l(mLock);
479 mCallbacks.emplace(cbCookie, Callbacks{});
Mikhail Naganov78f7f9a2023-11-16 15:49:23 -0800480 mMapper.addStream(*outStream, mixPortConfig.id, aidlPatch.id);
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800481 }
482 if (streamCb) streamCb->setCookie(cbCookie);
483 eventCb->setCookie(cbCookie);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800484 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000485 return OK;
486}
487
Mikhail Naganov31d46652023-01-10 18:29:25 +0000488status_t DeviceHalAidl::openInputStream(
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800489 audio_io_handle_t handle, audio_devices_t devices,
490 struct audio_config* config, audio_input_flags_t flags,
491 const char* address, audio_source_t source,
492 audio_devices_t outputDevice, const char* outputDeviceAddress,
Mikhail Naganov31d46652023-01-10 18:29:25 +0000493 sp<StreamInHalInterface>* inStream) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800494 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700495 TIME_CHECK();
496 if (mModule == nullptr) return NO_INIT;
497 if (inStream == nullptr || config == nullptr) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000498 return BAD_VALUE;
499 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700500 constexpr bool isInput = true;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800501 int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
502 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(handle));
503 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700504 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, isInput));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800505 AudioDevice aidlDevice = VALUE_OR_RETURN_STATUS(
506 ::aidl::android::legacy2aidl_audio_device_AudioDevice(devices, address));
507 int32_t aidlInputFlags = VALUE_OR_RETURN_STATUS(
508 ::aidl::android::legacy2aidl_audio_input_flags_t_int32_t_mask(flags));
509 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::input>(aidlInputFlags);
510 AudioSource aidlSource = VALUE_OR_RETURN_STATUS(
511 ::aidl::android::legacy2aidl_audio_source_t_AudioSource(source));
512 AudioPortConfig mixPortConfig;
Mikhail Naganove93a0862023-03-15 17:06:59 -0700513 AudioPatch aidlPatch;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700514 Hal2AidlMapper::Cleanups cleanups(mMapperAccessor);
515 {
516 std::lock_guard l(mLock);
517 RETURN_STATUS_IF_ERROR(mMapper.prepareToOpenStream(
518 aidlHandle, aidlDevice, aidlFlags, aidlSource,
519 &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
520 }
521 *config = VALUE_OR_RETURN_STATUS(
522 ::aidl::android::aidl2legacy_AudioConfig_audio_config_t(aidlConfig, isInput));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800523 ::aidl::android::hardware::audio::core::IModule::OpenInputStreamArguments args;
524 args.portConfigId = mixPortConfig.id;
525 RecordTrackMetadata aidlTrackMetadata{
526 .source = aidlSource, .gain = 1, .channelMask = aidlConfig.base.channelMask };
527 if (outputDevice != AUDIO_DEVICE_NONE) {
528 aidlTrackMetadata.destinationDevice = VALUE_OR_RETURN_STATUS(
529 ::aidl::android::legacy2aidl_audio_device_AudioDevice(
530 outputDevice, outputDeviceAddress));
531 }
532 args.sinkMetadata.tracks.push_back(std::move(aidlTrackMetadata));
533 args.bufferSizeFrames = aidlConfig.frameCount;
534 ::aidl::android::hardware::audio::core::IModule::OpenInputStreamReturn ret;
535 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openInputStream(args, &ret)));
Mikhail Naganov712d71b2023-02-23 17:57:16 -0800536 StreamContextAidl context(ret.desc, false /*isAsynchronous*/);
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800537 if (!context.isValid()) {
538 ALOGE("%s: Failed to created a valid stream context from the descriptor: %s",
539 __func__, ret.desc.toString().c_str());
540 return NO_INIT;
541 }
Mikhail Naganove93a0862023-03-15 17:06:59 -0700542 *inStream = sp<StreamInHalAidl>::make(*config, std::move(context), aidlPatch.latenciesMs[0],
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700543 std::move(ret.stream), mVendorExt, this /*micInfoProvider*/);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700544 {
545 std::lock_guard l(mLock);
Mikhail Naganov78f7f9a2023-11-16 15:49:23 -0800546 mMapper.addStream(*inStream, mixPortConfig.id, aidlPatch.id);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700547 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800548 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000549 return OK;
550}
551
552status_t DeviceHalAidl::supportsAudioPatches(bool* supportsPatches) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700553 if (supportsPatches == nullptr) {
554 return BAD_VALUE;
555 }
Shunkai Yao51202502022-12-12 06:11:46 +0000556 *supportsPatches = true;
557 return OK;
558}
559
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800560status_t DeviceHalAidl::createAudioPatch(unsigned int num_sources,
561 const struct audio_port_config* sources,
562 unsigned int num_sinks,
563 const struct audio_port_config* sinks,
564 audio_patch_handle_t* patch) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800565 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000566 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700567 if (mModule == nullptr) return NO_INIT;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800568 if (num_sinks > AUDIO_PATCH_PORTS_MAX || num_sources > AUDIO_PATCH_PORTS_MAX ||
569 sources == nullptr || sinks == nullptr || patch == nullptr) {
570 return BAD_VALUE;
571 }
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800572 // When the patch handle (*patch) is AUDIO_PATCH_HANDLE_NONE, it means
573 // the framework wants to create a new patch. The handle has to be generated
574 // by the HAL. Since handles generated this way can only be unique within
575 // a HAL module, the framework generates a globally unique handle, and maps
576 // it on the <HAL module, patch handle> pair.
577 // When the patch handle is set, it meant the framework intends to update
578 // an existing patch.
579 //
580 // This behavior corresponds to HAL module behavior, with the only difference
581 // that the HAL module uses `int32_t` for patch IDs. The following assert ensures
582 // that both the framework and the HAL use the same value for "no ID":
583 static_assert(AUDIO_PATCH_HANDLE_NONE == 0);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700584 int32_t aidlPatchId = static_cast<int32_t>(*patch);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800585
586 // Upon conversion, mix port configs contain audio configuration, while
587 // device port configs contain device address. This data is used to find
588 // or create HAL configs.
589 std::vector<AudioPortConfig> aidlSources, aidlSinks;
590 for (unsigned int i = 0; i < num_sources; ++i) {
591 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
592 sources[i].role, sources[i].type)) ==
593 ::aidl::android::AudioPortDirection::INPUT;
594 aidlSources.push_back(VALUE_OR_RETURN_STATUS(
595 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
596 sources[i], isInput, 0)));
597 }
598 for (unsigned int i = 0; i < num_sinks; ++i) {
599 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
600 sinks[i].role, sinks[i].type)) ==
601 ::aidl::android::AudioPortDirection::INPUT;
602 aidlSinks.push_back(VALUE_OR_RETURN_STATUS(
603 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
604 sinks[i], isInput, 0)));
605 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700606 Hal2AidlMapper::Cleanups cleanups(mMapperAccessor);
607 {
608 std::lock_guard l(mLock);
609 RETURN_STATUS_IF_ERROR(mMapper.createOrUpdatePatch(
610 aidlSources, aidlSinks, &aidlPatchId, &cleanups));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800611 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700612 *patch = static_cast<audio_patch_handle_t>(aidlPatchId);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800613 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000614 return OK;
615}
616
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800617status_t DeviceHalAidl::releaseAudioPatch(audio_patch_handle_t patch) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800618 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000619 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700620 if (mModule == nullptr) return NO_INIT;
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800621 static_assert(AUDIO_PATCH_HANDLE_NONE == 0);
622 if (patch == AUDIO_PATCH_HANDLE_NONE) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800623 return BAD_VALUE;
624 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700625 std::lock_guard l(mLock);
626 RETURN_STATUS_IF_ERROR(mMapper.releaseAudioPatch(static_cast<int32_t>(patch)));
Shunkai Yao51202502022-12-12 06:11:46 +0000627 return OK;
628}
629
Mikhail Naganove93a0862023-03-15 17:06:59 -0700630status_t DeviceHalAidl::getAudioPort(struct audio_port* port) {
Mikhail Naganove93a0862023-03-15 17:06:59 -0700631 if (port == nullptr) {
632 return BAD_VALUE;
633 }
634 audio_port_v7 portV7;
635 audio_populate_audio_port_v7(port, &portV7);
636 RETURN_STATUS_IF_ERROR(getAudioPort(&portV7));
637 return audio_populate_audio_port(&portV7, port) ? OK : BAD_VALUE;
638}
639
640status_t DeviceHalAidl::getAudioPort(struct audio_port_v7 *port) {
641 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
642 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700643 if (mModule == nullptr) return NO_INIT;
Mikhail Naganove93a0862023-03-15 17:06:59 -0700644 if (port == nullptr) {
645 return BAD_VALUE;
646 }
647 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(port->role, port->type)) ==
648 ::aidl::android::AudioPortDirection::INPUT;
649 auto aidlPort = VALUE_OR_RETURN_STATUS(
650 ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
651 if (aidlPort.ext.getTag() != AudioPortExt::device) {
652 ALOGE("%s: provided port is not a device port (module %s): %s",
653 __func__, mInstance.c_str(), aidlPort.toString().c_str());
654 return BAD_VALUE;
655 }
656 const auto& matchDevice = aidlPort.ext.get<AudioPortExt::device>().device;
657 // It seems that we don't have to call HAL since all valid ports have been added either
658 // during initialization, or while handling connection of an external device.
Mikhail Naganove93a0862023-03-15 17:06:59 -0700659 const int32_t fwkId = aidlPort.id;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700660 {
661 std::lock_guard l(mLock);
662 RETURN_STATUS_IF_ERROR(mMapper.getAudioPortCached(matchDevice, &aidlPort));
663 }
Mikhail Naganove93a0862023-03-15 17:06:59 -0700664 aidlPort.id = fwkId;
665 *port = VALUE_OR_RETURN_STATUS(::aidl::android::aidl2legacy_AudioPort_audio_port_v7(
666 aidlPort, isInput));
667 return OK;
668}
669
jiabin12537fc2023-10-12 17:56:08 +0000670status_t DeviceHalAidl::getAudioMixPort(const struct audio_port_v7 *devicePort,
671 struct audio_port_v7 *mixPort) {
672 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700673 TIME_CHECK();
674 if (mModule == nullptr) return NO_INIT;
675 if (devicePort == nullptr || mixPort == nullptr ||
676 devicePort->type != AUDIO_PORT_TYPE_DEVICE || mixPort->type != AUDIO_PORT_TYPE_MIX) {
jiabin12537fc2023-10-12 17:56:08 +0000677 return BAD_VALUE;
678 }
679 const int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
680 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(mixPort->ext.mix.handle));
jiabin12537fc2023-10-12 17:56:08 +0000681 AudioPort port;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700682 {
683 std::lock_guard l(mLock);
684 RETURN_STATUS_IF_ERROR(mMapper.getAudioMixPort(aidlHandle, &port));
jiabin12537fc2023-10-12 17:56:08 +0000685 }
686 const bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
687 mixPort->role, mixPort->type)) == ::aidl::android::AudioPortDirection::INPUT;
688 *mixPort = VALUE_OR_RETURN_STATUS(::aidl::android::aidl2legacy_AudioPort_audio_port_v7(
689 port, isInput));
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700690 return OK;
jiabin12537fc2023-10-12 17:56:08 +0000691}
692
Mikhail Naganove93a0862023-03-15 17:06:59 -0700693status_t DeviceHalAidl::setAudioPortConfig(const struct audio_port_config* config) {
694 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
695 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700696 if (mModule == nullptr) return NO_INIT;
Mikhail Naganove93a0862023-03-15 17:06:59 -0700697 if (config == nullptr) {
698 return BAD_VALUE;
699 }
700 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
701 config->role, config->type)) == ::aidl::android::AudioPortDirection::INPUT;
702 AudioPortConfig requestedPortConfig = VALUE_OR_RETURN_STATUS(
703 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
704 *config, isInput, 0 /*portId*/));
705 AudioPortConfig portConfig;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700706 std::lock_guard l(mLock);
707 return mMapper.findOrCreatePortConfig(
708 requestedPortConfig, std::set<int32_t>(), &portConfig);
Shunkai Yao51202502022-12-12 06:11:46 +0000709}
710
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800711MicrophoneInfoProvider::Info const* DeviceHalAidl::getMicrophoneInfo() {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700712 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
713 TIME_CHECK();
714 if (!mModule) return {};
715 std::lock_guard l(mLock);
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800716 if (mMicrophones.status == Microphones::Status::UNKNOWN) {
717 TIME_CHECK();
718 std::vector<MicrophoneInfo> aidlInfo;
719 status_t status = statusTFromBinderStatus(mModule->getMicrophones(&aidlInfo));
720 if (status == OK) {
721 mMicrophones.status = Microphones::Status::QUERIED;
722 mMicrophones.info = std::move(aidlInfo);
723 } else if (status == INVALID_OPERATION) {
724 mMicrophones.status = Microphones::Status::NOT_SUPPORTED;
725 } else {
726 ALOGE("%s: Unexpected status from 'IModule.getMicrophones': %d", __func__, status);
727 return {};
728 }
729 }
730 if (mMicrophones.status == Microphones::Status::QUERIED) {
731 return &mMicrophones.info;
732 }
733 return {}; // NOT_SUPPORTED
734}
735
Shunkai Yao51202502022-12-12 06:11:46 +0000736status_t DeviceHalAidl::getMicrophones(
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800737 std::vector<audio_microphone_characteristic_t>* microphones) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700738 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
739 TIME_CHECK();
740 if (mModule == nullptr) return NO_INIT;
741 if (microphones == nullptr) {
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800742 return BAD_VALUE;
743 }
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800744 auto staticInfo = getMicrophoneInfo();
745 if (!staticInfo) return INVALID_OPERATION;
746 std::vector<MicrophoneDynamicInfo> emptyDynamicInfo;
747 emptyDynamicInfo.reserve(staticInfo->size());
748 std::transform(staticInfo->begin(), staticInfo->end(), std::back_inserter(emptyDynamicInfo),
749 [](const auto& info) { return MicrophoneDynamicInfo{ .id = info.id }; });
750 *microphones = VALUE_OR_RETURN_STATUS(
751 ::aidl::android::convertContainers<std::vector<audio_microphone_characteristic_t>>(
752 *staticInfo, emptyDynamicInfo,
753 ::aidl::android::aidl2legacy_MicrophoneInfos_audio_microphone_characteristic_t)
754 );
Shunkai Yao51202502022-12-12 06:11:46 +0000755 return OK;
756}
757
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700758status_t DeviceHalAidl::addDeviceEffect(
759 const struct audio_port_config *device, sp<EffectHalInterface> effect) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700760 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700761 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700762 if (mModule == nullptr) return NO_INIT;
763 if (device == nullptr || effect == nullptr) {
Shunkai Yao51202502022-12-12 06:11:46 +0000764 return BAD_VALUE;
765 }
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700766 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
767 device->role, device->type)) == ::aidl::android::AudioPortDirection::INPUT;
768 auto requestedPortConfig = VALUE_OR_RETURN_STATUS(
769 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
770 *device, isInput, 0));
771 if (requestedPortConfig.ext.getTag() != AudioPortExt::Tag::device) {
772 ALOGE("%s: provided port config is not a device port config: %s",
773 __func__, requestedPortConfig.toString().c_str());
774 return BAD_VALUE;
775 }
776 AudioPortConfig devicePortConfig;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700777 Hal2AidlMapper::Cleanups cleanups(mMapperAccessor);
778 {
779 std::lock_guard l(mLock);
780 RETURN_STATUS_IF_ERROR(mMapper.findOrCreatePortConfig(
781 requestedPortConfig, {} /*destinationPortIds*/, &devicePortConfig, &cleanups));
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700782 }
783 auto aidlEffect = sp<effect::EffectHalAidl>::cast(effect);
784 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->addDeviceEffect(
785 devicePortConfig.id, aidlEffect->getIEffect())));
786 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000787 return OK;
788}
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700789status_t DeviceHalAidl::removeDeviceEffect(
790 const struct audio_port_config *device, sp<EffectHalInterface> effect) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700791 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700792 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700793 if (mModule == nullptr) return NO_INIT;
794 if (device == nullptr || effect == nullptr) {
Shunkai Yao51202502022-12-12 06:11:46 +0000795 return BAD_VALUE;
796 }
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700797 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
798 device->role, device->type)) == ::aidl::android::AudioPortDirection::INPUT;
799 auto requestedPortConfig = VALUE_OR_RETURN_STATUS(
800 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
801 *device, isInput, 0));
802 if (requestedPortConfig.ext.getTag() != AudioPortExt::Tag::device) {
803 ALOGE("%s: provided port config is not a device port config: %s",
804 __func__, requestedPortConfig.toString().c_str());
805 return BAD_VALUE;
806 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700807 AudioPortConfig devicePortConfig;
808 {
809 std::lock_guard l(mLock);
810 RETURN_STATUS_IF_ERROR(mMapper.findPortConfig(
811 requestedPortConfig.ext.get<AudioPortExt::Tag::device>().device,
812 &devicePortConfig));
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700813 }
814 auto aidlEffect = sp<effect::EffectHalAidl>::cast(effect);
815 return statusTFromBinderStatus(mModule->removeDeviceEffect(
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700816 devicePortConfig.id, aidlEffect->getIEffect()));
Shunkai Yao51202502022-12-12 06:11:46 +0000817}
818
819status_t DeviceHalAidl::getMmapPolicyInfos(
David Li9cf5e622023-03-21 00:51:10 +0800820 media::audio::common::AudioMMapPolicyType policyType,
821 std::vector<media::audio::common::AudioMMapPolicyInfo>* policyInfos) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700822 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000823 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700824 if (mModule == nullptr) return NO_INIT;
Mikhail Naganov25bc9a22023-04-21 18:48:16 -0700825 AudioMMapPolicyType mmapPolicyType = VALUE_OR_RETURN_STATUS(
826 cpp2ndk_AudioMMapPolicyType(policyType));
David Li9cf5e622023-03-21 00:51:10 +0800827
828 std::vector<AudioMMapPolicyInfo> mmapPolicyInfos;
829
830 if (status_t status = statusTFromBinderStatus(
831 mModule->getMmapPolicyInfos(mmapPolicyType, &mmapPolicyInfos)); status != OK) {
832 return status;
833 }
834
835 *policyInfos = VALUE_OR_RETURN_STATUS(
836 convertContainer<std::vector<media::audio::common::AudioMMapPolicyInfo>>(
837 mmapPolicyInfos, ndk2cpp_AudioMMapPolicyInfo));
Shunkai Yao51202502022-12-12 06:11:46 +0000838 return OK;
839}
840
841int32_t DeviceHalAidl::getAAudioMixerBurstCount() {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700842 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000843 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700844 if (mModule == nullptr) return NO_INIT;
David Li9cf5e622023-03-21 00:51:10 +0800845 int32_t mixerBurstCount = 0;
846 if (mModule->getAAudioMixerBurstCount(&mixerBurstCount).isOk()) {
847 return mixerBurstCount;
848 }
849 return 0;
Shunkai Yao51202502022-12-12 06:11:46 +0000850}
851
852int32_t DeviceHalAidl::getAAudioHardwareBurstMinUsec() {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700853 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000854 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700855 if (mModule == nullptr) return NO_INIT;
David Li9cf5e622023-03-21 00:51:10 +0800856 int32_t hardwareBurstMinUsec = 0;
857 if (mModule->getAAudioHardwareBurstMinUsec(&hardwareBurstMinUsec).isOk()) {
858 return hardwareBurstMinUsec;
859 }
860 return 0;
Shunkai Yao51202502022-12-12 06:11:46 +0000861}
862
863error::Result<audio_hw_sync_t> DeviceHalAidl::getHwAvSync() {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700864 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000865 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700866 if (mModule == nullptr) return NO_INIT;
Mikhail Naganov08a62ab2023-03-14 17:11:51 -0700867 int32_t aidlHwAvSync;
868 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->generateHwAvSyncId(&aidlHwAvSync)));
869 return VALUE_OR_RETURN_STATUS(
870 ::aidl::android::aidl2legacy_int32_t_audio_hw_sync_t(aidlHwAvSync));
Shunkai Yao51202502022-12-12 06:11:46 +0000871}
872
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000873status_t DeviceHalAidl::dump(int fd, const Vector<String16>& args) {
874 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700875 if (mModule == nullptr) return NO_INIT;
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000876 return mModule->dump(fd, Args(args).args(), args.size());
David Li9cf5e622023-03-21 00:51:10 +0800877}
Shunkai Yao51202502022-12-12 06:11:46 +0000878
Eric Laurent7af6ee72023-06-29 11:44:54 +0200879status_t DeviceHalAidl::supportsBluetoothVariableLatency(bool* supports) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700880 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000881 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700882 if (mModule == nullptr) return NO_INIT;
Mikhail Naganov3ac95c92023-04-12 13:14:30 -0700883 if (supports == nullptr) {
884 return BAD_VALUE;
885 }
886 return statusTFromBinderStatus(mModule->supportsVariableLatency(supports));
Shunkai Yao51202502022-12-12 06:11:46 +0000887}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000888
Vlad Popa03bd5bc2023-01-17 16:16:51 +0100889status_t DeviceHalAidl::getSoundDoseInterface(const std::string& module,
890 ::ndk::SpAIBinder* soundDoseBinder) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700891 if (soundDoseBinder == nullptr) {
892 return BAD_VALUE;
893 }
Vlad Popa03bd5bc2023-01-17 16:16:51 +0100894 if (mSoundDose == nullptr) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700895 ALOGE("%s failed to retrieve the sound dose interface for module %s",
896 __func__, module.c_str());
897 return BAD_VALUE;
Vlad Popa03bd5bc2023-01-17 16:16:51 +0100898 }
899 *soundDoseBinder = mSoundDose->asBinder();
900 ALOGI("%s using audio AIDL HAL sound dose interface", __func__);
Vlad Popa03bd5bc2023-01-17 16:16:51 +0100901 return OK;
902}
jiabin872de702023-04-27 22:04:31 +0000903
904status_t DeviceHalAidl::prepareToDisconnectExternalDevice(const struct audio_port_v7* port) {
905 // There is not AIDL API defined for `prepareToDisconnectExternalDevice`.
906 // Call `setConnectedState` instead.
907 // TODO(b/279824103): call prepareToDisconnectExternalDevice when it is added.
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700908 RETURN_STATUS_IF_ERROR(setConnectedState(port, false /*connected*/));
909 std::lock_guard l(mLock);
910 mDeviceDisconnectionNotified.insert(port->id);
Mikhail Naganov66907492023-09-11 17:22:03 -0700911 // Return that there was no error as otherwise the disconnection procedure will not be
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700912 // considered complete for upper layers, and 'setConnectedState' will not be called again
913 return OK;
jiabin872de702023-04-27 22:04:31 +0000914}
915
Mikhail Naganove93a0862023-03-15 17:06:59 -0700916status_t DeviceHalAidl::setConnectedState(const struct audio_port_v7 *port, bool connected) {
Mikhail Naganovae9063d2023-11-07 16:43:51 -0800917 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganove93a0862023-03-15 17:06:59 -0700918 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700919 if (mModule == nullptr) return NO_INIT;
Mikhail Naganove93a0862023-03-15 17:06:59 -0700920 if (port == nullptr) {
921 return BAD_VALUE;
922 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700923 if (!connected) {
924 std::lock_guard l(mLock);
925 if (mDeviceDisconnectionNotified.erase(port->id) > 0) {
926 // For device disconnection, APM will first call `prepareToDisconnectExternalDevice`
927 // and then call `setConnectedState`. However, there is no API for
928 // `prepareToDisconnectExternalDevice` yet. In that case, `setConnectedState` will be
929 // called when calling `prepareToDisconnectExternalDevice`. Do not call to the HAL if
930 // previous call is successful. Also remove the cache here to avoid a large cache after
931 // a long run.
932 return OK;
933 }
jiabin872de702023-04-27 22:04:31 +0000934 }
Mikhail Naganove93a0862023-03-15 17:06:59 -0700935 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(port->role, port->type)) ==
936 ::aidl::android::AudioPortDirection::INPUT;
937 AudioPort aidlPort = VALUE_OR_RETURN_STATUS(
938 ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
939 if (aidlPort.ext.getTag() != AudioPortExt::device) {
940 ALOGE("%s: provided port is not a device port (module %s): %s",
941 __func__, mInstance.c_str(), aidlPort.toString().c_str());
942 return BAD_VALUE;
943 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700944 std::lock_guard l(mLock);
945 return mMapper.setDevicePortConnectedState(aidlPort, connected);
Mikhail Naganove93a0862023-03-15 17:06:59 -0700946}
947
948status_t DeviceHalAidl::setSimulateDeviceConnections(bool enabled) {
949 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700950 if (mModule == nullptr) return NO_INIT;
951 {
952 std::lock_guard l(mLock);
953 mMapper.resetUnusedPatchesAndPortConfigs();
954 }
Mikhail Naganove93a0862023-03-15 17:06:59 -0700955 ModuleDebug debug{ .simulateDeviceConnections = enabled };
956 status_t status = statusTFromBinderStatus(mModule->setModuleDebug(debug));
957 // This is important to log as it affects HAL behavior.
958 if (status == OK) {
959 ALOGI("%s: set enabled: %d", __func__, enabled);
960 } else {
961 ALOGW("%s: set enabled to %d failed: %d", __func__, enabled, status);
962 }
963 return status;
964}
965
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700966status_t DeviceHalAidl::filterAndRetrieveBtA2dpParameters(
967 AudioParameter &keys, AudioParameter *result) {
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700968 if (String8 key = String8(AudioParameter::keyReconfigA2dpSupported); keys.containsKey(key)) {
969 keys.remove(key);
David Lia7761ed2023-11-03 17:22:07 +0000970 if (mBluetoothA2dp != nullptr) {
971 bool supports;
972 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
973 mBluetoothA2dp->supportsOffloadReconfiguration(&supports)));
974 result->addInt(key, supports ? 1 : 0);
975 } else {
976 ALOGI("%s: no IBluetoothA2dp on %s", __func__, mInstance.c_str());
977 result->addInt(key, 0);
978 }
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700979 }
980 return OK;
981}
982
Mikhail Naganovccc82112023-04-27 18:14:15 -0700983status_t DeviceHalAidl::filterAndUpdateBtA2dpParameters(AudioParameter &parameters) {
Mikhail Naganovccc82112023-04-27 18:14:15 -0700984 std::optional<bool> a2dpEnabled;
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700985 std::optional<std::vector<VendorParameter>> reconfigureOffload;
Mikhail Naganovccc82112023-04-27 18:14:15 -0700986 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
987 parameters, String8(AudioParameter::keyBtA2dpSuspended),
988 [&a2dpEnabled](const String8& trueOrFalse) {
989 if (trueOrFalse == AudioParameter::valueTrue) {
990 a2dpEnabled = false; // 'suspended' == true
991 return OK;
992 } else if (trueOrFalse == AudioParameter::valueFalse) {
993 a2dpEnabled = true; // 'suspended' == false
994 return OK;
995 }
996 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
997 AudioParameter::keyBtA2dpSuspended, trueOrFalse.c_str());
998 return BAD_VALUE;
999 }));
Mikhail Naganove7a26ad2023-05-25 17:36:48 -07001000 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1001 parameters, String8(AudioParameter::keyReconfigA2dp),
1002 [&](const String8& value) -> status_t {
1003 if (mVendorExt != nullptr) {
1004 std::vector<VendorParameter> result;
1005 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
1006 mVendorExt->parseBluetoothA2dpReconfigureOffload(
1007 std::string(value.c_str()), &result)));
1008 reconfigureOffload = std::move(result);
1009 } else {
1010 reconfigureOffload = std::vector<VendorParameter>();
1011 }
1012 return OK;
1013 }));
Mikhail Naganovccc82112023-04-27 18:14:15 -07001014 if (mBluetoothA2dp != nullptr && a2dpEnabled.has_value()) {
1015 return statusTFromBinderStatus(mBluetoothA2dp->setEnabled(a2dpEnabled.value()));
1016 }
Mikhail Naganove7a26ad2023-05-25 17:36:48 -07001017 if (mBluetoothA2dp != nullptr && reconfigureOffload.has_value()) {
1018 return statusTFromBinderStatus(mBluetoothA2dp->reconfigureOffload(
1019 reconfigureOffload.value()));
1020 }
Mikhail Naganovccc82112023-04-27 18:14:15 -07001021 return OK;
1022}
1023
1024status_t DeviceHalAidl::filterAndUpdateBtHfpParameters(AudioParameter &parameters) {
Mikhail Naganovccc82112023-04-27 18:14:15 -07001025 IBluetooth::HfpConfig hfpConfig;
1026 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1027 parameters, String8(AudioParameter::keyBtHfpEnable),
1028 [&hfpConfig](const String8& trueOrFalse) {
1029 if (trueOrFalse == AudioParameter::valueTrue) {
1030 hfpConfig.isEnabled = Boolean{ .value = true };
1031 return OK;
1032 } else if (trueOrFalse == AudioParameter::valueFalse) {
1033 hfpConfig.isEnabled = Boolean{ .value = false };
1034 return OK;
1035 }
1036 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1037 AudioParameter::keyBtHfpEnable, trueOrFalse.c_str());
1038 return BAD_VALUE;
1039 }));
1040 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
1041 parameters, String8(AudioParameter::keyBtHfpSamplingRate),
1042 [&hfpConfig](int sampleRate) {
1043 return sampleRate > 0 ?
1044 hfpConfig.sampleRate = Int{ .value = sampleRate }, OK : BAD_VALUE;
1045 }));
1046 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
1047 parameters, String8(AudioParameter::keyBtHfpVolume),
1048 [&hfpConfig](int volume0to15) {
1049 if (volume0to15 >= 0 && volume0to15 <= 15) {
1050 hfpConfig.volume = Float{ .value = volume0to15 / 15.0f };
1051 return OK;
1052 }
1053 return BAD_VALUE;
1054 }));
1055 if (mBluetooth != nullptr && hfpConfig != IBluetooth::HfpConfig{}) {
1056 IBluetooth::HfpConfig newHfpConfig;
1057 return statusTFromBinderStatus(mBluetooth->setHfpConfig(hfpConfig, &newHfpConfig));
1058 }
1059 return OK;
1060}
1061
1062status_t DeviceHalAidl::filterAndUpdateBtLeParameters(AudioParameter &parameters) {
Mikhail Naganovccc82112023-04-27 18:14:15 -07001063 std::optional<bool> leEnabled;
1064 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1065 parameters, String8(AudioParameter::keyBtLeSuspended),
1066 [&leEnabled](const String8& trueOrFalse) {
1067 if (trueOrFalse == AudioParameter::valueTrue) {
1068 leEnabled = false; // 'suspended' == true
1069 return OK;
1070 } else if (trueOrFalse == AudioParameter::valueFalse) {
1071 leEnabled = true; // 'suspended' == false
1072 return OK;
1073 }
1074 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1075 AudioParameter::keyBtLeSuspended, trueOrFalse.c_str());
1076 return BAD_VALUE;
1077 }));
1078 if (mBluetoothLe != nullptr && leEnabled.has_value()) {
1079 return statusTFromBinderStatus(mBluetoothLe->setEnabled(leEnabled.value()));
1080 }
1081 return OK;
1082}
1083
1084status_t DeviceHalAidl::filterAndUpdateBtScoParameters(AudioParameter &parameters) {
Mikhail Naganovccc82112023-04-27 18:14:15 -07001085 IBluetooth::ScoConfig scoConfig;
1086 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1087 parameters, String8(AudioParameter::keyBtSco),
1088 [&scoConfig](const String8& onOrOff) {
1089 if (onOrOff == AudioParameter::valueOn) {
1090 scoConfig.isEnabled = Boolean{ .value = true };
1091 return OK;
1092 } else if (onOrOff == AudioParameter::valueOff) {
1093 scoConfig.isEnabled = Boolean{ .value = false };
1094 return OK;
1095 }
1096 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1097 AudioParameter::keyBtSco, onOrOff.c_str());
1098 return BAD_VALUE;
1099 }));
1100 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1101 parameters, String8(AudioParameter::keyBtScoHeadsetName),
1102 [&scoConfig](const String8& name) {
1103 scoConfig.debugName = name;
1104 return OK;
1105 }));
1106 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1107 parameters, String8(AudioParameter::keyBtNrec),
1108 [&scoConfig](const String8& onOrOff) {
1109 if (onOrOff == AudioParameter::valueOn) {
1110 scoConfig.isNrecEnabled = Boolean{ .value = true };
1111 return OK;
1112 } else if (onOrOff == AudioParameter::valueOff) {
1113 scoConfig.isNrecEnabled = Boolean{ .value = false };
1114 return OK;
1115 }
1116 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1117 AudioParameter::keyBtNrec, onOrOff.c_str());
1118 return BAD_VALUE;
1119 }));
1120 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1121 parameters, String8(AudioParameter::keyBtScoWb),
1122 [&scoConfig](const String8& onOrOff) {
1123 if (onOrOff == AudioParameter::valueOn) {
1124 scoConfig.mode = IBluetooth::ScoConfig::Mode::SCO_WB;
1125 return OK;
1126 } else if (onOrOff == AudioParameter::valueOff) {
1127 scoConfig.mode = IBluetooth::ScoConfig::Mode::SCO;
1128 return OK;
1129 }
1130 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1131 AudioParameter::keyBtScoWb, onOrOff.c_str());
1132 return BAD_VALUE;
1133 }));
1134 if (mBluetooth != nullptr && scoConfig != IBluetooth::ScoConfig{}) {
1135 IBluetooth::ScoConfig newScoConfig;
1136 return statusTFromBinderStatus(mBluetooth->setScoConfig(scoConfig, &newScoConfig));
1137 }
1138 return OK;
1139}
1140
Mikhail Naganove92c34b2023-05-31 14:24:48 -07001141status_t DeviceHalAidl::filterAndUpdateScreenParameters(AudioParameter &parameters) {
Mikhail Naganove92c34b2023-05-31 14:24:48 -07001142 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1143 parameters, String8(AudioParameter::keyScreenState),
1144 [&](const String8& onOrOff) -> status_t {
1145 std::optional<bool> isTurnedOn;
1146 if (onOrOff == AudioParameter::valueOn) {
1147 isTurnedOn = true;
1148 } else if (onOrOff == AudioParameter::valueOff) {
1149 isTurnedOn = false;
1150 }
1151 if (!isTurnedOn.has_value()) {
1152 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1153 AudioParameter::keyScreenState, onOrOff.c_str());
1154 return BAD_VALUE;
1155 }
1156 return statusTFromBinderStatus(
1157 mModule->updateScreenState(isTurnedOn.value()));
1158 }));
1159 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
1160 parameters, String8(AudioParameter::keyScreenRotation),
1161 [&](int rotationDegrees) -> status_t {
1162 IModule::ScreenRotation rotation;
1163 switch (rotationDegrees) {
1164 case 0: rotation = IModule::ScreenRotation::DEG_0; break;
1165 case 90: rotation = IModule::ScreenRotation::DEG_90; break;
1166 case 180: rotation = IModule::ScreenRotation::DEG_180; break;
1167 case 270: rotation = IModule::ScreenRotation::DEG_270; break;
1168 default:
1169 ALOGE("setParameters: parameter key \"%s\" has invalid value %d",
1170 AudioParameter::keyScreenRotation, rotationDegrees);
1171 return BAD_VALUE;
1172 }
1173 return statusTFromBinderStatus(mModule->updateScreenRotation(rotation));
1174 }));
1175 return OK;
1176}
1177
Mikhail Naganovb9a81312023-07-18 13:55:34 -07001178status_t DeviceHalAidl::filterAndUpdateTelephonyParameters(AudioParameter &parameters) {
Mikhail Naganovb9a81312023-07-18 13:55:34 -07001179 using TtyMode = ITelephony::TelecomConfig::TtyMode;
1180 ITelephony::TelecomConfig telConfig;
1181 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1182 parameters, String8(AudioParameter::keyTtyMode),
1183 [&telConfig](const String8& mode) {
1184 if (mode == AudioParameter::valueTtyModeOff) {
1185 telConfig.ttyMode = TtyMode::OFF;
1186 return OK;
1187 } else if (mode == AudioParameter::valueTtyModeFull) {
1188 telConfig.ttyMode = TtyMode::FULL;
1189 return OK;
1190 } else if (mode == AudioParameter::valueTtyModeHco) {
1191 telConfig.ttyMode = TtyMode::HCO;
1192 return OK;
1193 } else if (mode == AudioParameter::valueTtyModeVco) {
1194 telConfig.ttyMode = TtyMode::VCO;
1195 return OK;
1196 }
1197 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1198 AudioParameter::keyTtyMode, mode.c_str());
1199 return BAD_VALUE;
1200 }));
1201 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1202 parameters, String8(AudioParameter::keyHacSetting),
1203 [&telConfig](const String8& onOrOff) {
1204 if (onOrOff == AudioParameter::valueHacOn) {
1205 telConfig.isHacEnabled = Boolean{ .value = true };
1206 return OK;
1207 } else if (onOrOff == AudioParameter::valueHacOff) {
1208 telConfig.isHacEnabled = Boolean{ .value = false };
1209 return OK;
1210 }
1211 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1212 AudioParameter::keyHacSetting, onOrOff.c_str());
1213 return BAD_VALUE;
1214 }));
1215 if (mTelephony != nullptr && telConfig != ITelephony::TelecomConfig{}) {
1216 ITelephony::TelecomConfig newTelConfig;
1217 return statusTFromBinderStatus(
1218 mTelephony->setTelecomConfig(telConfig, &newTelConfig));
1219 }
1220 return OK;
1221}
1222
Mikhail Naganovdfd594e2023-02-08 16:59:41 -08001223void DeviceHalAidl::clearCallbacks(void* cookie) {
1224 std::lock_guard l(mLock);
1225 mCallbacks.erase(cookie);
1226}
1227
1228sp<StreamOutHalInterfaceCallback> DeviceHalAidl::getStreamOutCallback(void* cookie) {
1229 return getCallbackImpl(cookie, &Callbacks::out);
1230}
1231
1232void DeviceHalAidl::setStreamOutCallback(
1233 void* cookie, const sp<StreamOutHalInterfaceCallback>& cb) {
1234 setCallbackImpl(cookie, &Callbacks::out, cb);
1235}
1236
1237sp<StreamOutHalInterfaceEventCallback> DeviceHalAidl::getStreamOutEventCallback(
1238 void* cookie) {
1239 return getCallbackImpl(cookie, &Callbacks::event);
1240}
1241
1242void DeviceHalAidl::setStreamOutEventCallback(
1243 void* cookie, const sp<StreamOutHalInterfaceEventCallback>& cb) {
1244 setCallbackImpl(cookie, &Callbacks::event, cb);
1245}
1246
1247sp<StreamOutHalInterfaceLatencyModeCallback> DeviceHalAidl::getStreamOutLatencyModeCallback(
1248 void* cookie) {
1249 return getCallbackImpl(cookie, &Callbacks::latency);
1250}
1251
1252void DeviceHalAidl::setStreamOutLatencyModeCallback(
1253 void* cookie, const sp<StreamOutHalInterfaceLatencyModeCallback>& cb) {
1254 setCallbackImpl(cookie, &Callbacks::latency, cb);
1255}
1256
1257template<class C>
1258sp<C> DeviceHalAidl::getCallbackImpl(void* cookie, wp<C> DeviceHalAidl::Callbacks::* field) {
1259 std::lock_guard l(mLock);
1260 if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
1261 return ((it->second).*field).promote();
1262 }
1263 return nullptr;
1264}
1265template<class C>
1266void DeviceHalAidl::setCallbackImpl(
1267 void* cookie, wp<C> DeviceHalAidl::Callbacks::* field, const sp<C>& cb) {
1268 std::lock_guard l(mLock);
1269 if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
1270 (it->second).*field = cb;
1271 }
1272}
1273
Mikhail Naganov31d46652023-01-10 18:29:25 +00001274} // namespace android