blob: a58ce1b212946f0444e135795e84544fc1baf9ab [file] [log] [blame]
Shunkai Yao51202502022-12-12 06:11:46 +00001/*
2 * Copyright (C) 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "DeviceHalAidl"
Vlad Popa03bd5bc2023-01-17 16:16:51 +010018// #define LOG_NDEBUG 0
Shunkai Yao51202502022-12-12 06:11:46 +000019
Mikhail Naganovf56ce782023-01-25 11:29:11 -080020#include <algorithm>
Mikhail Naganovf56ce782023-01-25 11:29:11 -080021
Mikhail Naganovb0c55252023-02-08 16:59:41 -080022#include <aidl/android/hardware/audio/core/BnStreamCallback.h>
23#include <aidl/android/hardware/audio/core/BnStreamOutEventCallback.h>
Mikhail Naganovfab697c2023-01-11 19:33:13 +000024#include <aidl/android/hardware/audio/core/StreamDescriptor.h>
25#include <error/expected_utils.h>
26#include <media/AidlConversionCppNdk.h>
Mikhail Naganovbfbb75b2023-04-21 18:48:16 -070027#include <media/AidlConversionNdkCpp.h>
Mikhail Naganovfab697c2023-01-11 19:33:13 +000028#include <media/AidlConversionUtil.h>
Mikhail Naganov31d46652023-01-10 18:29:25 +000029#include <mediautils/TimeCheck.h>
Mikhail Naganovae9063d2023-11-07 16:43:51 -080030#include <system/audio.h>
Mikhail Naganov8bd806e2023-01-30 12:33:18 -080031#include <Utils.h>
Mikhail Naganov31d46652023-01-10 18:29:25 +000032#include <utils/Log.h>
Shunkai Yao51202502022-12-12 06:11:46 +000033
Mikhail Naganov31d46652023-01-10 18:29:25 +000034#include "DeviceHalAidl.h"
Mikhail Naganova82a69d2023-06-14 16:31:32 -070035#include "EffectHalAidl.h"
Mikhail Naganov31d46652023-01-10 18:29:25 +000036#include "StreamHalAidl.h"
37
Mikhail Naganovfab697c2023-01-11 19:33:13 +000038using aidl::android::aidl_utils::statusTFromBinderStatus;
Mikhail Naganov27382bb2023-04-27 18:14:15 -070039using aidl::android::media::audio::common::Boolean;
Mikhail Naganovf56ce782023-01-25 11:29:11 -080040using aidl::android::media::audio::common::AudioConfig;
41using aidl::android::media::audio::common::AudioDevice;
Mikhail Naganov8bd806e2023-01-30 12:33:18 -080042using aidl::android::media::audio::common::AudioDeviceType;
Mikhail Naganovf56ce782023-01-25 11:29:11 -080043using aidl::android::media::audio::common::AudioIoFlags;
Mikhail Naganovb0c55252023-02-08 16:59:41 -080044using aidl::android::media::audio::common::AudioLatencyMode;
David Li9cf5e622023-03-21 00:51:10 +080045using aidl::android::media::audio::common::AudioMMapPolicy;
46using aidl::android::media::audio::common::AudioMMapPolicyInfo;
47using aidl::android::media::audio::common::AudioMMapPolicyType;
Mikhail Naganovfab697c2023-01-11 19:33:13 +000048using aidl::android::media::audio::common::AudioMode;
Mikhail Naganovf56ce782023-01-25 11:29:11 -080049using aidl::android::media::audio::common::AudioOutputFlags;
50using aidl::android::media::audio::common::AudioPort;
51using aidl::android::media::audio::common::AudioPortConfig;
David Li9cf5e622023-03-21 00:51:10 +080052using aidl::android::media::audio::common::AudioPortExt;
Mikhail Naganovf56ce782023-01-25 11:29:11 -080053using aidl::android::media::audio::common::AudioSource;
Mikhail Naganovfab697c2023-01-11 19:33:13 +000054using aidl::android::media::audio::common::Float;
David Li9cf5e622023-03-21 00:51:10 +080055using aidl::android::media::audio::common::Int;
56using aidl::android::media::audio::common::MicrophoneDynamicInfo;
57using aidl::android::media::audio::common::MicrophoneInfo;
Mikhail Naganove7a26ad2023-05-25 17:36:48 -070058using aidl::android::media::audio::IHalAdapterVendorExtension;
Mikhail Naganov6352e822023-03-09 18:22:36 -080059using aidl::android::hardware::audio::common::getFrameSizeInBytes;
60using aidl::android::hardware::audio::common::isBitPositionFlagSet;
Mikhail Naganovf56ce782023-01-25 11:29:11 -080061using aidl::android::hardware::audio::common::RecordTrackMetadata;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -070062using aidl::android::hardware::audio::core::sounddose::ISoundDose;
Mikhail Naganovf56ce782023-01-25 11:29:11 -080063using aidl::android::hardware::audio::core::AudioPatch;
Mikhail Naganovecfafb72023-03-29 10:06:15 -070064using aidl::android::hardware::audio::core::AudioRoute;
Mikhail Naganov27382bb2023-04-27 18:14:15 -070065using aidl::android::hardware::audio::core::IBluetooth;
66using aidl::android::hardware::audio::core::IBluetoothA2dp;
67using aidl::android::hardware::audio::core::IBluetoothLe;
Mikhail Naganovfab697c2023-01-11 19:33:13 +000068using aidl::android::hardware::audio::core::IModule;
69using aidl::android::hardware::audio::core::ITelephony;
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -070070using aidl::android::hardware::audio::core::ModuleDebug;
Mikhail Naganove7a26ad2023-05-25 17:36:48 -070071using aidl::android::hardware::audio::core::VendorParameter;
Mikhail Naganov31d46652023-01-10 18:29:25 +000072
73namespace android {
74
Mikhail Naganovf56ce782023-01-25 11:29:11 -080075namespace {
76
Mikhail Naganov2d814892023-04-24 13:06:04 -070077// Note: these converters are for types defined in different AIDL files. Although these
78// AIDL files are copies of each other, however formally these are different types
79// thus we don't use a conversion via a parcelable.
80ConversionResult<media::AudioRoute> ndk2cpp_AudioRoute(const AudioRoute& ndk) {
81 media::AudioRoute cpp;
82 cpp.sourcePortIds.insert(
83 cpp.sourcePortIds.end(), ndk.sourcePortIds.begin(), ndk.sourcePortIds.end());
84 cpp.sinkPortId = ndk.sinkPortId;
85 cpp.isExclusive = ndk.isExclusive;
86 return cpp;
87}
88
Mikhail Naganovffd97712023-05-03 17:45:36 -070089template<typename T>
90std::shared_ptr<T> retrieveSubInterface(const std::shared_ptr<IModule>& module,
91 ::ndk::ScopedAStatus (IModule::*getT)(std::shared_ptr<T>*)) {
92 if (module != nullptr) {
93 std::shared_ptr<T> instance;
94 if (auto status = (module.get()->*getT)(&instance); status.isOk()) {
95 return instance;
96 }
97 }
98 return nullptr;
99}
100
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800101} // namespace
102
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700103DeviceHalAidl::DeviceHalAidl(const std::string& instance, const std::shared_ptr<IModule>& module,
104 const std::shared_ptr<IHalAdapterVendorExtension>& vext)
Mikhail Naganovffd97712023-05-03 17:45:36 -0700105 : ConversionHelperAidl("DeviceHalAidl"),
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700106 mInstance(instance), mModule(module), mVendorExt(vext),
Mikhail Naganov27382bb2023-04-27 18:14:15 -0700107 mTelephony(retrieveSubInterface<ITelephony>(module, &IModule::getTelephony)),
108 mBluetooth(retrieveSubInterface<IBluetooth>(module, &IModule::getBluetooth)),
109 mBluetoothA2dp(retrieveSubInterface<IBluetoothA2dp>(module, &IModule::getBluetoothA2dp)),
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700110 mBluetoothLe(retrieveSubInterface<IBluetoothLe>(module, &IModule::getBluetoothLe)),
111 mSoundDose(retrieveSubInterface<ISoundDose>(module, &IModule::getSoundDose)),
112 mMapper(instance, module), mMapperAccessor(mMapper, mLock) {
Mikhail Naganovffd97712023-05-03 17:45:36 -0700113}
114
Mikhail Naganov2d814892023-04-24 13:06:04 -0700115status_t DeviceHalAidl::getAudioPorts(std::vector<media::audio::common::AudioPort> *ports) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700116 std::lock_guard l(mLock);
117 return mMapper.getAudioPorts(ports, ndk2cpp_AudioPort);
Mikhail Naganov2d814892023-04-24 13:06:04 -0700118}
119
120status_t DeviceHalAidl::getAudioRoutes(std::vector<media::AudioRoute> *routes) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700121 std::lock_guard l(mLock);
122 return mMapper.getAudioRoutes(routes, ndk2cpp_AudioRoute);
Mikhail Naganov2d814892023-04-24 13:06:04 -0700123}
124
Mikhail Naganovffd97712023-05-03 17:45:36 -0700125status_t DeviceHalAidl::getSupportedModes(std::vector<media::audio::common::AudioMode> *modes) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700126 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganovffd97712023-05-03 17:45:36 -0700127 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700128 if (mModule == nullptr) return NO_INIT;
129 if (mTelephony == nullptr) return INVALID_OPERATION;
Mikhail Naganovffd97712023-05-03 17:45:36 -0700130 if (modes == nullptr) {
131 return BAD_VALUE;
132 }
Mikhail Naganovffd97712023-05-03 17:45:36 -0700133 std::vector<AudioMode> aidlModes;
134 RETURN_STATUS_IF_ERROR(
135 statusTFromBinderStatus(mTelephony->getSupportedAudioModes(&aidlModes)));
136 *modes = VALUE_OR_RETURN_STATUS(
137 ::aidl::android::convertContainer<std::vector<media::audio::common::AudioMode>>(
138 aidlModes, ndk2cpp_AudioMode));
139 return OK;
140}
141
Mikhail Naganov31d46652023-01-10 18:29:25 +0000142status_t DeviceHalAidl::getSupportedDevices(uint32_t*) {
143 // Obsolete.
144 return INVALID_OPERATION;
Shunkai Yao51202502022-12-12 06:11:46 +0000145}
146
147status_t DeviceHalAidl::initCheck() {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700148 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800149 TIME_CHECK();
Mikhail Naganov31d46652023-01-10 18:29:25 +0000150 if (mModule == nullptr) return NO_INIT;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700151 std::lock_guard l(mLock);
152 return mMapper.initialize();
Shunkai Yao51202502022-12-12 06:11:46 +0000153}
154
155status_t DeviceHalAidl::setVoiceVolume(float volume) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700156 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000157 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700158 if (mModule == nullptr) return NO_INIT;
Mikhail Naganovffd97712023-05-03 17:45:36 -0700159 if (mTelephony == nullptr) return INVALID_OPERATION;
160 ITelephony::TelecomConfig inConfig{ .voiceVolume = Float{volume} }, outConfig;
161 RETURN_STATUS_IF_ERROR(
162 statusTFromBinderStatus(mTelephony->setTelecomConfig(inConfig, &outConfig)));
163 ALOGW_IF(outConfig.voiceVolume.has_value() && volume != outConfig.voiceVolume.value().value,
164 "%s: the resulting voice volume %f is not the same as requested %f",
165 __func__, outConfig.voiceVolume.value().value, volume);
166 return OK;
Shunkai Yao51202502022-12-12 06:11:46 +0000167}
168
169status_t DeviceHalAidl::setMasterVolume(float volume) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700170 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000171 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700172 if (mModule == nullptr) return NO_INIT;
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000173 return statusTFromBinderStatus(mModule->setMasterVolume(volume));
Shunkai Yao51202502022-12-12 06:11:46 +0000174}
175
176status_t DeviceHalAidl::getMasterVolume(float *volume) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700177 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000178 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700179 if (mModule == nullptr) return NO_INIT;
180 if (volume == nullptr) {
181 return BAD_VALUE;
182 }
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000183 return statusTFromBinderStatus(mModule->getMasterVolume(volume));
Shunkai Yao51202502022-12-12 06:11:46 +0000184}
185
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000186status_t DeviceHalAidl::setMode(audio_mode_t mode) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700187 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000188 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700189 if (mModule == nullptr) return NO_INIT;
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000190 AudioMode audioMode = VALUE_OR_FATAL(::aidl::android::legacy2aidl_audio_mode_t_AudioMode(mode));
Mikhail Naganovffd97712023-05-03 17:45:36 -0700191 if (mTelephony != nullptr) {
192 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mTelephony->switchAudioMode(audioMode)));
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000193 }
194 return statusTFromBinderStatus(mModule->updateAudioMode(audioMode));
Shunkai Yao51202502022-12-12 06:11:46 +0000195}
196
197status_t DeviceHalAidl::setMicMute(bool state) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700198 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000199 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700200 if (mModule == nullptr) return NO_INIT;
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000201 return statusTFromBinderStatus(mModule->setMicMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000202}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000203
Shunkai Yao51202502022-12-12 06:11:46 +0000204status_t DeviceHalAidl::getMicMute(bool *state) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700205 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000206 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700207 if (mModule == nullptr) return NO_INIT;
208 if (state == nullptr) {
209 return BAD_VALUE;
210 }
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000211 return statusTFromBinderStatus(mModule->getMicMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000212}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000213
Shunkai Yao51202502022-12-12 06:11:46 +0000214status_t DeviceHalAidl::setMasterMute(bool state) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700215 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000216 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700217 if (mModule == nullptr) return NO_INIT;
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000218 return statusTFromBinderStatus(mModule->setMasterMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000219}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000220
Shunkai Yao51202502022-12-12 06:11:46 +0000221status_t DeviceHalAidl::getMasterMute(bool *state) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700222 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000223 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700224 if (mModule == nullptr) return NO_INIT;
225 if (state == nullptr) {
226 return BAD_VALUE;
227 }
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000228 return statusTFromBinderStatus(mModule->getMasterMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000229}
230
Mikhail Naganov27382bb2023-04-27 18:14:15 -0700231status_t DeviceHalAidl::setParameters(const String8& kvPairs) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700232 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
233 TIME_CHECK();
234 if (mModule == nullptr) return NO_INIT;
Mikhail Naganov27382bb2023-04-27 18:14:15 -0700235 AudioParameter parameters(kvPairs);
236 ALOGD("%s: parameters: \"%s\"", __func__, parameters.toString().c_str());
237
238 if (status_t status = filterAndUpdateBtA2dpParameters(parameters); status != OK) {
239 ALOGW("%s: filtering or updating BT A2DP parameters failed: %d", __func__, status);
240 }
241 if (status_t status = filterAndUpdateBtHfpParameters(parameters); status != OK) {
242 ALOGW("%s: filtering or updating BT HFP parameters failed: %d", __func__, status);
243 }
244 if (status_t status = filterAndUpdateBtLeParameters(parameters); status != OK) {
245 ALOGW("%s: filtering or updating BT LE parameters failed: %d", __func__, status);
246 }
247 if (status_t status = filterAndUpdateBtScoParameters(parameters); status != OK) {
248 ALOGW("%s: filtering or updating BT SCO parameters failed: %d", __func__, status);
249 }
Mikhail Naganove92c34b2023-05-31 14:24:48 -0700250 if (status_t status = filterAndUpdateScreenParameters(parameters); status != OK) {
251 ALOGW("%s: filtering or updating screen parameters failed: %d", __func__, status);
252 }
Mikhail Naganovb9a81312023-07-18 13:55:34 -0700253 if (status_t status = filterAndUpdateTelephonyParameters(parameters); status != OK) {
254 ALOGW("%s: filtering or updating telephony parameters failed: %d", __func__, status);
255 }
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700256 return parseAndSetVendorParameters(mVendorExt, mModule, parameters);
Shunkai Yao51202502022-12-12 06:11:46 +0000257}
258
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700259status_t DeviceHalAidl::getParameters(const String8& keys, String8 *values) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700260 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000261 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700262 if (mModule == nullptr) return NO_INIT;
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700263 if (values == nullptr) {
264 return BAD_VALUE;
265 }
266 AudioParameter parameterKeys(keys), result;
267 if (status_t status = filterAndRetrieveBtA2dpParameters(parameterKeys, &result); status != OK) {
268 ALOGW("%s: filtering or retrieving BT A2DP parameters failed: %d", __func__, status);
269 }
270 *values = result.toString();
271 return parseAndGetVendorParameters(mVendorExt, mModule, parameterKeys, values);
Shunkai Yao51202502022-12-12 06:11:46 +0000272}
273
Mikhail Naganov8bd806e2023-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 Naganov8bd806e2023-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 Naganov8bd806e2023-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 Naganov8bd806e2023-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 Naganovb1ddbb02023-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 Naganov8bd806e2023-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 Naganovb0c55252023-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 Naganovf56ce782023-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 Naganov8bd806e2023-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 Naganovf56ce782023-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 Naganovf56ce782023-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 Naganovb1ddbb02023-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 Naganovf56ce782023-01-25 11:29:11 -0800451 ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamArguments args;
452 args.portConfigId = mixPortConfig.id;
Mikhail Naganovb0c55252023-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 Naganovf56ce782023-01-25 11:29:11 -0800464 args.bufferSizeFrames = aidlConfig.frameCount;
Mikhail Naganovb0c55252023-02-08 16:59:41 -0800465 args.eventCallback = eventCb;
Mikhail Naganovf56ce782023-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 Naganov8bd806e2023-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 Naganovb1ddbb02023-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 Naganovb0c55252023-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 Naganovb0c55252023-02-08 16:59:41 -0800481 }
482 if (streamCb) streamCb->setCookie(cbCookie);
483 eventCb->setCookie(cbCookie);
Mikhail Naganovf56ce782023-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 Naganovf56ce782023-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 Naganov8bd806e2023-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 Naganovf56ce782023-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 Naganovf56ce782023-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 Naganovb1ddbb02023-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 Naganovf56ce782023-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 Naganov8bd806e2023-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 Naganovb1ddbb02023-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 Naganovf56ce782023-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 Naganovf56ce782023-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 Naganov8bd806e2023-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 Naganovf56ce782023-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 Naganovf56ce782023-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 Naganovf56ce782023-01-25 11:29:11 -0800611 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700612 *patch = static_cast<audio_patch_handle_t>(aidlPatchId);
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800613 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000614 return OK;
615}
616
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800617status_t DeviceHalAidl::releaseAudioPatch(audio_patch_handle_t patch) {
Mikhail Naganov8bd806e2023-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 Naganovf56ce782023-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 Naganovb1ddbb02023-03-15 17:06:59 -0700630status_t DeviceHalAidl::getAudioPort(struct audio_port* port) {
Mikhail Naganovb1ddbb02023-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 Naganovb1ddbb02023-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 Naganovb1ddbb02023-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 Naganovb1ddbb02023-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 Naganovb1ddbb02023-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 Naganovb1ddbb02023-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 Naganovbfbb75b2023-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 Laurent8ed6d792023-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 }
Vlad Popae1f33902023-10-30 19:48:25 -0700899
900 if (mSoundDose == nullptr) {
901 ALOGE("%s failed to return the sound dose interface for module %s: not implemented",
902 __func__,
903 module.c_str());
904 return NO_INIT;
905 }
906
Vlad Popa03bd5bc2023-01-17 16:16:51 +0100907 *soundDoseBinder = mSoundDose->asBinder();
908 ALOGI("%s using audio AIDL HAL sound dose interface", __func__);
Vlad Popa03bd5bc2023-01-17 16:16:51 +0100909 return OK;
910}
911
jiabinc0048632023-04-27 22:04:31 +0000912status_t DeviceHalAidl::prepareToDisconnectExternalDevice(const struct audio_port_v7* port) {
913 // There is not AIDL API defined for `prepareToDisconnectExternalDevice`.
914 // Call `setConnectedState` instead.
915 // TODO(b/279824103): call prepareToDisconnectExternalDevice when it is added.
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700916 RETURN_STATUS_IF_ERROR(setConnectedState(port, false /*connected*/));
917 std::lock_guard l(mLock);
918 mDeviceDisconnectionNotified.insert(port->id);
Mikhail Naganov66907492023-09-11 17:22:03 -0700919 // Return that there was no error as otherwise the disconnection procedure will not be
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700920 // considered complete for upper layers, and 'setConnectedState' will not be called again
921 return OK;
jiabinc0048632023-04-27 22:04:31 +0000922}
923
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700924status_t DeviceHalAidl::setConnectedState(const struct audio_port_v7 *port, bool connected) {
Mikhail Naganovae9063d2023-11-07 16:43:51 -0800925 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700926 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700927 if (mModule == nullptr) return NO_INIT;
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700928 if (port == nullptr) {
929 return BAD_VALUE;
930 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700931 if (!connected) {
932 std::lock_guard l(mLock);
933 if (mDeviceDisconnectionNotified.erase(port->id) > 0) {
934 // For device disconnection, APM will first call `prepareToDisconnectExternalDevice`
935 // and then call `setConnectedState`. However, there is no API for
936 // `prepareToDisconnectExternalDevice` yet. In that case, `setConnectedState` will be
937 // called when calling `prepareToDisconnectExternalDevice`. Do not call to the HAL if
938 // previous call is successful. Also remove the cache here to avoid a large cache after
939 // a long run.
940 return OK;
941 }
jiabinc0048632023-04-27 22:04:31 +0000942 }
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700943 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(port->role, port->type)) ==
944 ::aidl::android::AudioPortDirection::INPUT;
945 AudioPort aidlPort = VALUE_OR_RETURN_STATUS(
946 ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
947 if (aidlPort.ext.getTag() != AudioPortExt::device) {
948 ALOGE("%s: provided port is not a device port (module %s): %s",
949 __func__, mInstance.c_str(), aidlPort.toString().c_str());
950 return BAD_VALUE;
951 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700952 std::lock_guard l(mLock);
953 return mMapper.setDevicePortConnectedState(aidlPort, connected);
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700954}
955
956status_t DeviceHalAidl::setSimulateDeviceConnections(bool enabled) {
957 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700958 if (mModule == nullptr) return NO_INIT;
959 {
960 std::lock_guard l(mLock);
961 mMapper.resetUnusedPatchesAndPortConfigs();
962 }
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700963 ModuleDebug debug{ .simulateDeviceConnections = enabled };
964 status_t status = statusTFromBinderStatus(mModule->setModuleDebug(debug));
965 // This is important to log as it affects HAL behavior.
966 if (status == OK) {
967 ALOGI("%s: set enabled: %d", __func__, enabled);
968 } else {
969 ALOGW("%s: set enabled to %d failed: %d", __func__, enabled, status);
970 }
971 return status;
972}
973
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700974status_t DeviceHalAidl::filterAndRetrieveBtA2dpParameters(
975 AudioParameter &keys, AudioParameter *result) {
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700976 if (String8 key = String8(AudioParameter::keyReconfigA2dpSupported); keys.containsKey(key)) {
977 keys.remove(key);
David Li8bb0cea2023-11-03 12:46:38 +0800978 if (mBluetoothA2dp != nullptr) {
979 bool supports;
980 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
981 mBluetoothA2dp->supportsOffloadReconfiguration(&supports)));
982 result->addInt(key, supports ? 1 : 0);
983 } else {
984 ALOGI("%s: no IBluetoothA2dp on %s", __func__, mInstance.c_str());
985 result->addInt(key, 0);
986 }
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700987 }
988 return OK;
989}
990
Mikhail Naganov27382bb2023-04-27 18:14:15 -0700991status_t DeviceHalAidl::filterAndUpdateBtA2dpParameters(AudioParameter &parameters) {
Mikhail Naganov27382bb2023-04-27 18:14:15 -0700992 std::optional<bool> a2dpEnabled;
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700993 std::optional<std::vector<VendorParameter>> reconfigureOffload;
Mikhail Naganov27382bb2023-04-27 18:14:15 -0700994 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
995 parameters, String8(AudioParameter::keyBtA2dpSuspended),
996 [&a2dpEnabled](const String8& trueOrFalse) {
997 if (trueOrFalse == AudioParameter::valueTrue) {
998 a2dpEnabled = false; // 'suspended' == true
999 return OK;
1000 } else if (trueOrFalse == AudioParameter::valueFalse) {
1001 a2dpEnabled = true; // 'suspended' == false
1002 return OK;
1003 }
1004 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1005 AudioParameter::keyBtA2dpSuspended, trueOrFalse.c_str());
1006 return BAD_VALUE;
1007 }));
Mikhail Naganove7a26ad2023-05-25 17:36:48 -07001008 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1009 parameters, String8(AudioParameter::keyReconfigA2dp),
1010 [&](const String8& value) -> status_t {
1011 if (mVendorExt != nullptr) {
1012 std::vector<VendorParameter> result;
1013 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
1014 mVendorExt->parseBluetoothA2dpReconfigureOffload(
1015 std::string(value.c_str()), &result)));
1016 reconfigureOffload = std::move(result);
1017 } else {
1018 reconfigureOffload = std::vector<VendorParameter>();
1019 }
1020 return OK;
1021 }));
Mikhail Naganov27382bb2023-04-27 18:14:15 -07001022 if (mBluetoothA2dp != nullptr && a2dpEnabled.has_value()) {
1023 return statusTFromBinderStatus(mBluetoothA2dp->setEnabled(a2dpEnabled.value()));
1024 }
Mikhail Naganove7a26ad2023-05-25 17:36:48 -07001025 if (mBluetoothA2dp != nullptr && reconfigureOffload.has_value()) {
1026 return statusTFromBinderStatus(mBluetoothA2dp->reconfigureOffload(
1027 reconfigureOffload.value()));
1028 }
Mikhail Naganov27382bb2023-04-27 18:14:15 -07001029 return OK;
1030}
1031
1032status_t DeviceHalAidl::filterAndUpdateBtHfpParameters(AudioParameter &parameters) {
Mikhail Naganov27382bb2023-04-27 18:14:15 -07001033 IBluetooth::HfpConfig hfpConfig;
1034 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1035 parameters, String8(AudioParameter::keyBtHfpEnable),
1036 [&hfpConfig](const String8& trueOrFalse) {
1037 if (trueOrFalse == AudioParameter::valueTrue) {
1038 hfpConfig.isEnabled = Boolean{ .value = true };
1039 return OK;
1040 } else if (trueOrFalse == AudioParameter::valueFalse) {
1041 hfpConfig.isEnabled = Boolean{ .value = false };
1042 return OK;
1043 }
1044 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1045 AudioParameter::keyBtHfpEnable, trueOrFalse.c_str());
1046 return BAD_VALUE;
1047 }));
1048 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
1049 parameters, String8(AudioParameter::keyBtHfpSamplingRate),
1050 [&hfpConfig](int sampleRate) {
1051 return sampleRate > 0 ?
1052 hfpConfig.sampleRate = Int{ .value = sampleRate }, OK : BAD_VALUE;
1053 }));
1054 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
1055 parameters, String8(AudioParameter::keyBtHfpVolume),
1056 [&hfpConfig](int volume0to15) {
1057 if (volume0to15 >= 0 && volume0to15 <= 15) {
1058 hfpConfig.volume = Float{ .value = volume0to15 / 15.0f };
1059 return OK;
1060 }
1061 return BAD_VALUE;
1062 }));
1063 if (mBluetooth != nullptr && hfpConfig != IBluetooth::HfpConfig{}) {
1064 IBluetooth::HfpConfig newHfpConfig;
1065 return statusTFromBinderStatus(mBluetooth->setHfpConfig(hfpConfig, &newHfpConfig));
1066 }
1067 return OK;
1068}
1069
1070status_t DeviceHalAidl::filterAndUpdateBtLeParameters(AudioParameter &parameters) {
Mikhail Naganov27382bb2023-04-27 18:14:15 -07001071 std::optional<bool> leEnabled;
1072 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1073 parameters, String8(AudioParameter::keyBtLeSuspended),
1074 [&leEnabled](const String8& trueOrFalse) {
1075 if (trueOrFalse == AudioParameter::valueTrue) {
1076 leEnabled = false; // 'suspended' == true
1077 return OK;
1078 } else if (trueOrFalse == AudioParameter::valueFalse) {
1079 leEnabled = true; // 'suspended' == false
1080 return OK;
1081 }
1082 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1083 AudioParameter::keyBtLeSuspended, trueOrFalse.c_str());
1084 return BAD_VALUE;
1085 }));
1086 if (mBluetoothLe != nullptr && leEnabled.has_value()) {
1087 return statusTFromBinderStatus(mBluetoothLe->setEnabled(leEnabled.value()));
1088 }
1089 return OK;
1090}
1091
1092status_t DeviceHalAidl::filterAndUpdateBtScoParameters(AudioParameter &parameters) {
Mikhail Naganov27382bb2023-04-27 18:14:15 -07001093 IBluetooth::ScoConfig scoConfig;
1094 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1095 parameters, String8(AudioParameter::keyBtSco),
1096 [&scoConfig](const String8& onOrOff) {
1097 if (onOrOff == AudioParameter::valueOn) {
1098 scoConfig.isEnabled = Boolean{ .value = true };
1099 return OK;
1100 } else if (onOrOff == AudioParameter::valueOff) {
1101 scoConfig.isEnabled = Boolean{ .value = false };
1102 return OK;
1103 }
1104 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1105 AudioParameter::keyBtSco, onOrOff.c_str());
1106 return BAD_VALUE;
1107 }));
1108 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1109 parameters, String8(AudioParameter::keyBtScoHeadsetName),
1110 [&scoConfig](const String8& name) {
1111 scoConfig.debugName = name;
1112 return OK;
1113 }));
1114 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1115 parameters, String8(AudioParameter::keyBtNrec),
1116 [&scoConfig](const String8& onOrOff) {
1117 if (onOrOff == AudioParameter::valueOn) {
1118 scoConfig.isNrecEnabled = Boolean{ .value = true };
1119 return OK;
1120 } else if (onOrOff == AudioParameter::valueOff) {
1121 scoConfig.isNrecEnabled = Boolean{ .value = false };
1122 return OK;
1123 }
1124 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1125 AudioParameter::keyBtNrec, onOrOff.c_str());
1126 return BAD_VALUE;
1127 }));
1128 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1129 parameters, String8(AudioParameter::keyBtScoWb),
1130 [&scoConfig](const String8& onOrOff) {
1131 if (onOrOff == AudioParameter::valueOn) {
1132 scoConfig.mode = IBluetooth::ScoConfig::Mode::SCO_WB;
1133 return OK;
1134 } else if (onOrOff == AudioParameter::valueOff) {
1135 scoConfig.mode = IBluetooth::ScoConfig::Mode::SCO;
1136 return OK;
1137 }
1138 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1139 AudioParameter::keyBtScoWb, onOrOff.c_str());
1140 return BAD_VALUE;
1141 }));
1142 if (mBluetooth != nullptr && scoConfig != IBluetooth::ScoConfig{}) {
1143 IBluetooth::ScoConfig newScoConfig;
1144 return statusTFromBinderStatus(mBluetooth->setScoConfig(scoConfig, &newScoConfig));
1145 }
1146 return OK;
1147}
1148
Mikhail Naganove92c34b2023-05-31 14:24:48 -07001149status_t DeviceHalAidl::filterAndUpdateScreenParameters(AudioParameter &parameters) {
Mikhail Naganove92c34b2023-05-31 14:24:48 -07001150 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1151 parameters, String8(AudioParameter::keyScreenState),
1152 [&](const String8& onOrOff) -> status_t {
1153 std::optional<bool> isTurnedOn;
1154 if (onOrOff == AudioParameter::valueOn) {
1155 isTurnedOn = true;
1156 } else if (onOrOff == AudioParameter::valueOff) {
1157 isTurnedOn = false;
1158 }
1159 if (!isTurnedOn.has_value()) {
1160 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1161 AudioParameter::keyScreenState, onOrOff.c_str());
1162 return BAD_VALUE;
1163 }
1164 return statusTFromBinderStatus(
1165 mModule->updateScreenState(isTurnedOn.value()));
1166 }));
1167 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
1168 parameters, String8(AudioParameter::keyScreenRotation),
1169 [&](int rotationDegrees) -> status_t {
1170 IModule::ScreenRotation rotation;
1171 switch (rotationDegrees) {
1172 case 0: rotation = IModule::ScreenRotation::DEG_0; break;
1173 case 90: rotation = IModule::ScreenRotation::DEG_90; break;
1174 case 180: rotation = IModule::ScreenRotation::DEG_180; break;
1175 case 270: rotation = IModule::ScreenRotation::DEG_270; break;
1176 default:
1177 ALOGE("setParameters: parameter key \"%s\" has invalid value %d",
1178 AudioParameter::keyScreenRotation, rotationDegrees);
1179 return BAD_VALUE;
1180 }
1181 return statusTFromBinderStatus(mModule->updateScreenRotation(rotation));
1182 }));
1183 return OK;
1184}
1185
Mikhail Naganovb9a81312023-07-18 13:55:34 -07001186status_t DeviceHalAidl::filterAndUpdateTelephonyParameters(AudioParameter &parameters) {
Mikhail Naganovb9a81312023-07-18 13:55:34 -07001187 using TtyMode = ITelephony::TelecomConfig::TtyMode;
1188 ITelephony::TelecomConfig telConfig;
1189 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1190 parameters, String8(AudioParameter::keyTtyMode),
1191 [&telConfig](const String8& mode) {
1192 if (mode == AudioParameter::valueTtyModeOff) {
1193 telConfig.ttyMode = TtyMode::OFF;
1194 return OK;
1195 } else if (mode == AudioParameter::valueTtyModeFull) {
1196 telConfig.ttyMode = TtyMode::FULL;
1197 return OK;
1198 } else if (mode == AudioParameter::valueTtyModeHco) {
1199 telConfig.ttyMode = TtyMode::HCO;
1200 return OK;
1201 } else if (mode == AudioParameter::valueTtyModeVco) {
1202 telConfig.ttyMode = TtyMode::VCO;
1203 return OK;
1204 }
1205 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1206 AudioParameter::keyTtyMode, mode.c_str());
1207 return BAD_VALUE;
1208 }));
1209 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1210 parameters, String8(AudioParameter::keyHacSetting),
1211 [&telConfig](const String8& onOrOff) {
1212 if (onOrOff == AudioParameter::valueHacOn) {
1213 telConfig.isHacEnabled = Boolean{ .value = true };
1214 return OK;
1215 } else if (onOrOff == AudioParameter::valueHacOff) {
1216 telConfig.isHacEnabled = Boolean{ .value = false };
1217 return OK;
1218 }
1219 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1220 AudioParameter::keyHacSetting, onOrOff.c_str());
1221 return BAD_VALUE;
1222 }));
1223 if (mTelephony != nullptr && telConfig != ITelephony::TelecomConfig{}) {
1224 ITelephony::TelecomConfig newTelConfig;
1225 return statusTFromBinderStatus(
1226 mTelephony->setTelecomConfig(telConfig, &newTelConfig));
1227 }
1228 return OK;
1229}
1230
Mikhail Naganovb0c55252023-02-08 16:59:41 -08001231void DeviceHalAidl::clearCallbacks(void* cookie) {
1232 std::lock_guard l(mLock);
1233 mCallbacks.erase(cookie);
1234}
1235
1236sp<StreamOutHalInterfaceCallback> DeviceHalAidl::getStreamOutCallback(void* cookie) {
1237 return getCallbackImpl(cookie, &Callbacks::out);
1238}
1239
1240void DeviceHalAidl::setStreamOutCallback(
1241 void* cookie, const sp<StreamOutHalInterfaceCallback>& cb) {
1242 setCallbackImpl(cookie, &Callbacks::out, cb);
1243}
1244
1245sp<StreamOutHalInterfaceEventCallback> DeviceHalAidl::getStreamOutEventCallback(
1246 void* cookie) {
1247 return getCallbackImpl(cookie, &Callbacks::event);
1248}
1249
1250void DeviceHalAidl::setStreamOutEventCallback(
1251 void* cookie, const sp<StreamOutHalInterfaceEventCallback>& cb) {
1252 setCallbackImpl(cookie, &Callbacks::event, cb);
1253}
1254
1255sp<StreamOutHalInterfaceLatencyModeCallback> DeviceHalAidl::getStreamOutLatencyModeCallback(
1256 void* cookie) {
1257 return getCallbackImpl(cookie, &Callbacks::latency);
1258}
1259
1260void DeviceHalAidl::setStreamOutLatencyModeCallback(
1261 void* cookie, const sp<StreamOutHalInterfaceLatencyModeCallback>& cb) {
1262 setCallbackImpl(cookie, &Callbacks::latency, cb);
1263}
1264
1265template<class C>
1266sp<C> DeviceHalAidl::getCallbackImpl(void* cookie, wp<C> DeviceHalAidl::Callbacks::* field) {
1267 std::lock_guard l(mLock);
1268 if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
1269 return ((it->second).*field).promote();
1270 }
1271 return nullptr;
1272}
1273template<class C>
1274void DeviceHalAidl::setCallbackImpl(
1275 void* cookie, wp<C> DeviceHalAidl::Callbacks::* field, const sp<C>& cb) {
1276 std::lock_guard l(mLock);
1277 if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
1278 (it->second).*field = cb;
1279 }
1280}
1281
Mikhail Naganov31d46652023-01-10 18:29:25 +00001282} // namespace android