blob: 032533cedab6f6b403c38397d75186df46f21a7a [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;
David Li21289462024-04-17 01:09:23 +080061using aidl::android::hardware::audio::common::kDumpFromAudioServerArgument;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -080062using aidl::android::hardware::audio::common::RecordTrackMetadata;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -070063using aidl::android::hardware::audio::core::sounddose::ISoundDose;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -080064using aidl::android::hardware::audio::core::AudioPatch;
Mikhail Naganov289468a2023-03-29 10:06:15 -070065using aidl::android::hardware::audio::core::AudioRoute;
Mikhail Naganovccc82112023-04-27 18:14:15 -070066using aidl::android::hardware::audio::core::IBluetooth;
67using aidl::android::hardware::audio::core::IBluetoothA2dp;
68using aidl::android::hardware::audio::core::IBluetoothLe;
Mikhail Naganovfab697c2023-01-11 19:33:13 +000069using aidl::android::hardware::audio::core::IModule;
70using aidl::android::hardware::audio::core::ITelephony;
Mikhail Naganove93a0862023-03-15 17:06:59 -070071using aidl::android::hardware::audio::core::ModuleDebug;
Mikhail Naganove7a26ad2023-05-25 17:36:48 -070072using aidl::android::hardware::audio::core::VendorParameter;
Mikhail Naganov31d46652023-01-10 18:29:25 +000073
74namespace android {
75
Mikhail Naganov5b1eed12023-01-25 11:29:11 -080076namespace {
77
Mikhail Naganovf83b9742023-04-24 13:06:04 -070078// Note: these converters are for types defined in different AIDL files. Although these
79// AIDL files are copies of each other, however formally these are different types
80// thus we don't use a conversion via a parcelable.
81ConversionResult<media::AudioRoute> ndk2cpp_AudioRoute(const AudioRoute& ndk) {
82 media::AudioRoute cpp;
83 cpp.sourcePortIds.insert(
84 cpp.sourcePortIds.end(), ndk.sourcePortIds.begin(), ndk.sourcePortIds.end());
85 cpp.sinkPortId = ndk.sinkPortId;
86 cpp.isExclusive = ndk.isExclusive;
David Li9cf5e622023-03-21 00:51:10 +080087 return cpp;
88}
89
Mikhail Naganov1fba38c2023-05-03 17:45:36 -070090template<typename T>
91std::shared_ptr<T> retrieveSubInterface(const std::shared_ptr<IModule>& module,
92 ::ndk::ScopedAStatus (IModule::*getT)(std::shared_ptr<T>*)) {
93 if (module != nullptr) {
94 std::shared_ptr<T> instance;
95 if (auto status = (module.get()->*getT)(&instance); status.isOk()) {
96 return instance;
97 }
98 }
99 return nullptr;
100}
101
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800102} // namespace
103
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700104DeviceHalAidl::DeviceHalAidl(const std::string& instance, const std::shared_ptr<IModule>& module,
105 const std::shared_ptr<IHalAdapterVendorExtension>& vext)
Mikhail Naganov1fba38c2023-05-03 17:45:36 -0700106 : ConversionHelperAidl("DeviceHalAidl"),
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700107 mInstance(instance), mModule(module), mVendorExt(vext),
Mikhail Naganovccc82112023-04-27 18:14:15 -0700108 mTelephony(retrieveSubInterface<ITelephony>(module, &IModule::getTelephony)),
109 mBluetooth(retrieveSubInterface<IBluetooth>(module, &IModule::getBluetooth)),
110 mBluetoothA2dp(retrieveSubInterface<IBluetoothA2dp>(module, &IModule::getBluetoothA2dp)),
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700111 mBluetoothLe(retrieveSubInterface<IBluetoothLe>(module, &IModule::getBluetoothLe)),
112 mSoundDose(retrieveSubInterface<ISoundDose>(module, &IModule::getSoundDose)),
113 mMapper(instance, module), mMapperAccessor(mMapper, mLock) {
Mikhail Naganov1fba38c2023-05-03 17:45:36 -0700114}
115
Mikhail Naganovf83b9742023-04-24 13:06:04 -0700116status_t DeviceHalAidl::getAudioPorts(std::vector<media::audio::common::AudioPort> *ports) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700117 std::lock_guard l(mLock);
118 return mMapper.getAudioPorts(ports, ndk2cpp_AudioPort);
Mikhail Naganovf83b9742023-04-24 13:06:04 -0700119}
120
121status_t DeviceHalAidl::getAudioRoutes(std::vector<media::AudioRoute> *routes) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700122 std::lock_guard l(mLock);
123 return mMapper.getAudioRoutes(routes, ndk2cpp_AudioRoute);
Mikhail Naganovf83b9742023-04-24 13:06:04 -0700124}
125
Mikhail Naganov1fba38c2023-05-03 17:45:36 -0700126status_t DeviceHalAidl::getSupportedModes(std::vector<media::audio::common::AudioMode> *modes) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700127 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov1fba38c2023-05-03 17:45:36 -0700128 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700129 if (mModule == nullptr) return NO_INIT;
130 if (mTelephony == nullptr) return INVALID_OPERATION;
Mikhail Naganov1fba38c2023-05-03 17:45:36 -0700131 if (modes == nullptr) {
132 return BAD_VALUE;
133 }
Mikhail Naganov1fba38c2023-05-03 17:45:36 -0700134 std::vector<AudioMode> aidlModes;
135 RETURN_STATUS_IF_ERROR(
136 statusTFromBinderStatus(mTelephony->getSupportedAudioModes(&aidlModes)));
137 *modes = VALUE_OR_RETURN_STATUS(
138 ::aidl::android::convertContainer<std::vector<media::audio::common::AudioMode>>(
139 aidlModes, ndk2cpp_AudioMode));
140 return OK;
141}
142
Mikhail Naganov31d46652023-01-10 18:29:25 +0000143status_t DeviceHalAidl::getSupportedDevices(uint32_t*) {
144 // Obsolete.
145 return INVALID_OPERATION;
Shunkai Yao51202502022-12-12 06:11:46 +0000146}
147
148status_t DeviceHalAidl::initCheck() {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700149 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800150 TIME_CHECK();
Mikhail Naganov31d46652023-01-10 18:29:25 +0000151 if (mModule == nullptr) return NO_INIT;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700152 std::lock_guard l(mLock);
153 return mMapper.initialize();
Shunkai Yao51202502022-12-12 06:11:46 +0000154}
155
156status_t DeviceHalAidl::setVoiceVolume(float volume) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700157 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000158 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700159 if (mModule == nullptr) return NO_INIT;
Mikhail Naganov1fba38c2023-05-03 17:45:36 -0700160 if (mTelephony == nullptr) return INVALID_OPERATION;
161 ITelephony::TelecomConfig inConfig{ .voiceVolume = Float{volume} }, outConfig;
162 RETURN_STATUS_IF_ERROR(
163 statusTFromBinderStatus(mTelephony->setTelecomConfig(inConfig, &outConfig)));
164 ALOGW_IF(outConfig.voiceVolume.has_value() && volume != outConfig.voiceVolume.value().value,
165 "%s: the resulting voice volume %f is not the same as requested %f",
166 __func__, outConfig.voiceVolume.value().value, volume);
167 return OK;
Shunkai Yao51202502022-12-12 06:11:46 +0000168}
169
170status_t DeviceHalAidl::setMasterVolume(float volume) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700171 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000172 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700173 if (mModule == nullptr) return NO_INIT;
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000174 return statusTFromBinderStatus(mModule->setMasterVolume(volume));
Shunkai Yao51202502022-12-12 06:11:46 +0000175}
176
177status_t DeviceHalAidl::getMasterVolume(float *volume) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700178 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000179 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700180 if (mModule == nullptr) return NO_INIT;
181 if (volume == nullptr) {
182 return BAD_VALUE;
183 }
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000184 return statusTFromBinderStatus(mModule->getMasterVolume(volume));
Shunkai Yao51202502022-12-12 06:11:46 +0000185}
186
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000187status_t DeviceHalAidl::setMode(audio_mode_t mode) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700188 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000189 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700190 if (mModule == nullptr) return NO_INIT;
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000191 AudioMode audioMode = VALUE_OR_FATAL(::aidl::android::legacy2aidl_audio_mode_t_AudioMode(mode));
Mikhail Naganov1fba38c2023-05-03 17:45:36 -0700192 if (mTelephony != nullptr) {
193 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mTelephony->switchAudioMode(audioMode)));
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000194 }
195 return statusTFromBinderStatus(mModule->updateAudioMode(audioMode));
Shunkai Yao51202502022-12-12 06:11:46 +0000196}
197
198status_t DeviceHalAidl::setMicMute(bool state) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700199 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000200 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700201 if (mModule == nullptr) return NO_INIT;
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000202 return statusTFromBinderStatus(mModule->setMicMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000203}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000204
Shunkai Yao51202502022-12-12 06:11:46 +0000205status_t DeviceHalAidl::getMicMute(bool *state) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700206 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000207 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700208 if (mModule == nullptr) return NO_INIT;
209 if (state == nullptr) {
210 return BAD_VALUE;
211 }
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000212 return statusTFromBinderStatus(mModule->getMicMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000213}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000214
Shunkai Yao51202502022-12-12 06:11:46 +0000215status_t DeviceHalAidl::setMasterMute(bool state) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700216 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000217 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700218 if (mModule == nullptr) return NO_INIT;
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000219 return statusTFromBinderStatus(mModule->setMasterMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000220}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000221
Shunkai Yao51202502022-12-12 06:11:46 +0000222status_t DeviceHalAidl::getMasterMute(bool *state) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700223 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000224 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700225 if (mModule == nullptr) return NO_INIT;
226 if (state == nullptr) {
227 return BAD_VALUE;
228 }
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000229 return statusTFromBinderStatus(mModule->getMasterMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000230}
231
Mikhail Naganovccc82112023-04-27 18:14:15 -0700232status_t DeviceHalAidl::setParameters(const String8& kvPairs) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700233 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
234 TIME_CHECK();
235 if (mModule == nullptr) return NO_INIT;
Mikhail Naganovccc82112023-04-27 18:14:15 -0700236 AudioParameter parameters(kvPairs);
237 ALOGD("%s: parameters: \"%s\"", __func__, parameters.toString().c_str());
238
239 if (status_t status = filterAndUpdateBtA2dpParameters(parameters); status != OK) {
240 ALOGW("%s: filtering or updating BT A2DP parameters failed: %d", __func__, status);
241 }
242 if (status_t status = filterAndUpdateBtHfpParameters(parameters); status != OK) {
243 ALOGW("%s: filtering or updating BT HFP parameters failed: %d", __func__, status);
244 }
245 if (status_t status = filterAndUpdateBtLeParameters(parameters); status != OK) {
246 ALOGW("%s: filtering or updating BT LE parameters failed: %d", __func__, status);
247 }
248 if (status_t status = filterAndUpdateBtScoParameters(parameters); status != OK) {
249 ALOGW("%s: filtering or updating BT SCO parameters failed: %d", __func__, status);
250 }
Mikhail Naganove92c34b2023-05-31 14:24:48 -0700251 if (status_t status = filterAndUpdateScreenParameters(parameters); status != OK) {
252 ALOGW("%s: filtering or updating screen parameters failed: %d", __func__, status);
253 }
Mikhail Naganovb9a81312023-07-18 13:55:34 -0700254 if (status_t status = filterAndUpdateTelephonyParameters(parameters); status != OK) {
255 ALOGW("%s: filtering or updating telephony parameters failed: %d", __func__, status);
256 }
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700257 return parseAndSetVendorParameters(mVendorExt, mModule, parameters);
Shunkai Yao51202502022-12-12 06:11:46 +0000258}
259
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700260status_t DeviceHalAidl::getParameters(const String8& keys, String8 *values) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700261 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000262 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700263 if (mModule == nullptr) return NO_INIT;
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700264 if (values == nullptr) {
265 return BAD_VALUE;
266 }
267 AudioParameter parameterKeys(keys), result;
268 if (status_t status = filterAndRetrieveBtA2dpParameters(parameterKeys, &result); status != OK) {
269 ALOGW("%s: filtering or retrieving BT A2DP parameters failed: %d", __func__, status);
270 }
Eric Laurent7e3c0832023-11-30 15:04:50 +0100271 if (status_t status = filterAndRetrieveBtLeParameters(parameterKeys, &result); status != OK) {
272 ALOGW("%s: filtering or retrieving BT LE parameters failed: %d", __func__, status);
273 }
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700274 *values = result.toString();
275 return parseAndGetVendorParameters(mVendorExt, mModule, parameterKeys, values);
Shunkai Yao51202502022-12-12 06:11:46 +0000276}
277
Mikhail Naganovd5b643f2024-02-15 11:51:26 -0800278status_t DeviceHalAidl::getInputBufferSize(struct audio_config* config, size_t* size) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800279 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800280 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700281 if (mModule == nullptr) return NO_INIT;
282 if (config == nullptr || size == nullptr) {
283 return BAD_VALUE;
284 }
Mikhail Naganovd5b643f2024-02-15 11:51:26 -0800285 constexpr bool isInput = true;
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800286 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
Mikhail Naganovd5b643f2024-02-15 11:51:26 -0800287 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, isInput));
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800288 AudioDevice aidlDevice;
289 aidlDevice.type.type = AudioDeviceType::IN_DEFAULT;
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800290 AudioSource aidlSource = AudioSource::DEFAULT;
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800291 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::input>(0);
292 AudioPortConfig mixPortConfig;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700293 Hal2AidlMapper::Cleanups cleanups(mMapperAccessor);
Mikhail Naganove93a0862023-03-15 17:06:59 -0700294 AudioPatch aidlPatch;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700295 {
296 std::lock_guard l(mLock);
297 RETURN_STATUS_IF_ERROR(mMapper.prepareToOpenStream(
298 0 /*handle*/, aidlDevice, aidlFlags, aidlSource,
299 &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
300 }
Mikhail Naganovd5b643f2024-02-15 11:51:26 -0800301 *config = VALUE_OR_RETURN_STATUS(
302 ::aidl::android::aidl2legacy_AudioConfig_audio_config_t(aidlConfig, isInput));
303 if (mixPortConfig.id == 0) return BAD_VALUE; // HAL suggests a different config.
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800304 *size = aidlConfig.frameCount *
305 getFrameSizeInBytes(aidlConfig.base.format, aidlConfig.base.channelMask);
306 // Do not disarm cleanups to release temporary port configs.
307 return OK;
308}
309
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800310namespace {
311
312class StreamCallbackBase {
313 protected:
314 explicit StreamCallbackBase(const sp<CallbackBroker>& broker) : mBroker(broker) {}
315 public:
316 void* getCookie() const { return mCookie; }
317 void setCookie(void* cookie) { mCookie = cookie; }
318 sp<CallbackBroker> getBroker() const {
319 if (void* cookie = mCookie; cookie != nullptr) return mBroker.promote();
320 return nullptr;
321 }
322 private:
323 const wp<CallbackBroker> mBroker;
324 std::atomic<void*> mCookie;
325};
326
327template<class C>
328class StreamCallbackBaseHelper {
329 protected:
330 explicit StreamCallbackBaseHelper(const StreamCallbackBase& base) : mBase(base) {}
331 sp<C> getCb(const sp<CallbackBroker>& broker, void* cookie);
332 using CbRef = const sp<C>&;
333 ndk::ScopedAStatus runCb(const std::function<void(CbRef cb)>& f) {
334 if (auto cb = getCb(mBase.getBroker(), mBase.getCookie()); cb != nullptr) f(cb);
335 return ndk::ScopedAStatus::ok();
336 }
337 private:
338 const StreamCallbackBase& mBase;
339};
340
341template<>
342sp<StreamOutHalInterfaceCallback> StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>::getCb(
343 const sp<CallbackBroker>& broker, void* cookie) {
344 if (broker != nullptr) return broker->getStreamOutCallback(cookie);
345 return nullptr;
346}
347
348template<>
349sp<StreamOutHalInterfaceEventCallback>
350StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>::getCb(
351 const sp<CallbackBroker>& broker, void* cookie) {
352 if (broker != nullptr) return broker->getStreamOutEventCallback(cookie);
353 return nullptr;
354}
355
356template<>
357sp<StreamOutHalInterfaceLatencyModeCallback>
358StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>::getCb(
359 const sp<CallbackBroker>& broker, void* cookie) {
360 if (broker != nullptr) return broker->getStreamOutLatencyModeCallback(cookie);
361 return nullptr;
362}
363
364/*
365Note on the callback ownership.
366
367In the Binder ownership model, the server implementation is kept alive
368as long as there is any client (proxy object) alive. This is done by
369incrementing the refcount of the server-side object by the Binder framework.
370When it detects that the last client is gone, it decrements the refcount back.
371
372Thus, it is not needed to keep any references to StreamCallback on our
373side (after we have sent an instance to the client), because we are
374the server-side. The callback object will be kept alive as long as the HAL server
375holds a strong ref to IStreamCallback proxy.
376*/
377
378class OutputStreamCallbackAidl : public StreamCallbackBase,
379 public StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>,
380 public ::aidl::android::hardware::audio::core::BnStreamCallback {
381 public:
382 explicit OutputStreamCallbackAidl(const sp<CallbackBroker>& broker)
383 : StreamCallbackBase(broker),
384 StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>(
385 *static_cast<StreamCallbackBase*>(this)) {}
386 ndk::ScopedAStatus onTransferReady() override {
387 return runCb([](CbRef cb) { cb->onWriteReady(); });
388 }
389 ndk::ScopedAStatus onError() override {
390 return runCb([](CbRef cb) { cb->onError(); });
391 }
392 ndk::ScopedAStatus onDrainReady() override {
393 return runCb([](CbRef cb) { cb->onDrainReady(); });
394 }
395};
396
397class OutputStreamEventCallbackAidl :
398 public StreamCallbackBase,
399 public StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>,
400 public StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>,
401 public ::aidl::android::hardware::audio::core::BnStreamOutEventCallback {
402 public:
403 explicit OutputStreamEventCallbackAidl(const sp<CallbackBroker>& broker)
404 : StreamCallbackBase(broker),
405 StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>(
406 *static_cast<StreamCallbackBase*>(this)),
407 StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>(
408 *static_cast<StreamCallbackBase*>(this)) {}
Ryan Prichard78c5e452024-02-08 16:16:57 -0800409 ndk::ScopedAStatus onCodecFormatChanged(const std::vector<uint8_t>& halMetadata) override {
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800410 return StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>::runCb(
411 [&halMetadata](auto cb) { cb->onCodecFormatChanged(halMetadata); });
412 }
413 ndk::ScopedAStatus onRecommendedLatencyModeChanged(
414 const std::vector<AudioLatencyMode>& in_modes) override {
415 auto halModes = VALUE_OR_FATAL(
416 ::aidl::android::convertContainer<std::vector<audio_latency_mode_t>>(
417 in_modes,
418 ::aidl::android::aidl2legacy_AudioLatencyMode_audio_latency_mode_t));
419 return StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>::runCb(
420 [&halModes](auto cb) { cb->onRecommendedLatencyModeChanged(halModes); });
421 }
422};
423
424} // namespace
425
Mikhail Naganov31d46652023-01-10 18:29:25 +0000426status_t DeviceHalAidl::openOutputStream(
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800427 audio_io_handle_t handle, audio_devices_t devices,
428 audio_output_flags_t flags, struct audio_config* config,
429 const char* address,
Mikhail Naganov31d46652023-01-10 18:29:25 +0000430 sp<StreamOutHalInterface>* outStream) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800431 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700432 TIME_CHECK();
433 if (mModule == nullptr) return NO_INIT;
434 if (outStream == nullptr || config == nullptr) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000435 return BAD_VALUE;
436 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700437 constexpr bool isInput = false;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800438 int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
439 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(handle));
440 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700441 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, isInput));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800442 AudioDevice aidlDevice = VALUE_OR_RETURN_STATUS(
443 ::aidl::android::legacy2aidl_audio_device_AudioDevice(devices, address));
444 int32_t aidlOutputFlags = VALUE_OR_RETURN_STATUS(
445 ::aidl::android::legacy2aidl_audio_output_flags_t_int32_t_mask(flags));
446 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::output>(aidlOutputFlags);
447 AudioPortConfig mixPortConfig;
Mikhail Naganove93a0862023-03-15 17:06:59 -0700448 AudioPatch aidlPatch;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700449 Hal2AidlMapper::Cleanups cleanups(mMapperAccessor);
450 {
451 std::lock_guard l(mLock);
452 RETURN_STATUS_IF_ERROR(mMapper.prepareToOpenStream(aidlHandle, aidlDevice, aidlFlags,
453 AudioSource::SYS_RESERVED_INVALID /*only needed for input*/,
454 &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
455 }
456 *config = VALUE_OR_RETURN_STATUS(
457 ::aidl::android::aidl2legacy_AudioConfig_audio_config_t(aidlConfig, isInput));
Mikhail Naganovca92a5c2023-12-07 14:00:48 -0800458 if (mixPortConfig.id == 0) return BAD_VALUE; // HAL suggests a different config.
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800459 ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamArguments args;
460 args.portConfigId = mixPortConfig.id;
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800461 const bool isOffload = isBitPositionFlagSet(
462 aidlOutputFlags, AudioOutputFlags::COMPRESS_OFFLOAD);
463 std::shared_ptr<OutputStreamCallbackAidl> streamCb;
464 if (isOffload) {
465 streamCb = ndk::SharedRefBase::make<OutputStreamCallbackAidl>(this);
466 }
467 auto eventCb = ndk::SharedRefBase::make<OutputStreamEventCallbackAidl>(this);
468 if (isOffload) {
469 args.offloadInfo = aidlConfig.offloadInfo;
470 args.callback = streamCb;
471 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800472 args.bufferSizeFrames = aidlConfig.frameCount;
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800473 args.eventCallback = eventCb;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800474 ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamReturn ret;
475 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openOutputStream(args, &ret)));
Mikhail Naganov712d71b2023-02-23 17:57:16 -0800476 StreamContextAidl context(ret.desc, isOffload);
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800477 if (!context.isValid()) {
478 ALOGE("%s: Failed to created a valid stream context from the descriptor: %s",
479 __func__, ret.desc.toString().c_str());
480 return NO_INIT;
481 }
Mikhail Naganov8065bfd2024-03-25 14:59:49 -0700482 auto stream = sp<StreamOutHalAidl>::make(*config, std::move(context), aidlPatch.latenciesMs[0],
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700483 std::move(ret.stream), mVendorExt, this /*callbackBroker*/);
Mikhail Naganov8065bfd2024-03-25 14:59:49 -0700484 *outStream = stream;
485 /* StreamOutHalInterface* */ void* cbCookie = (*outStream).get();
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800486 {
487 std::lock_guard l(mLock);
488 mCallbacks.emplace(cbCookie, Callbacks{});
Mikhail Naganov78f7f9a2023-11-16 15:49:23 -0800489 mMapper.addStream(*outStream, mixPortConfig.id, aidlPatch.id);
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800490 }
Mikhail Naganov8065bfd2024-03-25 14:59:49 -0700491 if (streamCb) {
492 streamCb->setCookie(cbCookie);
493 // Although StreamOutHalAidl implements StreamOutHalInterfaceCallback,
494 // we always go via the CallbackBroker for consistency.
495 setStreamOutCallback(cbCookie, stream);
496 }
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800497 eventCb->setCookie(cbCookie);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800498 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000499 return OK;
500}
501
Mikhail Naganov31d46652023-01-10 18:29:25 +0000502status_t DeviceHalAidl::openInputStream(
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800503 audio_io_handle_t handle, audio_devices_t devices,
504 struct audio_config* config, audio_input_flags_t flags,
505 const char* address, audio_source_t source,
506 audio_devices_t outputDevice, const char* outputDeviceAddress,
Mikhail Naganov31d46652023-01-10 18:29:25 +0000507 sp<StreamInHalInterface>* inStream) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800508 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700509 TIME_CHECK();
510 if (mModule == nullptr) return NO_INIT;
511 if (inStream == nullptr || config == nullptr) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000512 return BAD_VALUE;
513 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700514 constexpr bool isInput = true;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800515 int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
516 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(handle));
517 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700518 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, isInput));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800519 AudioDevice aidlDevice = VALUE_OR_RETURN_STATUS(
520 ::aidl::android::legacy2aidl_audio_device_AudioDevice(devices, address));
521 int32_t aidlInputFlags = VALUE_OR_RETURN_STATUS(
522 ::aidl::android::legacy2aidl_audio_input_flags_t_int32_t_mask(flags));
523 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::input>(aidlInputFlags);
524 AudioSource aidlSource = VALUE_OR_RETURN_STATUS(
525 ::aidl::android::legacy2aidl_audio_source_t_AudioSource(source));
526 AudioPortConfig mixPortConfig;
Mikhail Naganove93a0862023-03-15 17:06:59 -0700527 AudioPatch aidlPatch;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700528 Hal2AidlMapper::Cleanups cleanups(mMapperAccessor);
529 {
530 std::lock_guard l(mLock);
531 RETURN_STATUS_IF_ERROR(mMapper.prepareToOpenStream(
532 aidlHandle, aidlDevice, aidlFlags, aidlSource,
533 &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
534 }
535 *config = VALUE_OR_RETURN_STATUS(
536 ::aidl::android::aidl2legacy_AudioConfig_audio_config_t(aidlConfig, isInput));
Mikhail Naganovca92a5c2023-12-07 14:00:48 -0800537 if (mixPortConfig.id == 0) return BAD_VALUE; // HAL suggests a different config.
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800538 ::aidl::android::hardware::audio::core::IModule::OpenInputStreamArguments args;
539 args.portConfigId = mixPortConfig.id;
540 RecordTrackMetadata aidlTrackMetadata{
541 .source = aidlSource, .gain = 1, .channelMask = aidlConfig.base.channelMask };
542 if (outputDevice != AUDIO_DEVICE_NONE) {
543 aidlTrackMetadata.destinationDevice = VALUE_OR_RETURN_STATUS(
544 ::aidl::android::legacy2aidl_audio_device_AudioDevice(
545 outputDevice, outputDeviceAddress));
546 }
547 args.sinkMetadata.tracks.push_back(std::move(aidlTrackMetadata));
548 args.bufferSizeFrames = aidlConfig.frameCount;
549 ::aidl::android::hardware::audio::core::IModule::OpenInputStreamReturn ret;
550 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openInputStream(args, &ret)));
Mikhail Naganov712d71b2023-02-23 17:57:16 -0800551 StreamContextAidl context(ret.desc, false /*isAsynchronous*/);
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800552 if (!context.isValid()) {
553 ALOGE("%s: Failed to created a valid stream context from the descriptor: %s",
554 __func__, ret.desc.toString().c_str());
555 return NO_INIT;
556 }
Mikhail Naganove93a0862023-03-15 17:06:59 -0700557 *inStream = sp<StreamInHalAidl>::make(*config, std::move(context), aidlPatch.latenciesMs[0],
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700558 std::move(ret.stream), mVendorExt, this /*micInfoProvider*/);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700559 {
560 std::lock_guard l(mLock);
Mikhail Naganov78f7f9a2023-11-16 15:49:23 -0800561 mMapper.addStream(*inStream, mixPortConfig.id, aidlPatch.id);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700562 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800563 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000564 return OK;
565}
566
567status_t DeviceHalAidl::supportsAudioPatches(bool* supportsPatches) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700568 if (supportsPatches == nullptr) {
569 return BAD_VALUE;
570 }
Shunkai Yao51202502022-12-12 06:11:46 +0000571 *supportsPatches = true;
572 return OK;
573}
574
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800575status_t DeviceHalAidl::createAudioPatch(unsigned int num_sources,
576 const struct audio_port_config* sources,
577 unsigned int num_sinks,
578 const struct audio_port_config* sinks,
579 audio_patch_handle_t* patch) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800580 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000581 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700582 if (mModule == nullptr) return NO_INIT;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800583 if (num_sinks > AUDIO_PATCH_PORTS_MAX || num_sources > AUDIO_PATCH_PORTS_MAX ||
584 sources == nullptr || sinks == nullptr || patch == nullptr) {
585 return BAD_VALUE;
586 }
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800587 // When the patch handle (*patch) is AUDIO_PATCH_HANDLE_NONE, it means
588 // the framework wants to create a new patch. The handle has to be generated
589 // by the HAL. Since handles generated this way can only be unique within
590 // a HAL module, the framework generates a globally unique handle, and maps
591 // it on the <HAL module, patch handle> pair.
592 // When the patch handle is set, it meant the framework intends to update
593 // an existing patch.
594 //
595 // This behavior corresponds to HAL module behavior, with the only difference
596 // that the HAL module uses `int32_t` for patch IDs. The following assert ensures
597 // that both the framework and the HAL use the same value for "no ID":
598 static_assert(AUDIO_PATCH_HANDLE_NONE == 0);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800599
600 // Upon conversion, mix port configs contain audio configuration, while
601 // device port configs contain device address. This data is used to find
602 // or create HAL configs.
603 std::vector<AudioPortConfig> aidlSources, aidlSinks;
604 for (unsigned int i = 0; i < num_sources; ++i) {
605 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
606 sources[i].role, sources[i].type)) ==
607 ::aidl::android::AudioPortDirection::INPUT;
608 aidlSources.push_back(VALUE_OR_RETURN_STATUS(
609 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
610 sources[i], isInput, 0)));
611 }
612 for (unsigned int i = 0; i < num_sinks; ++i) {
613 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
614 sinks[i].role, sinks[i].type)) ==
615 ::aidl::android::AudioPortDirection::INPUT;
616 aidlSinks.push_back(VALUE_OR_RETURN_STATUS(
617 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
618 sinks[i], isInput, 0)));
619 }
Mikhail Naganov6b5da722024-03-14 12:59:32 -0700620 int32_t aidlPatchId = static_cast<int32_t>(*patch);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700621 Hal2AidlMapper::Cleanups cleanups(mMapperAccessor);
622 {
623 std::lock_guard l(mLock);
Mikhail Naganov6b5da722024-03-14 12:59:32 -0700624 // Check for patches that only exist for the framework, or have different HAL patch ID.
625 if (int32_t aidlHalPatchId = mMapper.findFwkPatch(aidlPatchId); aidlHalPatchId != 0) {
626 if (aidlHalPatchId == aidlPatchId) {
627 // This patch was previously released by the HAL. Thus we need to pass '0'
628 // to the HAL to obtain a new patch.
629 int32_t newAidlPatchId = 0;
630 RETURN_STATUS_IF_ERROR(mMapper.createOrUpdatePatch(
631 aidlSources, aidlSinks, &newAidlPatchId, &cleanups));
632 mMapper.updateFwkPatch(aidlPatchId, newAidlPatchId);
633 } else {
634 RETURN_STATUS_IF_ERROR(mMapper.createOrUpdatePatch(
635 aidlSources, aidlSinks, &aidlHalPatchId, &cleanups));
636 }
637 } else {
638 RETURN_STATUS_IF_ERROR(mMapper.createOrUpdatePatch(
639 aidlSources, aidlSinks, &aidlPatchId, &cleanups));
640 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800641 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700642 *patch = static_cast<audio_patch_handle_t>(aidlPatchId);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800643 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000644 return OK;
645}
646
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800647status_t DeviceHalAidl::releaseAudioPatch(audio_patch_handle_t patch) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800648 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000649 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700650 if (mModule == nullptr) return NO_INIT;
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800651 static_assert(AUDIO_PATCH_HANDLE_NONE == 0);
652 if (patch == AUDIO_PATCH_HANDLE_NONE) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800653 return BAD_VALUE;
654 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700655 std::lock_guard l(mLock);
Mikhail Naganov6b5da722024-03-14 12:59:32 -0700656 // Check for patches that only exist for the framework, or have different HAL patch ID.
657 int32_t aidlPatchId = static_cast<int32_t>(patch);
658 if (int32_t aidlHalPatchId = mMapper.findFwkPatch(aidlPatchId); aidlHalPatchId != 0) {
659 if (aidlHalPatchId == aidlPatchId) {
660 // This patch was previously released by the HAL, just need to finish its removal.
661 mMapper.eraseFwkPatch(aidlPatchId);
662 return OK;
663 } else {
664 // This patch has a HAL patch ID which is different
665 aidlPatchId = aidlHalPatchId;
666 }
667 }
668 RETURN_STATUS_IF_ERROR(mMapper.releaseAudioPatch(aidlPatchId));
Shunkai Yao51202502022-12-12 06:11:46 +0000669 return OK;
670}
671
Mikhail Naganove93a0862023-03-15 17:06:59 -0700672status_t DeviceHalAidl::getAudioPort(struct audio_port* port) {
Mikhail Naganove93a0862023-03-15 17:06:59 -0700673 if (port == nullptr) {
674 return BAD_VALUE;
675 }
676 audio_port_v7 portV7;
677 audio_populate_audio_port_v7(port, &portV7);
678 RETURN_STATUS_IF_ERROR(getAudioPort(&portV7));
679 return audio_populate_audio_port(&portV7, port) ? OK : BAD_VALUE;
680}
681
682status_t DeviceHalAidl::getAudioPort(struct audio_port_v7 *port) {
683 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
684 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700685 if (mModule == nullptr) return NO_INIT;
Mikhail Naganove93a0862023-03-15 17:06:59 -0700686 if (port == nullptr) {
687 return BAD_VALUE;
688 }
689 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(port->role, port->type)) ==
690 ::aidl::android::AudioPortDirection::INPUT;
691 auto aidlPort = VALUE_OR_RETURN_STATUS(
692 ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
693 if (aidlPort.ext.getTag() != AudioPortExt::device) {
694 ALOGE("%s: provided port is not a device port (module %s): %s",
695 __func__, mInstance.c_str(), aidlPort.toString().c_str());
696 return BAD_VALUE;
697 }
698 const auto& matchDevice = aidlPort.ext.get<AudioPortExt::device>().device;
699 // It seems that we don't have to call HAL since all valid ports have been added either
700 // during initialization, or while handling connection of an external device.
Mikhail Naganove93a0862023-03-15 17:06:59 -0700701 const int32_t fwkId = aidlPort.id;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700702 {
703 std::lock_guard l(mLock);
704 RETURN_STATUS_IF_ERROR(mMapper.getAudioPortCached(matchDevice, &aidlPort));
705 }
Mikhail Naganove93a0862023-03-15 17:06:59 -0700706 aidlPort.id = fwkId;
707 *port = VALUE_OR_RETURN_STATUS(::aidl::android::aidl2legacy_AudioPort_audio_port_v7(
708 aidlPort, isInput));
709 return OK;
710}
711
jiabin12537fc2023-10-12 17:56:08 +0000712status_t DeviceHalAidl::getAudioMixPort(const struct audio_port_v7 *devicePort,
713 struct audio_port_v7 *mixPort) {
714 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700715 TIME_CHECK();
716 if (mModule == nullptr) return NO_INIT;
717 if (devicePort == nullptr || mixPort == nullptr ||
718 devicePort->type != AUDIO_PORT_TYPE_DEVICE || mixPort->type != AUDIO_PORT_TYPE_MIX) {
jiabin12537fc2023-10-12 17:56:08 +0000719 return BAD_VALUE;
720 }
721 const int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
722 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(mixPort->ext.mix.handle));
jiabin12537fc2023-10-12 17:56:08 +0000723 AudioPort port;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700724 {
725 std::lock_guard l(mLock);
726 RETURN_STATUS_IF_ERROR(mMapper.getAudioMixPort(aidlHandle, &port));
jiabin12537fc2023-10-12 17:56:08 +0000727 }
728 const bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
729 mixPort->role, mixPort->type)) == ::aidl::android::AudioPortDirection::INPUT;
730 *mixPort = VALUE_OR_RETURN_STATUS(::aidl::android::aidl2legacy_AudioPort_audio_port_v7(
731 port, isInput));
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700732 return OK;
jiabin12537fc2023-10-12 17:56:08 +0000733}
734
Mikhail Naganove93a0862023-03-15 17:06:59 -0700735status_t DeviceHalAidl::setAudioPortConfig(const struct audio_port_config* config) {
736 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
737 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700738 if (mModule == nullptr) return NO_INIT;
Mikhail Naganove93a0862023-03-15 17:06:59 -0700739 if (config == nullptr) {
740 return BAD_VALUE;
741 }
742 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
743 config->role, config->type)) == ::aidl::android::AudioPortDirection::INPUT;
744 AudioPortConfig requestedPortConfig = VALUE_OR_RETURN_STATUS(
745 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
746 *config, isInput, 0 /*portId*/));
747 AudioPortConfig portConfig;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700748 std::lock_guard l(mLock);
Mikhail Naganovca92a5c2023-12-07 14:00:48 -0800749 return mMapper.setPortConfig(requestedPortConfig, std::set<int32_t>(), &portConfig);
Shunkai Yao51202502022-12-12 06:11:46 +0000750}
751
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800752MicrophoneInfoProvider::Info const* DeviceHalAidl::getMicrophoneInfo() {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700753 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
754 TIME_CHECK();
755 if (!mModule) return {};
756 std::lock_guard l(mLock);
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800757 if (mMicrophones.status == Microphones::Status::UNKNOWN) {
758 TIME_CHECK();
759 std::vector<MicrophoneInfo> aidlInfo;
760 status_t status = statusTFromBinderStatus(mModule->getMicrophones(&aidlInfo));
761 if (status == OK) {
762 mMicrophones.status = Microphones::Status::QUERIED;
763 mMicrophones.info = std::move(aidlInfo);
764 } else if (status == INVALID_OPERATION) {
765 mMicrophones.status = Microphones::Status::NOT_SUPPORTED;
766 } else {
767 ALOGE("%s: Unexpected status from 'IModule.getMicrophones': %d", __func__, status);
768 return {};
769 }
770 }
771 if (mMicrophones.status == Microphones::Status::QUERIED) {
772 return &mMicrophones.info;
773 }
774 return {}; // NOT_SUPPORTED
775}
776
Shunkai Yao51202502022-12-12 06:11:46 +0000777status_t DeviceHalAidl::getMicrophones(
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800778 std::vector<audio_microphone_characteristic_t>* microphones) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700779 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
780 TIME_CHECK();
781 if (mModule == nullptr) return NO_INIT;
782 if (microphones == nullptr) {
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800783 return BAD_VALUE;
784 }
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800785 auto staticInfo = getMicrophoneInfo();
786 if (!staticInfo) return INVALID_OPERATION;
787 std::vector<MicrophoneDynamicInfo> emptyDynamicInfo;
788 emptyDynamicInfo.reserve(staticInfo->size());
789 std::transform(staticInfo->begin(), staticInfo->end(), std::back_inserter(emptyDynamicInfo),
790 [](const auto& info) { return MicrophoneDynamicInfo{ .id = info.id }; });
791 *microphones = VALUE_OR_RETURN_STATUS(
792 ::aidl::android::convertContainers<std::vector<audio_microphone_characteristic_t>>(
793 *staticInfo, emptyDynamicInfo,
794 ::aidl::android::aidl2legacy_MicrophoneInfos_audio_microphone_characteristic_t)
795 );
Shunkai Yao51202502022-12-12 06:11:46 +0000796 return OK;
797}
798
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700799status_t DeviceHalAidl::addDeviceEffect(
800 const struct audio_port_config *device, sp<EffectHalInterface> effect) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700801 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700802 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700803 if (mModule == nullptr) return NO_INIT;
804 if (device == nullptr || effect == nullptr) {
Shunkai Yao51202502022-12-12 06:11:46 +0000805 return BAD_VALUE;
806 }
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700807 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
808 device->role, device->type)) == ::aidl::android::AudioPortDirection::INPUT;
809 auto requestedPortConfig = VALUE_OR_RETURN_STATUS(
810 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
811 *device, isInput, 0));
812 if (requestedPortConfig.ext.getTag() != AudioPortExt::Tag::device) {
813 ALOGE("%s: provided port config is not a device port config: %s",
814 __func__, requestedPortConfig.toString().c_str());
815 return BAD_VALUE;
816 }
817 AudioPortConfig devicePortConfig;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700818 Hal2AidlMapper::Cleanups cleanups(mMapperAccessor);
819 {
820 std::lock_guard l(mLock);
Mikhail Naganovca92a5c2023-12-07 14:00:48 -0800821 RETURN_STATUS_IF_ERROR(mMapper.setPortConfig(
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700822 requestedPortConfig, {} /*destinationPortIds*/, &devicePortConfig, &cleanups));
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700823 }
824 auto aidlEffect = sp<effect::EffectHalAidl>::cast(effect);
825 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->addDeviceEffect(
826 devicePortConfig.id, aidlEffect->getIEffect())));
827 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000828 return OK;
829}
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700830status_t DeviceHalAidl::removeDeviceEffect(
831 const struct audio_port_config *device, sp<EffectHalInterface> effect) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700832 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700833 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700834 if (mModule == nullptr) return NO_INIT;
835 if (device == nullptr || effect == nullptr) {
Shunkai Yao51202502022-12-12 06:11:46 +0000836 return BAD_VALUE;
837 }
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700838 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
839 device->role, device->type)) == ::aidl::android::AudioPortDirection::INPUT;
840 auto requestedPortConfig = VALUE_OR_RETURN_STATUS(
841 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
842 *device, isInput, 0));
843 if (requestedPortConfig.ext.getTag() != AudioPortExt::Tag::device) {
844 ALOGE("%s: provided port config is not a device port config: %s",
845 __func__, requestedPortConfig.toString().c_str());
846 return BAD_VALUE;
847 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700848 AudioPortConfig devicePortConfig;
849 {
850 std::lock_guard l(mLock);
851 RETURN_STATUS_IF_ERROR(mMapper.findPortConfig(
852 requestedPortConfig.ext.get<AudioPortExt::Tag::device>().device,
853 &devicePortConfig));
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700854 }
855 auto aidlEffect = sp<effect::EffectHalAidl>::cast(effect);
856 return statusTFromBinderStatus(mModule->removeDeviceEffect(
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700857 devicePortConfig.id, aidlEffect->getIEffect()));
Shunkai Yao51202502022-12-12 06:11:46 +0000858}
859
860status_t DeviceHalAidl::getMmapPolicyInfos(
David Li9cf5e622023-03-21 00:51:10 +0800861 media::audio::common::AudioMMapPolicyType policyType,
862 std::vector<media::audio::common::AudioMMapPolicyInfo>* policyInfos) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700863 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000864 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700865 if (mModule == nullptr) return NO_INIT;
Mikhail Naganov25bc9a22023-04-21 18:48:16 -0700866 AudioMMapPolicyType mmapPolicyType = VALUE_OR_RETURN_STATUS(
867 cpp2ndk_AudioMMapPolicyType(policyType));
David Li9cf5e622023-03-21 00:51:10 +0800868
869 std::vector<AudioMMapPolicyInfo> mmapPolicyInfos;
870
871 if (status_t status = statusTFromBinderStatus(
872 mModule->getMmapPolicyInfos(mmapPolicyType, &mmapPolicyInfos)); status != OK) {
873 return status;
874 }
875
876 *policyInfos = VALUE_OR_RETURN_STATUS(
877 convertContainer<std::vector<media::audio::common::AudioMMapPolicyInfo>>(
878 mmapPolicyInfos, ndk2cpp_AudioMMapPolicyInfo));
Shunkai Yao51202502022-12-12 06:11:46 +0000879 return OK;
880}
881
882int32_t DeviceHalAidl::getAAudioMixerBurstCount() {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700883 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000884 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700885 if (mModule == nullptr) return NO_INIT;
David Li9cf5e622023-03-21 00:51:10 +0800886 int32_t mixerBurstCount = 0;
887 if (mModule->getAAudioMixerBurstCount(&mixerBurstCount).isOk()) {
888 return mixerBurstCount;
889 }
890 return 0;
Shunkai Yao51202502022-12-12 06:11:46 +0000891}
892
893int32_t DeviceHalAidl::getAAudioHardwareBurstMinUsec() {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700894 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000895 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700896 if (mModule == nullptr) return NO_INIT;
David Li9cf5e622023-03-21 00:51:10 +0800897 int32_t hardwareBurstMinUsec = 0;
898 if (mModule->getAAudioHardwareBurstMinUsec(&hardwareBurstMinUsec).isOk()) {
899 return hardwareBurstMinUsec;
900 }
901 return 0;
Shunkai Yao51202502022-12-12 06:11:46 +0000902}
903
904error::Result<audio_hw_sync_t> DeviceHalAidl::getHwAvSync() {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700905 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000906 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700907 if (mModule == nullptr) return NO_INIT;
Mikhail Naganov08a62ab2023-03-14 17:11:51 -0700908 int32_t aidlHwAvSync;
909 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->generateHwAvSyncId(&aidlHwAvSync)));
910 return VALUE_OR_RETURN_STATUS(
911 ::aidl::android::aidl2legacy_int32_t_audio_hw_sync_t(aidlHwAvSync));
Shunkai Yao51202502022-12-12 06:11:46 +0000912}
913
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000914status_t DeviceHalAidl::dump(int fd, const Vector<String16>& args) {
915 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700916 if (mModule == nullptr) return NO_INIT;
David Li21289462024-04-17 01:09:23 +0800917 Vector<String16> newArgs = args;
918 newArgs.push(String16(kDumpFromAudioServerArgument));
919 return mModule->dump(fd, Args(newArgs).args(), newArgs.size());
David Li9cf5e622023-03-21 00:51:10 +0800920}
Shunkai Yao51202502022-12-12 06:11:46 +0000921
Eric Laurent7af6ee72023-06-29 11:44:54 +0200922status_t DeviceHalAidl::supportsBluetoothVariableLatency(bool* supports) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700923 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000924 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700925 if (mModule == nullptr) return NO_INIT;
Mikhail Naganov3ac95c92023-04-12 13:14:30 -0700926 if (supports == nullptr) {
927 return BAD_VALUE;
928 }
929 return statusTFromBinderStatus(mModule->supportsVariableLatency(supports));
Shunkai Yao51202502022-12-12 06:11:46 +0000930}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000931
Vlad Popa03bd5bc2023-01-17 16:16:51 +0100932status_t DeviceHalAidl::getSoundDoseInterface(const std::string& module,
933 ::ndk::SpAIBinder* soundDoseBinder) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700934 if (soundDoseBinder == nullptr) {
935 return BAD_VALUE;
936 }
Vlad Popa03bd5bc2023-01-17 16:16:51 +0100937 if (mSoundDose == nullptr) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700938 ALOGE("%s failed to retrieve the sound dose interface for module %s",
939 __func__, module.c_str());
940 return BAD_VALUE;
Vlad Popa03bd5bc2023-01-17 16:16:51 +0100941 }
Vlad Popae1f33902023-10-30 19:48:25 -0700942
943 if (mSoundDose == nullptr) {
944 ALOGE("%s failed to return the sound dose interface for module %s: not implemented",
945 __func__,
946 module.c_str());
947 return NO_INIT;
948 }
949
Vlad Popa03bd5bc2023-01-17 16:16:51 +0100950 *soundDoseBinder = mSoundDose->asBinder();
951 ALOGI("%s using audio AIDL HAL sound dose interface", __func__);
Vlad Popa03bd5bc2023-01-17 16:16:51 +0100952 return OK;
953}
jiabin872de702023-04-27 22:04:31 +0000954
955status_t DeviceHalAidl::prepareToDisconnectExternalDevice(const struct audio_port_v7* port) {
jiabin62750c22023-12-21 22:06:07 +0000956 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
957 TIME_CHECK();
958 if (mModule == nullptr) return NO_INIT;
959 if (port == nullptr) {
960 return BAD_VALUE;
961 }
962 const bool isInput = VALUE_OR_RETURN_STATUS(
963 ::aidl::android::portDirection(port->role, port->type)) ==
964 ::aidl::android::AudioPortDirection::INPUT;
965 AudioPort aidlPort = VALUE_OR_RETURN_STATUS(
966 ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
967 if (aidlPort.ext.getTag() != AudioPortExt::device) {
968 ALOGE("%s: provided port is not a device port (module %s): %s",
969 __func__, mInstance.c_str(), aidlPort.toString().c_str());
970 return BAD_VALUE;
971 }
972 status_t status = NO_ERROR;
973 {
974 std::lock_guard l(mLock);
975 status = mMapper.prepareToDisconnectExternalDevice(aidlPort);
976 }
977 if (status == UNKNOWN_TRANSACTION) {
978 // If there is not AIDL API defined for `prepareToDisconnectExternalDevice`.
979 // Call `setConnectedState` instead.
980 RETURN_STATUS_IF_ERROR(setConnectedState(port, false /*connected*/));
981 std::lock_guard l(mLock);
982 mDeviceDisconnectionNotified.insert(port->id);
983 // Return that there was no error as otherwise the disconnection procedure will not be
984 // considered complete for upper layers, and 'setConnectedState' will not be called again
985 return OK;
986 } else {
987 return status;
988 }
jiabin872de702023-04-27 22:04:31 +0000989}
990
Mikhail Naganove93a0862023-03-15 17:06:59 -0700991status_t DeviceHalAidl::setConnectedState(const struct audio_port_v7 *port, bool connected) {
Mikhail Naganovae9063d2023-11-07 16:43:51 -0800992 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganove93a0862023-03-15 17:06:59 -0700993 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700994 if (mModule == nullptr) return NO_INIT;
Mikhail Naganove93a0862023-03-15 17:06:59 -0700995 if (port == nullptr) {
996 return BAD_VALUE;
997 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700998 if (!connected) {
999 std::lock_guard l(mLock);
1000 if (mDeviceDisconnectionNotified.erase(port->id) > 0) {
1001 // For device disconnection, APM will first call `prepareToDisconnectExternalDevice`
jiabin62750c22023-12-21 22:06:07 +00001002 // and then call `setConnectedState`. If `prepareToDisconnectExternalDevice` doesn't
1003 // exit, `setConnectedState` will be called when calling
1004 // `prepareToDisconnectExternalDevice`. Do not call to the HAL if previous call is
1005 // successful. Also remove the cache here to avoid a large cache after a long run.
Mikhail Naganovac9d4e72023-10-23 12:00:09 -07001006 return OK;
1007 }
jiabin872de702023-04-27 22:04:31 +00001008 }
Mikhail Naganove93a0862023-03-15 17:06:59 -07001009 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(port->role, port->type)) ==
1010 ::aidl::android::AudioPortDirection::INPUT;
1011 AudioPort aidlPort = VALUE_OR_RETURN_STATUS(
1012 ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
1013 if (aidlPort.ext.getTag() != AudioPortExt::device) {
1014 ALOGE("%s: provided port is not a device port (module %s): %s",
1015 __func__, mInstance.c_str(), aidlPort.toString().c_str());
1016 return BAD_VALUE;
1017 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -07001018 std::lock_guard l(mLock);
1019 return mMapper.setDevicePortConnectedState(aidlPort, connected);
Mikhail Naganove93a0862023-03-15 17:06:59 -07001020}
1021
1022status_t DeviceHalAidl::setSimulateDeviceConnections(bool enabled) {
1023 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -07001024 if (mModule == nullptr) return NO_INIT;
1025 {
1026 std::lock_guard l(mLock);
Mikhail Naganov6b5da722024-03-14 12:59:32 -07001027 mMapper.resetUnusedPatchesAndPortConfigs();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -07001028 }
Mikhail Naganove93a0862023-03-15 17:06:59 -07001029 ModuleDebug debug{ .simulateDeviceConnections = enabled };
1030 status_t status = statusTFromBinderStatus(mModule->setModuleDebug(debug));
1031 // This is important to log as it affects HAL behavior.
1032 if (status == OK) {
1033 ALOGI("%s: set enabled: %d", __func__, enabled);
1034 } else {
1035 ALOGW("%s: set enabled to %d failed: %d", __func__, enabled, status);
1036 }
1037 return status;
1038}
1039
Mikhail Naganove7a26ad2023-05-25 17:36:48 -07001040status_t DeviceHalAidl::filterAndRetrieveBtA2dpParameters(
1041 AudioParameter &keys, AudioParameter *result) {
Mikhail Naganove7a26ad2023-05-25 17:36:48 -07001042 if (String8 key = String8(AudioParameter::keyReconfigA2dpSupported); keys.containsKey(key)) {
1043 keys.remove(key);
David Lia7761ed2023-11-03 17:22:07 +00001044 if (mBluetoothA2dp != nullptr) {
1045 bool supports;
1046 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
1047 mBluetoothA2dp->supportsOffloadReconfiguration(&supports)));
1048 result->addInt(key, supports ? 1 : 0);
1049 } else {
1050 ALOGI("%s: no IBluetoothA2dp on %s", __func__, mInstance.c_str());
1051 result->addInt(key, 0);
1052 }
Mikhail Naganove7a26ad2023-05-25 17:36:48 -07001053 }
1054 return OK;
1055}
1056
Eric Laurent7e3c0832023-11-30 15:04:50 +01001057status_t DeviceHalAidl::filterAndRetrieveBtLeParameters(
1058 AudioParameter &keys, AudioParameter *result) {
1059 if (String8 key = String8(AudioParameter::keyReconfigLeSupported); keys.containsKey(key)) {
1060 keys.remove(key);
1061 if (mBluetoothLe != nullptr) {
1062 bool supports;
1063 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
1064 mBluetoothLe->supportsOffloadReconfiguration(&supports)));
1065 result->addInt(key, supports ? 1 : 0);
1066 } else {
1067 ALOGI("%s: no mBluetoothLe on %s", __func__, mInstance.c_str());
1068 result->addInt(key, 0);
1069 }
1070 }
1071 return OK;
1072}
1073
Mikhail Naganovccc82112023-04-27 18:14:15 -07001074status_t DeviceHalAidl::filterAndUpdateBtA2dpParameters(AudioParameter &parameters) {
Mikhail Naganovccc82112023-04-27 18:14:15 -07001075 std::optional<bool> a2dpEnabled;
Mikhail Naganove7a26ad2023-05-25 17:36:48 -07001076 std::optional<std::vector<VendorParameter>> reconfigureOffload;
Mikhail Naganovccc82112023-04-27 18:14:15 -07001077 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1078 parameters, String8(AudioParameter::keyBtA2dpSuspended),
1079 [&a2dpEnabled](const String8& trueOrFalse) {
1080 if (trueOrFalse == AudioParameter::valueTrue) {
1081 a2dpEnabled = false; // 'suspended' == true
1082 return OK;
1083 } else if (trueOrFalse == AudioParameter::valueFalse) {
1084 a2dpEnabled = true; // 'suspended' == false
1085 return OK;
1086 }
1087 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1088 AudioParameter::keyBtA2dpSuspended, trueOrFalse.c_str());
1089 return BAD_VALUE;
1090 }));
Mikhail Naganove7a26ad2023-05-25 17:36:48 -07001091 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1092 parameters, String8(AudioParameter::keyReconfigA2dp),
1093 [&](const String8& value) -> status_t {
Mikhail Naganove5011002024-01-26 10:57:19 -08001094 std::vector<VendorParameter> result;
1095 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
1096 mVendorExt->parseBluetoothA2dpReconfigureOffload(
1097 std::string(value.c_str()), &result)));
1098 reconfigureOffload = std::move(result);
Mikhail Naganove7a26ad2023-05-25 17:36:48 -07001099 return OK;
1100 }));
Mikhail Naganovccc82112023-04-27 18:14:15 -07001101 if (mBluetoothA2dp != nullptr && a2dpEnabled.has_value()) {
1102 return statusTFromBinderStatus(mBluetoothA2dp->setEnabled(a2dpEnabled.value()));
1103 }
Mikhail Naganove7a26ad2023-05-25 17:36:48 -07001104 if (mBluetoothA2dp != nullptr && reconfigureOffload.has_value()) {
1105 return statusTFromBinderStatus(mBluetoothA2dp->reconfigureOffload(
1106 reconfigureOffload.value()));
1107 }
Mikhail Naganovccc82112023-04-27 18:14:15 -07001108 return OK;
1109}
1110
1111status_t DeviceHalAidl::filterAndUpdateBtHfpParameters(AudioParameter &parameters) {
Mikhail Naganovccc82112023-04-27 18:14:15 -07001112 IBluetooth::HfpConfig hfpConfig;
1113 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1114 parameters, String8(AudioParameter::keyBtHfpEnable),
1115 [&hfpConfig](const String8& trueOrFalse) {
1116 if (trueOrFalse == AudioParameter::valueTrue) {
1117 hfpConfig.isEnabled = Boolean{ .value = true };
1118 return OK;
1119 } else if (trueOrFalse == AudioParameter::valueFalse) {
1120 hfpConfig.isEnabled = Boolean{ .value = false };
1121 return OK;
1122 }
1123 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1124 AudioParameter::keyBtHfpEnable, trueOrFalse.c_str());
1125 return BAD_VALUE;
1126 }));
1127 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
1128 parameters, String8(AudioParameter::keyBtHfpSamplingRate),
1129 [&hfpConfig](int sampleRate) {
1130 return sampleRate > 0 ?
1131 hfpConfig.sampleRate = Int{ .value = sampleRate }, OK : BAD_VALUE;
1132 }));
1133 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
1134 parameters, String8(AudioParameter::keyBtHfpVolume),
1135 [&hfpConfig](int volume0to15) {
1136 if (volume0to15 >= 0 && volume0to15 <= 15) {
1137 hfpConfig.volume = Float{ .value = volume0to15 / 15.0f };
1138 return OK;
1139 }
1140 return BAD_VALUE;
1141 }));
1142 if (mBluetooth != nullptr && hfpConfig != IBluetooth::HfpConfig{}) {
1143 IBluetooth::HfpConfig newHfpConfig;
1144 return statusTFromBinderStatus(mBluetooth->setHfpConfig(hfpConfig, &newHfpConfig));
1145 }
1146 return OK;
1147}
1148
1149status_t DeviceHalAidl::filterAndUpdateBtLeParameters(AudioParameter &parameters) {
Mikhail Naganovccc82112023-04-27 18:14:15 -07001150 std::optional<bool> leEnabled;
Eric Laurent7e3c0832023-11-30 15:04:50 +01001151 std::optional<std::vector<VendorParameter>> reconfigureOffload;
Mikhail Naganovccc82112023-04-27 18:14:15 -07001152 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1153 parameters, String8(AudioParameter::keyBtLeSuspended),
1154 [&leEnabled](const String8& trueOrFalse) {
1155 if (trueOrFalse == AudioParameter::valueTrue) {
1156 leEnabled = false; // 'suspended' == true
1157 return OK;
1158 } else if (trueOrFalse == AudioParameter::valueFalse) {
1159 leEnabled = true; // 'suspended' == false
1160 return OK;
1161 }
1162 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1163 AudioParameter::keyBtLeSuspended, trueOrFalse.c_str());
1164 return BAD_VALUE;
1165 }));
Eric Laurent7e3c0832023-11-30 15:04:50 +01001166 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1167 parameters, String8(AudioParameter::keyReconfigLe),
1168 [&](const String8& value) -> status_t {
1169 if (mVendorExt != nullptr) {
1170 std::vector<VendorParameter> result;
1171 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
1172 mVendorExt->parseBluetoothLeReconfigureOffload(
1173 std::string(value.c_str()), &result)));
1174 reconfigureOffload = std::move(result);
1175 } else {
1176 reconfigureOffload = std::vector<VendorParameter>();
1177 }
1178 return OK;
1179 }));
Mikhail Naganovccc82112023-04-27 18:14:15 -07001180 if (mBluetoothLe != nullptr && leEnabled.has_value()) {
1181 return statusTFromBinderStatus(mBluetoothLe->setEnabled(leEnabled.value()));
1182 }
Eric Laurent7e3c0832023-11-30 15:04:50 +01001183 if (mBluetoothLe != nullptr && reconfigureOffload.has_value()) {
1184 return statusTFromBinderStatus(mBluetoothLe->reconfigureOffload(
1185 reconfigureOffload.value()));
1186 }
Mikhail Naganovccc82112023-04-27 18:14:15 -07001187 return OK;
1188}
1189
1190status_t DeviceHalAidl::filterAndUpdateBtScoParameters(AudioParameter &parameters) {
Mikhail Naganovccc82112023-04-27 18:14:15 -07001191 IBluetooth::ScoConfig scoConfig;
1192 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1193 parameters, String8(AudioParameter::keyBtSco),
1194 [&scoConfig](const String8& onOrOff) {
1195 if (onOrOff == AudioParameter::valueOn) {
1196 scoConfig.isEnabled = Boolean{ .value = true };
1197 return OK;
1198 } else if (onOrOff == AudioParameter::valueOff) {
1199 scoConfig.isEnabled = Boolean{ .value = false };
1200 return OK;
1201 }
1202 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1203 AudioParameter::keyBtSco, onOrOff.c_str());
1204 return BAD_VALUE;
1205 }));
1206 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1207 parameters, String8(AudioParameter::keyBtScoHeadsetName),
1208 [&scoConfig](const String8& name) {
1209 scoConfig.debugName = name;
1210 return OK;
1211 }));
1212 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1213 parameters, String8(AudioParameter::keyBtNrec),
1214 [&scoConfig](const String8& onOrOff) {
1215 if (onOrOff == AudioParameter::valueOn) {
1216 scoConfig.isNrecEnabled = Boolean{ .value = true };
1217 return OK;
1218 } else if (onOrOff == AudioParameter::valueOff) {
1219 scoConfig.isNrecEnabled = Boolean{ .value = false };
1220 return OK;
1221 }
1222 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1223 AudioParameter::keyBtNrec, onOrOff.c_str());
1224 return BAD_VALUE;
1225 }));
1226 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1227 parameters, String8(AudioParameter::keyBtScoWb),
1228 [&scoConfig](const String8& onOrOff) {
1229 if (onOrOff == AudioParameter::valueOn) {
1230 scoConfig.mode = IBluetooth::ScoConfig::Mode::SCO_WB;
1231 return OK;
1232 } else if (onOrOff == AudioParameter::valueOff) {
1233 scoConfig.mode = IBluetooth::ScoConfig::Mode::SCO;
1234 return OK;
1235 }
1236 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1237 AudioParameter::keyBtScoWb, onOrOff.c_str());
1238 return BAD_VALUE;
1239 }));
1240 if (mBluetooth != nullptr && scoConfig != IBluetooth::ScoConfig{}) {
1241 IBluetooth::ScoConfig newScoConfig;
1242 return statusTFromBinderStatus(mBluetooth->setScoConfig(scoConfig, &newScoConfig));
1243 }
1244 return OK;
1245}
1246
Mikhail Naganove92c34b2023-05-31 14:24:48 -07001247status_t DeviceHalAidl::filterAndUpdateScreenParameters(AudioParameter &parameters) {
Mikhail Naganove92c34b2023-05-31 14:24:48 -07001248 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1249 parameters, String8(AudioParameter::keyScreenState),
1250 [&](const String8& onOrOff) -> status_t {
1251 std::optional<bool> isTurnedOn;
1252 if (onOrOff == AudioParameter::valueOn) {
1253 isTurnedOn = true;
1254 } else if (onOrOff == AudioParameter::valueOff) {
1255 isTurnedOn = false;
1256 }
1257 if (!isTurnedOn.has_value()) {
1258 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1259 AudioParameter::keyScreenState, onOrOff.c_str());
1260 return BAD_VALUE;
1261 }
1262 return statusTFromBinderStatus(
1263 mModule->updateScreenState(isTurnedOn.value()));
1264 }));
1265 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
1266 parameters, String8(AudioParameter::keyScreenRotation),
1267 [&](int rotationDegrees) -> status_t {
1268 IModule::ScreenRotation rotation;
1269 switch (rotationDegrees) {
1270 case 0: rotation = IModule::ScreenRotation::DEG_0; break;
1271 case 90: rotation = IModule::ScreenRotation::DEG_90; break;
1272 case 180: rotation = IModule::ScreenRotation::DEG_180; break;
1273 case 270: rotation = IModule::ScreenRotation::DEG_270; break;
1274 default:
1275 ALOGE("setParameters: parameter key \"%s\" has invalid value %d",
1276 AudioParameter::keyScreenRotation, rotationDegrees);
1277 return BAD_VALUE;
1278 }
1279 return statusTFromBinderStatus(mModule->updateScreenRotation(rotation));
1280 }));
1281 return OK;
1282}
1283
Mikhail Naganovb9a81312023-07-18 13:55:34 -07001284status_t DeviceHalAidl::filterAndUpdateTelephonyParameters(AudioParameter &parameters) {
Mikhail Naganovb9a81312023-07-18 13:55:34 -07001285 using TtyMode = ITelephony::TelecomConfig::TtyMode;
1286 ITelephony::TelecomConfig telConfig;
1287 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1288 parameters, String8(AudioParameter::keyTtyMode),
1289 [&telConfig](const String8& mode) {
1290 if (mode == AudioParameter::valueTtyModeOff) {
1291 telConfig.ttyMode = TtyMode::OFF;
1292 return OK;
1293 } else if (mode == AudioParameter::valueTtyModeFull) {
1294 telConfig.ttyMode = TtyMode::FULL;
1295 return OK;
1296 } else if (mode == AudioParameter::valueTtyModeHco) {
1297 telConfig.ttyMode = TtyMode::HCO;
1298 return OK;
1299 } else if (mode == AudioParameter::valueTtyModeVco) {
1300 telConfig.ttyMode = TtyMode::VCO;
1301 return OK;
1302 }
1303 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1304 AudioParameter::keyTtyMode, mode.c_str());
1305 return BAD_VALUE;
1306 }));
1307 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1308 parameters, String8(AudioParameter::keyHacSetting),
1309 [&telConfig](const String8& onOrOff) {
1310 if (onOrOff == AudioParameter::valueHacOn) {
1311 telConfig.isHacEnabled = Boolean{ .value = true };
1312 return OK;
1313 } else if (onOrOff == AudioParameter::valueHacOff) {
1314 telConfig.isHacEnabled = Boolean{ .value = false };
1315 return OK;
1316 }
1317 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1318 AudioParameter::keyHacSetting, onOrOff.c_str());
1319 return BAD_VALUE;
1320 }));
1321 if (mTelephony != nullptr && telConfig != ITelephony::TelecomConfig{}) {
1322 ITelephony::TelecomConfig newTelConfig;
1323 return statusTFromBinderStatus(
1324 mTelephony->setTelecomConfig(telConfig, &newTelConfig));
1325 }
1326 return OK;
1327}
1328
Mikhail Naganovdfd594e2023-02-08 16:59:41 -08001329void DeviceHalAidl::clearCallbacks(void* cookie) {
1330 std::lock_guard l(mLock);
1331 mCallbacks.erase(cookie);
1332}
1333
1334sp<StreamOutHalInterfaceCallback> DeviceHalAidl::getStreamOutCallback(void* cookie) {
1335 return getCallbackImpl(cookie, &Callbacks::out);
1336}
1337
1338void DeviceHalAidl::setStreamOutCallback(
1339 void* cookie, const sp<StreamOutHalInterfaceCallback>& cb) {
1340 setCallbackImpl(cookie, &Callbacks::out, cb);
1341}
1342
1343sp<StreamOutHalInterfaceEventCallback> DeviceHalAidl::getStreamOutEventCallback(
1344 void* cookie) {
1345 return getCallbackImpl(cookie, &Callbacks::event);
1346}
1347
1348void DeviceHalAidl::setStreamOutEventCallback(
1349 void* cookie, const sp<StreamOutHalInterfaceEventCallback>& cb) {
1350 setCallbackImpl(cookie, &Callbacks::event, cb);
1351}
1352
1353sp<StreamOutHalInterfaceLatencyModeCallback> DeviceHalAidl::getStreamOutLatencyModeCallback(
1354 void* cookie) {
1355 return getCallbackImpl(cookie, &Callbacks::latency);
1356}
1357
1358void DeviceHalAidl::setStreamOutLatencyModeCallback(
1359 void* cookie, const sp<StreamOutHalInterfaceLatencyModeCallback>& cb) {
1360 setCallbackImpl(cookie, &Callbacks::latency, cb);
1361}
1362
1363template<class C>
1364sp<C> DeviceHalAidl::getCallbackImpl(void* cookie, wp<C> DeviceHalAidl::Callbacks::* field) {
1365 std::lock_guard l(mLock);
1366 if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
1367 return ((it->second).*field).promote();
1368 }
1369 return nullptr;
1370}
1371template<class C>
1372void DeviceHalAidl::setCallbackImpl(
1373 void* cookie, wp<C> DeviceHalAidl::Callbacks::* field, const sp<C>& cb) {
1374 std::lock_guard l(mLock);
1375 if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
1376 (it->second).*field = cb;
1377 }
1378}
1379
Mikhail Naganov31d46652023-01-10 18:29:25 +00001380} // namespace android