blob: 2f2f69f11622029e304031a6089339d5293d1286 [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 }
Eric Laurent7e3c0832023-11-30 15:04:50 +0100270 if (status_t status = filterAndRetrieveBtLeParameters(parameterKeys, &result); status != OK) {
271 ALOGW("%s: filtering or retrieving BT LE parameters failed: %d", __func__, status);
272 }
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700273 *values = result.toString();
274 return parseAndGetVendorParameters(mVendorExt, mModule, parameterKeys, values);
Shunkai Yao51202502022-12-12 06:11:46 +0000275}
276
Mikhail Naganovd5b643f2024-02-15 11:51:26 -0800277status_t DeviceHalAidl::getInputBufferSize(struct audio_config* config, size_t* size) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800278 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800279 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700280 if (mModule == nullptr) return NO_INIT;
281 if (config == nullptr || size == nullptr) {
282 return BAD_VALUE;
283 }
Mikhail Naganovd5b643f2024-02-15 11:51:26 -0800284 constexpr bool isInput = true;
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800285 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
Mikhail Naganovd5b643f2024-02-15 11:51:26 -0800286 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, isInput));
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800287 AudioDevice aidlDevice;
288 aidlDevice.type.type = AudioDeviceType::IN_DEFAULT;
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800289 AudioSource aidlSource = AudioSource::DEFAULT;
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800290 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::input>(0);
291 AudioPortConfig mixPortConfig;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700292 Hal2AidlMapper::Cleanups cleanups(mMapperAccessor);
Mikhail Naganove93a0862023-03-15 17:06:59 -0700293 AudioPatch aidlPatch;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700294 {
295 std::lock_guard l(mLock);
296 RETURN_STATUS_IF_ERROR(mMapper.prepareToOpenStream(
297 0 /*handle*/, aidlDevice, aidlFlags, aidlSource,
298 &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
299 }
Mikhail Naganovd5b643f2024-02-15 11:51:26 -0800300 *config = VALUE_OR_RETURN_STATUS(
301 ::aidl::android::aidl2legacy_AudioConfig_audio_config_t(aidlConfig, isInput));
302 if (mixPortConfig.id == 0) return BAD_VALUE; // HAL suggests a different config.
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800303 *size = aidlConfig.frameCount *
304 getFrameSizeInBytes(aidlConfig.base.format, aidlConfig.base.channelMask);
305 // Do not disarm cleanups to release temporary port configs.
306 return OK;
307}
308
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800309namespace {
310
311class StreamCallbackBase {
312 protected:
313 explicit StreamCallbackBase(const sp<CallbackBroker>& broker) : mBroker(broker) {}
314 public:
315 void* getCookie() const { return mCookie; }
316 void setCookie(void* cookie) { mCookie = cookie; }
317 sp<CallbackBroker> getBroker() const {
318 if (void* cookie = mCookie; cookie != nullptr) return mBroker.promote();
319 return nullptr;
320 }
321 private:
322 const wp<CallbackBroker> mBroker;
323 std::atomic<void*> mCookie;
324};
325
326template<class C>
327class StreamCallbackBaseHelper {
328 protected:
329 explicit StreamCallbackBaseHelper(const StreamCallbackBase& base) : mBase(base) {}
330 sp<C> getCb(const sp<CallbackBroker>& broker, void* cookie);
331 using CbRef = const sp<C>&;
332 ndk::ScopedAStatus runCb(const std::function<void(CbRef cb)>& f) {
333 if (auto cb = getCb(mBase.getBroker(), mBase.getCookie()); cb != nullptr) f(cb);
334 return ndk::ScopedAStatus::ok();
335 }
336 private:
337 const StreamCallbackBase& mBase;
338};
339
340template<>
341sp<StreamOutHalInterfaceCallback> StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>::getCb(
342 const sp<CallbackBroker>& broker, void* cookie) {
343 if (broker != nullptr) return broker->getStreamOutCallback(cookie);
344 return nullptr;
345}
346
347template<>
348sp<StreamOutHalInterfaceEventCallback>
349StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>::getCb(
350 const sp<CallbackBroker>& broker, void* cookie) {
351 if (broker != nullptr) return broker->getStreamOutEventCallback(cookie);
352 return nullptr;
353}
354
355template<>
356sp<StreamOutHalInterfaceLatencyModeCallback>
357StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>::getCb(
358 const sp<CallbackBroker>& broker, void* cookie) {
359 if (broker != nullptr) return broker->getStreamOutLatencyModeCallback(cookie);
360 return nullptr;
361}
362
363/*
364Note on the callback ownership.
365
366In the Binder ownership model, the server implementation is kept alive
367as long as there is any client (proxy object) alive. This is done by
368incrementing the refcount of the server-side object by the Binder framework.
369When it detects that the last client is gone, it decrements the refcount back.
370
371Thus, it is not needed to keep any references to StreamCallback on our
372side (after we have sent an instance to the client), because we are
373the server-side. The callback object will be kept alive as long as the HAL server
374holds a strong ref to IStreamCallback proxy.
375*/
376
377class OutputStreamCallbackAidl : public StreamCallbackBase,
378 public StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>,
379 public ::aidl::android::hardware::audio::core::BnStreamCallback {
380 public:
381 explicit OutputStreamCallbackAidl(const sp<CallbackBroker>& broker)
382 : StreamCallbackBase(broker),
383 StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>(
384 *static_cast<StreamCallbackBase*>(this)) {}
385 ndk::ScopedAStatus onTransferReady() override {
386 return runCb([](CbRef cb) { cb->onWriteReady(); });
387 }
388 ndk::ScopedAStatus onError() override {
Mikhail Naganovf548cd32024-05-29 17:06:46 +0000389 return runCb([](CbRef cb) { cb->onError(true /*isHardError*/); });
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800390 }
391 ndk::ScopedAStatus onDrainReady() override {
392 return runCb([](CbRef cb) { cb->onDrainReady(); });
393 }
394};
395
396class OutputStreamEventCallbackAidl :
397 public StreamCallbackBase,
398 public StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>,
399 public StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>,
400 public ::aidl::android::hardware::audio::core::BnStreamOutEventCallback {
401 public:
402 explicit OutputStreamEventCallbackAidl(const sp<CallbackBroker>& broker)
403 : StreamCallbackBase(broker),
404 StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>(
405 *static_cast<StreamCallbackBase*>(this)),
406 StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>(
407 *static_cast<StreamCallbackBase*>(this)) {}
Ryan Prichard78c5e452024-02-08 16:16:57 -0800408 ndk::ScopedAStatus onCodecFormatChanged(const std::vector<uint8_t>& halMetadata) override {
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800409 return StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>::runCb(
410 [&halMetadata](auto cb) { cb->onCodecFormatChanged(halMetadata); });
411 }
412 ndk::ScopedAStatus onRecommendedLatencyModeChanged(
413 const std::vector<AudioLatencyMode>& in_modes) override {
414 auto halModes = VALUE_OR_FATAL(
415 ::aidl::android::convertContainer<std::vector<audio_latency_mode_t>>(
416 in_modes,
417 ::aidl::android::aidl2legacy_AudioLatencyMode_audio_latency_mode_t));
418 return StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>::runCb(
419 [&halModes](auto cb) { cb->onRecommendedLatencyModeChanged(halModes); });
420 }
421};
422
423} // namespace
424
Mikhail Naganov31d46652023-01-10 18:29:25 +0000425status_t DeviceHalAidl::openOutputStream(
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800426 audio_io_handle_t handle, audio_devices_t devices,
427 audio_output_flags_t flags, struct audio_config* config,
428 const char* address,
Mikhail Naganov31d46652023-01-10 18:29:25 +0000429 sp<StreamOutHalInterface>* outStream) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800430 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700431 TIME_CHECK();
432 if (mModule == nullptr) return NO_INIT;
433 if (outStream == nullptr || config == nullptr) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000434 return BAD_VALUE;
435 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700436 constexpr bool isInput = false;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800437 int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
438 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(handle));
439 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700440 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, isInput));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800441 AudioDevice aidlDevice = VALUE_OR_RETURN_STATUS(
442 ::aidl::android::legacy2aidl_audio_device_AudioDevice(devices, address));
443 int32_t aidlOutputFlags = VALUE_OR_RETURN_STATUS(
444 ::aidl::android::legacy2aidl_audio_output_flags_t_int32_t_mask(flags));
445 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::output>(aidlOutputFlags);
446 AudioPortConfig mixPortConfig;
Mikhail Naganove93a0862023-03-15 17:06:59 -0700447 AudioPatch aidlPatch;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700448 Hal2AidlMapper::Cleanups cleanups(mMapperAccessor);
449 {
450 std::lock_guard l(mLock);
451 RETURN_STATUS_IF_ERROR(mMapper.prepareToOpenStream(aidlHandle, aidlDevice, aidlFlags,
452 AudioSource::SYS_RESERVED_INVALID /*only needed for input*/,
453 &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
454 }
455 *config = VALUE_OR_RETURN_STATUS(
456 ::aidl::android::aidl2legacy_AudioConfig_audio_config_t(aidlConfig, isInput));
Mikhail Naganovca92a5c2023-12-07 14:00:48 -0800457 if (mixPortConfig.id == 0) return BAD_VALUE; // HAL suggests a different config.
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800458 ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamArguments args;
459 args.portConfigId = mixPortConfig.id;
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800460 const bool isOffload = isBitPositionFlagSet(
461 aidlOutputFlags, AudioOutputFlags::COMPRESS_OFFLOAD);
Kuowei Li3b9a69d2024-06-07 17:54:32 +0800462 const bool isHwAvSync = isBitPositionFlagSet(
463 aidlOutputFlags, AudioOutputFlags::HW_AV_SYNC);
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800464 std::shared_ptr<OutputStreamCallbackAidl> streamCb;
465 if (isOffload) {
466 streamCb = ndk::SharedRefBase::make<OutputStreamCallbackAidl>(this);
467 }
468 auto eventCb = ndk::SharedRefBase::make<OutputStreamEventCallbackAidl>(this);
Kuowei Li3b9a69d2024-06-07 17:54:32 +0800469 if (isOffload || isHwAvSync) {
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800470 args.offloadInfo = aidlConfig.offloadInfo;
Kuowei Li3b9a69d2024-06-07 17:54:32 +0800471 }
472 if (isOffload) {
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800473 args.callback = streamCb;
474 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800475 args.bufferSizeFrames = aidlConfig.frameCount;
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800476 args.eventCallback = eventCb;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800477 ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamReturn ret;
478 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openOutputStream(args, &ret)));
Mikhail Naganov712d71b2023-02-23 17:57:16 -0800479 StreamContextAidl context(ret.desc, isOffload);
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800480 if (!context.isValid()) {
481 ALOGE("%s: Failed to created a valid stream context from the descriptor: %s",
482 __func__, ret.desc.toString().c_str());
483 return NO_INIT;
484 }
Mikhail Naganov23224a12024-03-28 02:15:21 +0000485 auto stream = sp<StreamOutHalAidl>::make(*config, std::move(context), aidlPatch.latenciesMs[0],
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700486 std::move(ret.stream), mVendorExt, this /*callbackBroker*/);
Mikhail Naganov23224a12024-03-28 02:15:21 +0000487 *outStream = stream;
488 /* StreamOutHalInterface* */ void* cbCookie = (*outStream).get();
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800489 {
Mikhail Naganov22578412024-08-16 16:50:34 -0700490 std::lock_guard l(mCallbacksLock);
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800491 mCallbacks.emplace(cbCookie, Callbacks{});
Mikhail Naganov22578412024-08-16 16:50:34 -0700492 }
493 {
494 std::lock_guard l(mLock);
Mikhail Naganov78f7f9a2023-11-16 15:49:23 -0800495 mMapper.addStream(*outStream, mixPortConfig.id, aidlPatch.id);
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800496 }
Mikhail Naganov23224a12024-03-28 02:15:21 +0000497 if (streamCb) {
498 streamCb->setCookie(cbCookie);
499 // Although StreamOutHalAidl implements StreamOutHalInterfaceCallback,
500 // we always go via the CallbackBroker for consistency.
501 setStreamOutCallback(cbCookie, stream);
502 }
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800503 eventCb->setCookie(cbCookie);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800504 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000505 return OK;
506}
507
Mikhail Naganov31d46652023-01-10 18:29:25 +0000508status_t DeviceHalAidl::openInputStream(
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800509 audio_io_handle_t handle, audio_devices_t devices,
510 struct audio_config* config, audio_input_flags_t flags,
511 const char* address, audio_source_t source,
512 audio_devices_t outputDevice, const char* outputDeviceAddress,
Mikhail Naganov31d46652023-01-10 18:29:25 +0000513 sp<StreamInHalInterface>* inStream) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800514 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700515 TIME_CHECK();
516 if (mModule == nullptr) return NO_INIT;
517 if (inStream == nullptr || config == nullptr) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000518 return BAD_VALUE;
519 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700520 constexpr bool isInput = true;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800521 int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
522 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(handle));
523 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700524 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, isInput));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800525 AudioDevice aidlDevice = VALUE_OR_RETURN_STATUS(
526 ::aidl::android::legacy2aidl_audio_device_AudioDevice(devices, address));
527 int32_t aidlInputFlags = VALUE_OR_RETURN_STATUS(
528 ::aidl::android::legacy2aidl_audio_input_flags_t_int32_t_mask(flags));
529 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::input>(aidlInputFlags);
530 AudioSource aidlSource = VALUE_OR_RETURN_STATUS(
531 ::aidl::android::legacy2aidl_audio_source_t_AudioSource(source));
532 AudioPortConfig mixPortConfig;
Mikhail Naganove93a0862023-03-15 17:06:59 -0700533 AudioPatch aidlPatch;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700534 Hal2AidlMapper::Cleanups cleanups(mMapperAccessor);
535 {
536 std::lock_guard l(mLock);
537 RETURN_STATUS_IF_ERROR(mMapper.prepareToOpenStream(
538 aidlHandle, aidlDevice, aidlFlags, aidlSource,
539 &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
540 }
541 *config = VALUE_OR_RETURN_STATUS(
542 ::aidl::android::aidl2legacy_AudioConfig_audio_config_t(aidlConfig, isInput));
Mikhail Naganovca92a5c2023-12-07 14:00:48 -0800543 if (mixPortConfig.id == 0) return BAD_VALUE; // HAL suggests a different config.
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800544 ::aidl::android::hardware::audio::core::IModule::OpenInputStreamArguments args;
545 args.portConfigId = mixPortConfig.id;
546 RecordTrackMetadata aidlTrackMetadata{
547 .source = aidlSource, .gain = 1, .channelMask = aidlConfig.base.channelMask };
548 if (outputDevice != AUDIO_DEVICE_NONE) {
549 aidlTrackMetadata.destinationDevice = VALUE_OR_RETURN_STATUS(
550 ::aidl::android::legacy2aidl_audio_device_AudioDevice(
551 outputDevice, outputDeviceAddress));
552 }
553 args.sinkMetadata.tracks.push_back(std::move(aidlTrackMetadata));
554 args.bufferSizeFrames = aidlConfig.frameCount;
555 ::aidl::android::hardware::audio::core::IModule::OpenInputStreamReturn ret;
556 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openInputStream(args, &ret)));
Mikhail Naganov712d71b2023-02-23 17:57:16 -0800557 StreamContextAidl context(ret.desc, false /*isAsynchronous*/);
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800558 if (!context.isValid()) {
559 ALOGE("%s: Failed to created a valid stream context from the descriptor: %s",
560 __func__, ret.desc.toString().c_str());
561 return NO_INIT;
562 }
Mikhail Naganove93a0862023-03-15 17:06:59 -0700563 *inStream = sp<StreamInHalAidl>::make(*config, std::move(context), aidlPatch.latenciesMs[0],
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700564 std::move(ret.stream), mVendorExt, this /*micInfoProvider*/);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700565 {
566 std::lock_guard l(mLock);
Mikhail Naganov78f7f9a2023-11-16 15:49:23 -0800567 mMapper.addStream(*inStream, mixPortConfig.id, aidlPatch.id);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700568 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800569 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000570 return OK;
571}
572
573status_t DeviceHalAidl::supportsAudioPatches(bool* supportsPatches) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700574 if (supportsPatches == nullptr) {
575 return BAD_VALUE;
576 }
Shunkai Yao51202502022-12-12 06:11:46 +0000577 *supportsPatches = true;
578 return OK;
579}
580
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800581status_t DeviceHalAidl::createAudioPatch(unsigned int num_sources,
582 const struct audio_port_config* sources,
583 unsigned int num_sinks,
584 const struct audio_port_config* sinks,
585 audio_patch_handle_t* patch) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800586 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000587 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700588 if (mModule == nullptr) return NO_INIT;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800589 if (num_sinks > AUDIO_PATCH_PORTS_MAX || num_sources > AUDIO_PATCH_PORTS_MAX ||
590 sources == nullptr || sinks == nullptr || patch == nullptr) {
591 return BAD_VALUE;
592 }
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800593 // When the patch handle (*patch) is AUDIO_PATCH_HANDLE_NONE, it means
594 // the framework wants to create a new patch. The handle has to be generated
595 // by the HAL. Since handles generated this way can only be unique within
596 // a HAL module, the framework generates a globally unique handle, and maps
597 // it on the <HAL module, patch handle> pair.
598 // When the patch handle is set, it meant the framework intends to update
599 // an existing patch.
600 //
601 // This behavior corresponds to HAL module behavior, with the only difference
602 // that the HAL module uses `int32_t` for patch IDs. The following assert ensures
603 // that both the framework and the HAL use the same value for "no ID":
604 static_assert(AUDIO_PATCH_HANDLE_NONE == 0);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800605
606 // Upon conversion, mix port configs contain audio configuration, while
607 // device port configs contain device address. This data is used to find
608 // or create HAL configs.
609 std::vector<AudioPortConfig> aidlSources, aidlSinks;
610 for (unsigned int i = 0; i < num_sources; ++i) {
611 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
612 sources[i].role, sources[i].type)) ==
613 ::aidl::android::AudioPortDirection::INPUT;
614 aidlSources.push_back(VALUE_OR_RETURN_STATUS(
615 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
616 sources[i], isInput, 0)));
617 }
618 for (unsigned int i = 0; i < num_sinks; ++i) {
619 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
620 sinks[i].role, sinks[i].type)) ==
621 ::aidl::android::AudioPortDirection::INPUT;
622 aidlSinks.push_back(VALUE_OR_RETURN_STATUS(
623 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
624 sinks[i], isInput, 0)));
625 }
Mikhail Naganova317a802024-03-15 18:03:10 +0000626 int32_t aidlPatchId = static_cast<int32_t>(*patch);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700627 Hal2AidlMapper::Cleanups cleanups(mMapperAccessor);
628 {
629 std::lock_guard l(mLock);
Mikhail Naganova317a802024-03-15 18:03:10 +0000630 // Check for patches that only exist for the framework, or have different HAL patch ID.
631 if (int32_t aidlHalPatchId = mMapper.findFwkPatch(aidlPatchId); aidlHalPatchId != 0) {
632 if (aidlHalPatchId == aidlPatchId) {
633 // This patch was previously released by the HAL. Thus we need to pass '0'
634 // to the HAL to obtain a new patch.
635 int32_t newAidlPatchId = 0;
636 RETURN_STATUS_IF_ERROR(mMapper.createOrUpdatePatch(
637 aidlSources, aidlSinks, &newAidlPatchId, &cleanups));
638 mMapper.updateFwkPatch(aidlPatchId, newAidlPatchId);
639 } else {
640 RETURN_STATUS_IF_ERROR(mMapper.createOrUpdatePatch(
641 aidlSources, aidlSinks, &aidlHalPatchId, &cleanups));
642 }
643 } else {
644 RETURN_STATUS_IF_ERROR(mMapper.createOrUpdatePatch(
645 aidlSources, aidlSinks, &aidlPatchId, &cleanups));
646 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800647 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700648 *patch = static_cast<audio_patch_handle_t>(aidlPatchId);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800649 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000650 return OK;
651}
652
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800653status_t DeviceHalAidl::releaseAudioPatch(audio_patch_handle_t patch) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800654 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000655 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700656 if (mModule == nullptr) return NO_INIT;
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800657 static_assert(AUDIO_PATCH_HANDLE_NONE == 0);
658 if (patch == AUDIO_PATCH_HANDLE_NONE) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800659 return BAD_VALUE;
660 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700661 std::lock_guard l(mLock);
Mikhail Naganova317a802024-03-15 18:03:10 +0000662 // Check for patches that only exist for the framework, or have different HAL patch ID.
663 int32_t aidlPatchId = static_cast<int32_t>(patch);
664 if (int32_t aidlHalPatchId = mMapper.findFwkPatch(aidlPatchId); aidlHalPatchId != 0) {
665 if (aidlHalPatchId == aidlPatchId) {
666 // This patch was previously released by the HAL, just need to finish its removal.
667 mMapper.eraseFwkPatch(aidlPatchId);
668 return OK;
669 } else {
670 // This patch has a HAL patch ID which is different
671 aidlPatchId = aidlHalPatchId;
672 }
673 }
674 RETURN_STATUS_IF_ERROR(mMapper.releaseAudioPatch(aidlPatchId));
Shunkai Yao51202502022-12-12 06:11:46 +0000675 return OK;
676}
677
Mikhail Naganove93a0862023-03-15 17:06:59 -0700678status_t DeviceHalAidl::getAudioPort(struct audio_port* port) {
Mikhail Naganove93a0862023-03-15 17:06:59 -0700679 if (port == nullptr) {
680 return BAD_VALUE;
681 }
682 audio_port_v7 portV7;
683 audio_populate_audio_port_v7(port, &portV7);
684 RETURN_STATUS_IF_ERROR(getAudioPort(&portV7));
685 return audio_populate_audio_port(&portV7, port) ? OK : BAD_VALUE;
686}
687
688status_t DeviceHalAidl::getAudioPort(struct audio_port_v7 *port) {
689 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
690 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700691 if (mModule == nullptr) return NO_INIT;
Mikhail Naganove93a0862023-03-15 17:06:59 -0700692 if (port == nullptr) {
693 return BAD_VALUE;
694 }
695 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(port->role, port->type)) ==
696 ::aidl::android::AudioPortDirection::INPUT;
697 auto aidlPort = VALUE_OR_RETURN_STATUS(
698 ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
699 if (aidlPort.ext.getTag() != AudioPortExt::device) {
700 ALOGE("%s: provided port is not a device port (module %s): %s",
701 __func__, mInstance.c_str(), aidlPort.toString().c_str());
702 return BAD_VALUE;
703 }
704 const auto& matchDevice = aidlPort.ext.get<AudioPortExt::device>().device;
705 // It seems that we don't have to call HAL since all valid ports have been added either
706 // during initialization, or while handling connection of an external device.
Mikhail Naganove93a0862023-03-15 17:06:59 -0700707 const int32_t fwkId = aidlPort.id;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700708 {
709 std::lock_guard l(mLock);
710 RETURN_STATUS_IF_ERROR(mMapper.getAudioPortCached(matchDevice, &aidlPort));
711 }
Mikhail Naganove93a0862023-03-15 17:06:59 -0700712 aidlPort.id = fwkId;
713 *port = VALUE_OR_RETURN_STATUS(::aidl::android::aidl2legacy_AudioPort_audio_port_v7(
714 aidlPort, isInput));
715 return OK;
716}
717
jiabin12537fc2023-10-12 17:56:08 +0000718status_t DeviceHalAidl::getAudioMixPort(const struct audio_port_v7 *devicePort,
719 struct audio_port_v7 *mixPort) {
720 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700721 TIME_CHECK();
722 if (mModule == nullptr) return NO_INIT;
723 if (devicePort == nullptr || mixPort == nullptr ||
724 devicePort->type != AUDIO_PORT_TYPE_DEVICE || mixPort->type != AUDIO_PORT_TYPE_MIX) {
jiabin12537fc2023-10-12 17:56:08 +0000725 return BAD_VALUE;
726 }
727 const int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
728 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(mixPort->ext.mix.handle));
jiabin12537fc2023-10-12 17:56:08 +0000729 AudioPort port;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700730 {
731 std::lock_guard l(mLock);
732 RETURN_STATUS_IF_ERROR(mMapper.getAudioMixPort(aidlHandle, &port));
jiabin12537fc2023-10-12 17:56:08 +0000733 }
734 const bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
735 mixPort->role, mixPort->type)) == ::aidl::android::AudioPortDirection::INPUT;
736 *mixPort = VALUE_OR_RETURN_STATUS(::aidl::android::aidl2legacy_AudioPort_audio_port_v7(
737 port, isInput));
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700738 return OK;
jiabin12537fc2023-10-12 17:56:08 +0000739}
740
Mikhail Naganove93a0862023-03-15 17:06:59 -0700741status_t DeviceHalAidl::setAudioPortConfig(const struct audio_port_config* config) {
742 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
743 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700744 if (mModule == nullptr) return NO_INIT;
Mikhail Naganove93a0862023-03-15 17:06:59 -0700745 if (config == nullptr) {
746 return BAD_VALUE;
747 }
748 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
749 config->role, config->type)) == ::aidl::android::AudioPortDirection::INPUT;
750 AudioPortConfig requestedPortConfig = VALUE_OR_RETURN_STATUS(
751 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
752 *config, isInput, 0 /*portId*/));
753 AudioPortConfig portConfig;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700754 std::lock_guard l(mLock);
Mikhail Naganovca92a5c2023-12-07 14:00:48 -0800755 return mMapper.setPortConfig(requestedPortConfig, std::set<int32_t>(), &portConfig);
Shunkai Yao51202502022-12-12 06:11:46 +0000756}
757
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800758MicrophoneInfoProvider::Info const* DeviceHalAidl::getMicrophoneInfo() {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700759 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
760 TIME_CHECK();
761 if (!mModule) return {};
762 std::lock_guard l(mLock);
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800763 if (mMicrophones.status == Microphones::Status::UNKNOWN) {
764 TIME_CHECK();
765 std::vector<MicrophoneInfo> aidlInfo;
766 status_t status = statusTFromBinderStatus(mModule->getMicrophones(&aidlInfo));
767 if (status == OK) {
768 mMicrophones.status = Microphones::Status::QUERIED;
769 mMicrophones.info = std::move(aidlInfo);
770 } else if (status == INVALID_OPERATION) {
771 mMicrophones.status = Microphones::Status::NOT_SUPPORTED;
772 } else {
773 ALOGE("%s: Unexpected status from 'IModule.getMicrophones': %d", __func__, status);
774 return {};
775 }
776 }
777 if (mMicrophones.status == Microphones::Status::QUERIED) {
778 return &mMicrophones.info;
779 }
780 return {}; // NOT_SUPPORTED
781}
782
Shunkai Yao51202502022-12-12 06:11:46 +0000783status_t DeviceHalAidl::getMicrophones(
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800784 std::vector<audio_microphone_characteristic_t>* microphones) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700785 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
786 TIME_CHECK();
787 if (mModule == nullptr) return NO_INIT;
788 if (microphones == nullptr) {
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800789 return BAD_VALUE;
790 }
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800791 auto staticInfo = getMicrophoneInfo();
792 if (!staticInfo) return INVALID_OPERATION;
793 std::vector<MicrophoneDynamicInfo> emptyDynamicInfo;
794 emptyDynamicInfo.reserve(staticInfo->size());
795 std::transform(staticInfo->begin(), staticInfo->end(), std::back_inserter(emptyDynamicInfo),
796 [](const auto& info) { return MicrophoneDynamicInfo{ .id = info.id }; });
797 *microphones = VALUE_OR_RETURN_STATUS(
798 ::aidl::android::convertContainers<std::vector<audio_microphone_characteristic_t>>(
799 *staticInfo, emptyDynamicInfo,
800 ::aidl::android::aidl2legacy_MicrophoneInfos_audio_microphone_characteristic_t)
801 );
Shunkai Yao51202502022-12-12 06:11:46 +0000802 return OK;
803}
804
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700805status_t DeviceHalAidl::addDeviceEffect(
806 const struct audio_port_config *device, sp<EffectHalInterface> effect) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700807 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700808 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700809 if (mModule == nullptr) return NO_INIT;
810 if (device == nullptr || effect == nullptr) {
Shunkai Yao51202502022-12-12 06:11:46 +0000811 return BAD_VALUE;
812 }
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700813 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
814 device->role, device->type)) == ::aidl::android::AudioPortDirection::INPUT;
815 auto requestedPortConfig = VALUE_OR_RETURN_STATUS(
816 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
817 *device, isInput, 0));
818 if (requestedPortConfig.ext.getTag() != AudioPortExt::Tag::device) {
819 ALOGE("%s: provided port config is not a device port config: %s",
820 __func__, requestedPortConfig.toString().c_str());
821 return BAD_VALUE;
822 }
823 AudioPortConfig devicePortConfig;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700824 Hal2AidlMapper::Cleanups cleanups(mMapperAccessor);
825 {
826 std::lock_guard l(mLock);
Mikhail Naganovca92a5c2023-12-07 14:00:48 -0800827 RETURN_STATUS_IF_ERROR(mMapper.setPortConfig(
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700828 requestedPortConfig, {} /*destinationPortIds*/, &devicePortConfig, &cleanups));
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700829 }
830 auto aidlEffect = sp<effect::EffectHalAidl>::cast(effect);
831 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->addDeviceEffect(
832 devicePortConfig.id, aidlEffect->getIEffect())));
833 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000834 return OK;
835}
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700836status_t DeviceHalAidl::removeDeviceEffect(
837 const struct audio_port_config *device, sp<EffectHalInterface> effect) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700838 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700839 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700840 if (mModule == nullptr) return NO_INIT;
841 if (device == nullptr || effect == nullptr) {
Shunkai Yao51202502022-12-12 06:11:46 +0000842 return BAD_VALUE;
843 }
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700844 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
845 device->role, device->type)) == ::aidl::android::AudioPortDirection::INPUT;
846 auto requestedPortConfig = VALUE_OR_RETURN_STATUS(
847 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
848 *device, isInput, 0));
849 if (requestedPortConfig.ext.getTag() != AudioPortExt::Tag::device) {
850 ALOGE("%s: provided port config is not a device port config: %s",
851 __func__, requestedPortConfig.toString().c_str());
852 return BAD_VALUE;
853 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700854 AudioPortConfig devicePortConfig;
855 {
856 std::lock_guard l(mLock);
857 RETURN_STATUS_IF_ERROR(mMapper.findPortConfig(
858 requestedPortConfig.ext.get<AudioPortExt::Tag::device>().device,
859 &devicePortConfig));
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700860 }
861 auto aidlEffect = sp<effect::EffectHalAidl>::cast(effect);
862 return statusTFromBinderStatus(mModule->removeDeviceEffect(
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700863 devicePortConfig.id, aidlEffect->getIEffect()));
Shunkai Yao51202502022-12-12 06:11:46 +0000864}
865
866status_t DeviceHalAidl::getMmapPolicyInfos(
David Li9cf5e622023-03-21 00:51:10 +0800867 media::audio::common::AudioMMapPolicyType policyType,
868 std::vector<media::audio::common::AudioMMapPolicyInfo>* policyInfos) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700869 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000870 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700871 if (mModule == nullptr) return NO_INIT;
Mikhail Naganov25bc9a22023-04-21 18:48:16 -0700872 AudioMMapPolicyType mmapPolicyType = VALUE_OR_RETURN_STATUS(
873 cpp2ndk_AudioMMapPolicyType(policyType));
David Li9cf5e622023-03-21 00:51:10 +0800874
875 std::vector<AudioMMapPolicyInfo> mmapPolicyInfos;
876
877 if (status_t status = statusTFromBinderStatus(
878 mModule->getMmapPolicyInfos(mmapPolicyType, &mmapPolicyInfos)); status != OK) {
879 return status;
880 }
881
882 *policyInfos = VALUE_OR_RETURN_STATUS(
883 convertContainer<std::vector<media::audio::common::AudioMMapPolicyInfo>>(
884 mmapPolicyInfos, ndk2cpp_AudioMMapPolicyInfo));
Shunkai Yao51202502022-12-12 06:11:46 +0000885 return OK;
886}
887
888int32_t DeviceHalAidl::getAAudioMixerBurstCount() {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700889 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000890 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700891 if (mModule == nullptr) return NO_INIT;
David Li9cf5e622023-03-21 00:51:10 +0800892 int32_t mixerBurstCount = 0;
893 if (mModule->getAAudioMixerBurstCount(&mixerBurstCount).isOk()) {
894 return mixerBurstCount;
895 }
896 return 0;
Shunkai Yao51202502022-12-12 06:11:46 +0000897}
898
899int32_t DeviceHalAidl::getAAudioHardwareBurstMinUsec() {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700900 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000901 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700902 if (mModule == nullptr) return NO_INIT;
David Li9cf5e622023-03-21 00:51:10 +0800903 int32_t hardwareBurstMinUsec = 0;
904 if (mModule->getAAudioHardwareBurstMinUsec(&hardwareBurstMinUsec).isOk()) {
905 return hardwareBurstMinUsec;
906 }
907 return 0;
Shunkai Yao51202502022-12-12 06:11:46 +0000908}
909
910error::Result<audio_hw_sync_t> DeviceHalAidl::getHwAvSync() {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700911 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000912 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700913 if (mModule == nullptr) return NO_INIT;
Mikhail Naganov08a62ab2023-03-14 17:11:51 -0700914 int32_t aidlHwAvSync;
915 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->generateHwAvSyncId(&aidlHwAvSync)));
916 return VALUE_OR_RETURN_STATUS(
917 ::aidl::android::aidl2legacy_int32_t_audio_hw_sync_t(aidlHwAvSync));
Shunkai Yao51202502022-12-12 06:11:46 +0000918}
919
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000920status_t DeviceHalAidl::dump(int fd, const Vector<String16>& args) {
921 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700922 if (mModule == nullptr) return NO_INIT;
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000923 return mModule->dump(fd, Args(args).args(), args.size());
David Li9cf5e622023-03-21 00:51:10 +0800924}
Shunkai Yao51202502022-12-12 06:11:46 +0000925
Eric Laurent7af6ee72023-06-29 11:44:54 +0200926status_t DeviceHalAidl::supportsBluetoothVariableLatency(bool* supports) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700927 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000928 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700929 if (mModule == nullptr) return NO_INIT;
Mikhail Naganov3ac95c92023-04-12 13:14:30 -0700930 if (supports == nullptr) {
931 return BAD_VALUE;
932 }
933 return statusTFromBinderStatus(mModule->supportsVariableLatency(supports));
Shunkai Yao51202502022-12-12 06:11:46 +0000934}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000935
Vlad Popa03bd5bc2023-01-17 16:16:51 +0100936status_t DeviceHalAidl::getSoundDoseInterface(const std::string& module,
937 ::ndk::SpAIBinder* soundDoseBinder) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700938 if (soundDoseBinder == nullptr) {
939 return BAD_VALUE;
940 }
Vlad Popa03bd5bc2023-01-17 16:16:51 +0100941 if (mSoundDose == nullptr) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700942 ALOGE("%s failed to retrieve the sound dose interface for module %s",
943 __func__, module.c_str());
944 return BAD_VALUE;
Vlad Popa03bd5bc2023-01-17 16:16:51 +0100945 }
Vlad Popae1f33902023-10-30 19:48:25 -0700946
947 if (mSoundDose == nullptr) {
948 ALOGE("%s failed to return the sound dose interface for module %s: not implemented",
949 __func__,
950 module.c_str());
951 return NO_INIT;
952 }
953
Vlad Popa03bd5bc2023-01-17 16:16:51 +0100954 *soundDoseBinder = mSoundDose->asBinder();
955 ALOGI("%s using audio AIDL HAL sound dose interface", __func__);
Vlad Popa03bd5bc2023-01-17 16:16:51 +0100956 return OK;
957}
jiabin872de702023-04-27 22:04:31 +0000958
959status_t DeviceHalAidl::prepareToDisconnectExternalDevice(const struct audio_port_v7* port) {
jiabin62750c22023-12-21 22:06:07 +0000960 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
961 TIME_CHECK();
962 if (mModule == nullptr) return NO_INIT;
963 if (port == nullptr) {
964 return BAD_VALUE;
965 }
966 const bool isInput = VALUE_OR_RETURN_STATUS(
967 ::aidl::android::portDirection(port->role, port->type)) ==
968 ::aidl::android::AudioPortDirection::INPUT;
969 AudioPort aidlPort = VALUE_OR_RETURN_STATUS(
970 ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
971 if (aidlPort.ext.getTag() != AudioPortExt::device) {
972 ALOGE("%s: provided port is not a device port (module %s): %s",
973 __func__, mInstance.c_str(), aidlPort.toString().c_str());
974 return BAD_VALUE;
975 }
976 status_t status = NO_ERROR;
977 {
978 std::lock_guard l(mLock);
979 status = mMapper.prepareToDisconnectExternalDevice(aidlPort);
980 }
981 if (status == UNKNOWN_TRANSACTION) {
982 // If there is not AIDL API defined for `prepareToDisconnectExternalDevice`.
983 // Call `setConnectedState` instead.
984 RETURN_STATUS_IF_ERROR(setConnectedState(port, false /*connected*/));
985 std::lock_guard l(mLock);
986 mDeviceDisconnectionNotified.insert(port->id);
987 // Return that there was no error as otherwise the disconnection procedure will not be
988 // considered complete for upper layers, and 'setConnectedState' will not be called again
989 return OK;
990 } else {
991 return status;
992 }
jiabin872de702023-04-27 22:04:31 +0000993}
994
Mikhail Naganove93a0862023-03-15 17:06:59 -0700995status_t DeviceHalAidl::setConnectedState(const struct audio_port_v7 *port, bool connected) {
Mikhail Naganovae9063d2023-11-07 16:43:51 -0800996 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganove93a0862023-03-15 17:06:59 -0700997 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700998 if (mModule == nullptr) return NO_INIT;
Mikhail Naganove93a0862023-03-15 17:06:59 -0700999 if (port == nullptr) {
1000 return BAD_VALUE;
1001 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -07001002 if (!connected) {
1003 std::lock_guard l(mLock);
1004 if (mDeviceDisconnectionNotified.erase(port->id) > 0) {
1005 // For device disconnection, APM will first call `prepareToDisconnectExternalDevice`
jiabin62750c22023-12-21 22:06:07 +00001006 // and then call `setConnectedState`. If `prepareToDisconnectExternalDevice` doesn't
1007 // exit, `setConnectedState` will be called when calling
1008 // `prepareToDisconnectExternalDevice`. Do not call to the HAL if previous call is
1009 // successful. Also remove the cache here to avoid a large cache after a long run.
Mikhail Naganovac9d4e72023-10-23 12:00:09 -07001010 return OK;
1011 }
jiabin872de702023-04-27 22:04:31 +00001012 }
Mikhail Naganove93a0862023-03-15 17:06:59 -07001013 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(port->role, port->type)) ==
1014 ::aidl::android::AudioPortDirection::INPUT;
1015 AudioPort aidlPort = VALUE_OR_RETURN_STATUS(
1016 ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
1017 if (aidlPort.ext.getTag() != AudioPortExt::device) {
1018 ALOGE("%s: provided port is not a device port (module %s): %s",
1019 __func__, mInstance.c_str(), aidlPort.toString().c_str());
1020 return BAD_VALUE;
1021 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -07001022 std::lock_guard l(mLock);
1023 return mMapper.setDevicePortConnectedState(aidlPort, connected);
Mikhail Naganove93a0862023-03-15 17:06:59 -07001024}
1025
1026status_t DeviceHalAidl::setSimulateDeviceConnections(bool enabled) {
1027 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -07001028 if (mModule == nullptr) return NO_INIT;
1029 {
1030 std::lock_guard l(mLock);
Mikhail Naganova317a802024-03-15 18:03:10 +00001031 mMapper.resetUnusedPatchesAndPortConfigs();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -07001032 }
Mikhail Naganove93a0862023-03-15 17:06:59 -07001033 ModuleDebug debug{ .simulateDeviceConnections = enabled };
1034 status_t status = statusTFromBinderStatus(mModule->setModuleDebug(debug));
1035 // This is important to log as it affects HAL behavior.
1036 if (status == OK) {
1037 ALOGI("%s: set enabled: %d", __func__, enabled);
1038 } else {
1039 ALOGW("%s: set enabled to %d failed: %d", __func__, enabled, status);
1040 }
1041 return status;
1042}
1043
Mikhail Naganove7a26ad2023-05-25 17:36:48 -07001044status_t DeviceHalAidl::filterAndRetrieveBtA2dpParameters(
1045 AudioParameter &keys, AudioParameter *result) {
Mikhail Naganove7a26ad2023-05-25 17:36:48 -07001046 if (String8 key = String8(AudioParameter::keyReconfigA2dpSupported); keys.containsKey(key)) {
1047 keys.remove(key);
David Lia7761ed2023-11-03 17:22:07 +00001048 if (mBluetoothA2dp != nullptr) {
1049 bool supports;
1050 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
1051 mBluetoothA2dp->supportsOffloadReconfiguration(&supports)));
1052 result->addInt(key, supports ? 1 : 0);
1053 } else {
1054 ALOGI("%s: no IBluetoothA2dp on %s", __func__, mInstance.c_str());
1055 result->addInt(key, 0);
1056 }
Mikhail Naganove7a26ad2023-05-25 17:36:48 -07001057 }
1058 return OK;
1059}
1060
Eric Laurent7e3c0832023-11-30 15:04:50 +01001061status_t DeviceHalAidl::filterAndRetrieveBtLeParameters(
1062 AudioParameter &keys, AudioParameter *result) {
1063 if (String8 key = String8(AudioParameter::keyReconfigLeSupported); keys.containsKey(key)) {
1064 keys.remove(key);
1065 if (mBluetoothLe != nullptr) {
1066 bool supports;
1067 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
1068 mBluetoothLe->supportsOffloadReconfiguration(&supports)));
1069 result->addInt(key, supports ? 1 : 0);
1070 } else {
1071 ALOGI("%s: no mBluetoothLe on %s", __func__, mInstance.c_str());
1072 result->addInt(key, 0);
1073 }
1074 }
1075 return OK;
1076}
1077
Mikhail Naganovccc82112023-04-27 18:14:15 -07001078status_t DeviceHalAidl::filterAndUpdateBtA2dpParameters(AudioParameter &parameters) {
Mikhail Naganovccc82112023-04-27 18:14:15 -07001079 std::optional<bool> a2dpEnabled;
Mikhail Naganove7a26ad2023-05-25 17:36:48 -07001080 std::optional<std::vector<VendorParameter>> reconfigureOffload;
Mikhail Naganovccc82112023-04-27 18:14:15 -07001081 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1082 parameters, String8(AudioParameter::keyBtA2dpSuspended),
1083 [&a2dpEnabled](const String8& trueOrFalse) {
1084 if (trueOrFalse == AudioParameter::valueTrue) {
1085 a2dpEnabled = false; // 'suspended' == true
1086 return OK;
1087 } else if (trueOrFalse == AudioParameter::valueFalse) {
1088 a2dpEnabled = true; // 'suspended' == false
1089 return OK;
1090 }
1091 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1092 AudioParameter::keyBtA2dpSuspended, trueOrFalse.c_str());
1093 return BAD_VALUE;
1094 }));
Mikhail Naganove7a26ad2023-05-25 17:36:48 -07001095 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1096 parameters, String8(AudioParameter::keyReconfigA2dp),
1097 [&](const String8& value) -> status_t {
Mikhail Naganove5011002024-01-26 10:57:19 -08001098 std::vector<VendorParameter> result;
1099 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
1100 mVendorExt->parseBluetoothA2dpReconfigureOffload(
1101 std::string(value.c_str()), &result)));
1102 reconfigureOffload = std::move(result);
Mikhail Naganove7a26ad2023-05-25 17:36:48 -07001103 return OK;
1104 }));
Mikhail Naganovccc82112023-04-27 18:14:15 -07001105 if (mBluetoothA2dp != nullptr && a2dpEnabled.has_value()) {
1106 return statusTFromBinderStatus(mBluetoothA2dp->setEnabled(a2dpEnabled.value()));
1107 }
Mikhail Naganove7a26ad2023-05-25 17:36:48 -07001108 if (mBluetoothA2dp != nullptr && reconfigureOffload.has_value()) {
1109 return statusTFromBinderStatus(mBluetoothA2dp->reconfigureOffload(
1110 reconfigureOffload.value()));
1111 }
Mikhail Naganovccc82112023-04-27 18:14:15 -07001112 return OK;
1113}
1114
1115status_t DeviceHalAidl::filterAndUpdateBtHfpParameters(AudioParameter &parameters) {
Mikhail Naganovccc82112023-04-27 18:14:15 -07001116 IBluetooth::HfpConfig hfpConfig;
1117 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1118 parameters, String8(AudioParameter::keyBtHfpEnable),
1119 [&hfpConfig](const String8& trueOrFalse) {
1120 if (trueOrFalse == AudioParameter::valueTrue) {
1121 hfpConfig.isEnabled = Boolean{ .value = true };
1122 return OK;
1123 } else if (trueOrFalse == AudioParameter::valueFalse) {
1124 hfpConfig.isEnabled = Boolean{ .value = false };
1125 return OK;
1126 }
1127 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1128 AudioParameter::keyBtHfpEnable, trueOrFalse.c_str());
1129 return BAD_VALUE;
1130 }));
1131 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
1132 parameters, String8(AudioParameter::keyBtHfpSamplingRate),
1133 [&hfpConfig](int sampleRate) {
1134 return sampleRate > 0 ?
1135 hfpConfig.sampleRate = Int{ .value = sampleRate }, OK : BAD_VALUE;
1136 }));
1137 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
1138 parameters, String8(AudioParameter::keyBtHfpVolume),
1139 [&hfpConfig](int volume0to15) {
1140 if (volume0to15 >= 0 && volume0to15 <= 15) {
1141 hfpConfig.volume = Float{ .value = volume0to15 / 15.0f };
1142 return OK;
1143 }
1144 return BAD_VALUE;
1145 }));
1146 if (mBluetooth != nullptr && hfpConfig != IBluetooth::HfpConfig{}) {
1147 IBluetooth::HfpConfig newHfpConfig;
1148 return statusTFromBinderStatus(mBluetooth->setHfpConfig(hfpConfig, &newHfpConfig));
1149 }
1150 return OK;
1151}
1152
1153status_t DeviceHalAidl::filterAndUpdateBtLeParameters(AudioParameter &parameters) {
Mikhail Naganovccc82112023-04-27 18:14:15 -07001154 std::optional<bool> leEnabled;
Eric Laurent7e3c0832023-11-30 15:04:50 +01001155 std::optional<std::vector<VendorParameter>> reconfigureOffload;
Mikhail Naganovccc82112023-04-27 18:14:15 -07001156 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1157 parameters, String8(AudioParameter::keyBtLeSuspended),
1158 [&leEnabled](const String8& trueOrFalse) {
1159 if (trueOrFalse == AudioParameter::valueTrue) {
1160 leEnabled = false; // 'suspended' == true
1161 return OK;
1162 } else if (trueOrFalse == AudioParameter::valueFalse) {
1163 leEnabled = true; // 'suspended' == false
1164 return OK;
1165 }
1166 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1167 AudioParameter::keyBtLeSuspended, trueOrFalse.c_str());
1168 return BAD_VALUE;
1169 }));
Eric Laurent7e3c0832023-11-30 15:04:50 +01001170 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1171 parameters, String8(AudioParameter::keyReconfigLe),
1172 [&](const String8& value) -> status_t {
1173 if (mVendorExt != nullptr) {
1174 std::vector<VendorParameter> result;
1175 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
1176 mVendorExt->parseBluetoothLeReconfigureOffload(
1177 std::string(value.c_str()), &result)));
1178 reconfigureOffload = std::move(result);
1179 } else {
1180 reconfigureOffload = std::vector<VendorParameter>();
1181 }
1182 return OK;
1183 }));
Mikhail Naganovccc82112023-04-27 18:14:15 -07001184 if (mBluetoothLe != nullptr && leEnabled.has_value()) {
1185 return statusTFromBinderStatus(mBluetoothLe->setEnabled(leEnabled.value()));
1186 }
Eric Laurent7e3c0832023-11-30 15:04:50 +01001187 if (mBluetoothLe != nullptr && reconfigureOffload.has_value()) {
1188 return statusTFromBinderStatus(mBluetoothLe->reconfigureOffload(
1189 reconfigureOffload.value()));
1190 }
Mikhail Naganovccc82112023-04-27 18:14:15 -07001191 return OK;
1192}
1193
1194status_t DeviceHalAidl::filterAndUpdateBtScoParameters(AudioParameter &parameters) {
Mikhail Naganovccc82112023-04-27 18:14:15 -07001195 IBluetooth::ScoConfig scoConfig;
1196 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1197 parameters, String8(AudioParameter::keyBtSco),
1198 [&scoConfig](const String8& onOrOff) {
1199 if (onOrOff == AudioParameter::valueOn) {
1200 scoConfig.isEnabled = Boolean{ .value = true };
1201 return OK;
1202 } else if (onOrOff == AudioParameter::valueOff) {
1203 scoConfig.isEnabled = Boolean{ .value = false };
1204 return OK;
1205 }
1206 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1207 AudioParameter::keyBtSco, onOrOff.c_str());
1208 return BAD_VALUE;
1209 }));
1210 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1211 parameters, String8(AudioParameter::keyBtScoHeadsetName),
1212 [&scoConfig](const String8& name) {
1213 scoConfig.debugName = name;
1214 return OK;
1215 }));
1216 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1217 parameters, String8(AudioParameter::keyBtNrec),
1218 [&scoConfig](const String8& onOrOff) {
1219 if (onOrOff == AudioParameter::valueOn) {
1220 scoConfig.isNrecEnabled = Boolean{ .value = true };
1221 return OK;
1222 } else if (onOrOff == AudioParameter::valueOff) {
1223 scoConfig.isNrecEnabled = Boolean{ .value = false };
1224 return OK;
1225 }
1226 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1227 AudioParameter::keyBtNrec, onOrOff.c_str());
1228 return BAD_VALUE;
1229 }));
1230 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1231 parameters, String8(AudioParameter::keyBtScoWb),
1232 [&scoConfig](const String8& onOrOff) {
1233 if (onOrOff == AudioParameter::valueOn) {
1234 scoConfig.mode = IBluetooth::ScoConfig::Mode::SCO_WB;
1235 return OK;
1236 } else if (onOrOff == AudioParameter::valueOff) {
1237 scoConfig.mode = IBluetooth::ScoConfig::Mode::SCO;
1238 return OK;
1239 }
1240 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1241 AudioParameter::keyBtScoWb, onOrOff.c_str());
1242 return BAD_VALUE;
1243 }));
1244 if (mBluetooth != nullptr && scoConfig != IBluetooth::ScoConfig{}) {
1245 IBluetooth::ScoConfig newScoConfig;
1246 return statusTFromBinderStatus(mBluetooth->setScoConfig(scoConfig, &newScoConfig));
1247 }
1248 return OK;
1249}
1250
Mikhail Naganove92c34b2023-05-31 14:24:48 -07001251status_t DeviceHalAidl::filterAndUpdateScreenParameters(AudioParameter &parameters) {
Mikhail Naganove92c34b2023-05-31 14:24:48 -07001252 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1253 parameters, String8(AudioParameter::keyScreenState),
1254 [&](const String8& onOrOff) -> status_t {
1255 std::optional<bool> isTurnedOn;
1256 if (onOrOff == AudioParameter::valueOn) {
1257 isTurnedOn = true;
1258 } else if (onOrOff == AudioParameter::valueOff) {
1259 isTurnedOn = false;
1260 }
1261 if (!isTurnedOn.has_value()) {
1262 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1263 AudioParameter::keyScreenState, onOrOff.c_str());
1264 return BAD_VALUE;
1265 }
1266 return statusTFromBinderStatus(
1267 mModule->updateScreenState(isTurnedOn.value()));
1268 }));
1269 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
1270 parameters, String8(AudioParameter::keyScreenRotation),
1271 [&](int rotationDegrees) -> status_t {
1272 IModule::ScreenRotation rotation;
1273 switch (rotationDegrees) {
1274 case 0: rotation = IModule::ScreenRotation::DEG_0; break;
1275 case 90: rotation = IModule::ScreenRotation::DEG_90; break;
1276 case 180: rotation = IModule::ScreenRotation::DEG_180; break;
1277 case 270: rotation = IModule::ScreenRotation::DEG_270; break;
1278 default:
1279 ALOGE("setParameters: parameter key \"%s\" has invalid value %d",
1280 AudioParameter::keyScreenRotation, rotationDegrees);
1281 return BAD_VALUE;
1282 }
1283 return statusTFromBinderStatus(mModule->updateScreenRotation(rotation));
1284 }));
1285 return OK;
1286}
1287
Mikhail Naganovb9a81312023-07-18 13:55:34 -07001288status_t DeviceHalAidl::filterAndUpdateTelephonyParameters(AudioParameter &parameters) {
Mikhail Naganovb9a81312023-07-18 13:55:34 -07001289 using TtyMode = ITelephony::TelecomConfig::TtyMode;
1290 ITelephony::TelecomConfig telConfig;
1291 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1292 parameters, String8(AudioParameter::keyTtyMode),
1293 [&telConfig](const String8& mode) {
1294 if (mode == AudioParameter::valueTtyModeOff) {
1295 telConfig.ttyMode = TtyMode::OFF;
1296 return OK;
1297 } else if (mode == AudioParameter::valueTtyModeFull) {
1298 telConfig.ttyMode = TtyMode::FULL;
1299 return OK;
1300 } else if (mode == AudioParameter::valueTtyModeHco) {
1301 telConfig.ttyMode = TtyMode::HCO;
1302 return OK;
1303 } else if (mode == AudioParameter::valueTtyModeVco) {
1304 telConfig.ttyMode = TtyMode::VCO;
1305 return OK;
1306 }
1307 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1308 AudioParameter::keyTtyMode, mode.c_str());
1309 return BAD_VALUE;
1310 }));
1311 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1312 parameters, String8(AudioParameter::keyHacSetting),
1313 [&telConfig](const String8& onOrOff) {
1314 if (onOrOff == AudioParameter::valueHacOn) {
1315 telConfig.isHacEnabled = Boolean{ .value = true };
1316 return OK;
1317 } else if (onOrOff == AudioParameter::valueHacOff) {
1318 telConfig.isHacEnabled = Boolean{ .value = false };
1319 return OK;
1320 }
1321 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1322 AudioParameter::keyHacSetting, onOrOff.c_str());
1323 return BAD_VALUE;
1324 }));
1325 if (mTelephony != nullptr && telConfig != ITelephony::TelecomConfig{}) {
1326 ITelephony::TelecomConfig newTelConfig;
1327 return statusTFromBinderStatus(
1328 mTelephony->setTelecomConfig(telConfig, &newTelConfig));
1329 }
1330 return OK;
1331}
1332
Mikhail Naganovdfd594e2023-02-08 16:59:41 -08001333void DeviceHalAidl::clearCallbacks(void* cookie) {
Mikhail Naganov22578412024-08-16 16:50:34 -07001334 std::lock_guard l(mCallbacksLock);
Mikhail Naganovdfd594e2023-02-08 16:59:41 -08001335 mCallbacks.erase(cookie);
1336}
1337
1338sp<StreamOutHalInterfaceCallback> DeviceHalAidl::getStreamOutCallback(void* cookie) {
1339 return getCallbackImpl(cookie, &Callbacks::out);
1340}
1341
1342void DeviceHalAidl::setStreamOutCallback(
1343 void* cookie, const sp<StreamOutHalInterfaceCallback>& cb) {
1344 setCallbackImpl(cookie, &Callbacks::out, cb);
1345}
1346
1347sp<StreamOutHalInterfaceEventCallback> DeviceHalAidl::getStreamOutEventCallback(
1348 void* cookie) {
1349 return getCallbackImpl(cookie, &Callbacks::event);
1350}
1351
1352void DeviceHalAidl::setStreamOutEventCallback(
1353 void* cookie, const sp<StreamOutHalInterfaceEventCallback>& cb) {
1354 setCallbackImpl(cookie, &Callbacks::event, cb);
1355}
1356
1357sp<StreamOutHalInterfaceLatencyModeCallback> DeviceHalAidl::getStreamOutLatencyModeCallback(
1358 void* cookie) {
1359 return getCallbackImpl(cookie, &Callbacks::latency);
1360}
1361
1362void DeviceHalAidl::setStreamOutLatencyModeCallback(
1363 void* cookie, const sp<StreamOutHalInterfaceLatencyModeCallback>& cb) {
1364 setCallbackImpl(cookie, &Callbacks::latency, cb);
1365}
1366
Mikhail Naganov22578412024-08-16 16:50:34 -07001367template <class C>
Mikhail Naganovdfd594e2023-02-08 16:59:41 -08001368sp<C> DeviceHalAidl::getCallbackImpl(void* cookie, wp<C> DeviceHalAidl::Callbacks::* field) {
Mikhail Naganov22578412024-08-16 16:50:34 -07001369 wp<C> result;
1370 {
1371 std::lock_guard l(mCallbacksLock);
1372 if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
1373 result = (it->second).*field;
1374 }
Mikhail Naganovdfd594e2023-02-08 16:59:41 -08001375 }
Mikhail Naganov22578412024-08-16 16:50:34 -07001376 return result.promote();
Mikhail Naganovdfd594e2023-02-08 16:59:41 -08001377}
1378template<class C>
1379void DeviceHalAidl::setCallbackImpl(
1380 void* cookie, wp<C> DeviceHalAidl::Callbacks::* field, const sp<C>& cb) {
Mikhail Naganov22578412024-08-16 16:50:34 -07001381 std::lock_guard l(mCallbacksLock);
Mikhail Naganovdfd594e2023-02-08 16:59:41 -08001382 if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
1383 (it->second).*field = cb;
1384 }
1385}
1386
Mikhail Naganov31d46652023-01-10 18:29:25 +00001387} // namespace android