blob: 8285c17d8ba5a4c0ee719c6cd3fdab09a3758e76 [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>
Haofan Wangbf44e092024-07-07 15:29:38 -070027#include <media/AidlConversionNdk.h>
Mikhail Naganov25bc9a22023-04-21 18:48:16 -070028#include <media/AidlConversionNdkCpp.h>
Mikhail Naganovfab697c2023-01-11 19:33:13 +000029#include <media/AidlConversionUtil.h>
Mikhail Naganov31d46652023-01-10 18:29:25 +000030#include <mediautils/TimeCheck.h>
Mikhail Naganovae9063d2023-11-07 16:43:51 -080031#include <system/audio.h>
Mikhail Naganov89a9f742023-01-30 12:33:18 -080032#include <Utils.h>
Mikhail Naganov31d46652023-01-10 18:29:25 +000033#include <utils/Log.h>
Shunkai Yao51202502022-12-12 06:11:46 +000034
Mikhail Naganov31d46652023-01-10 18:29:25 +000035#include "DeviceHalAidl.h"
Mikhail Naganova82a69d2023-06-14 16:31:32 -070036#include "EffectHalAidl.h"
Mikhail Naganov31d46652023-01-10 18:29:25 +000037#include "StreamHalAidl.h"
38
Mikhail Naganovfab697c2023-01-11 19:33:13 +000039using aidl::android::aidl_utils::statusTFromBinderStatus;
Mikhail Naganovccc82112023-04-27 18:14:15 -070040using aidl::android::media::audio::common::Boolean;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -080041using aidl::android::media::audio::common::AudioConfig;
42using aidl::android::media::audio::common::AudioDevice;
Mikhail Naganov89a9f742023-01-30 12:33:18 -080043using aidl::android::media::audio::common::AudioDeviceType;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -080044using aidl::android::media::audio::common::AudioIoFlags;
Mikhail Naganovdfd594e2023-02-08 16:59:41 -080045using aidl::android::media::audio::common::AudioLatencyMode;
David Li9cf5e622023-03-21 00:51:10 +080046using aidl::android::media::audio::common::AudioMMapPolicy;
47using aidl::android::media::audio::common::AudioMMapPolicyInfo;
48using aidl::android::media::audio::common::AudioMMapPolicyType;
Mikhail Naganovfab697c2023-01-11 19:33:13 +000049using aidl::android::media::audio::common::AudioMode;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -080050using aidl::android::media::audio::common::AudioOutputFlags;
51using aidl::android::media::audio::common::AudioPort;
52using aidl::android::media::audio::common::AudioPortConfig;
David Li9cf5e622023-03-21 00:51:10 +080053using aidl::android::media::audio::common::AudioPortExt;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -080054using aidl::android::media::audio::common::AudioSource;
Mikhail Naganovfab697c2023-01-11 19:33:13 +000055using aidl::android::media::audio::common::Float;
David Li9cf5e622023-03-21 00:51:10 +080056using aidl::android::media::audio::common::Int;
57using aidl::android::media::audio::common::MicrophoneDynamicInfo;
58using aidl::android::media::audio::common::MicrophoneInfo;
Mikhail Naganove7a26ad2023-05-25 17:36:48 -070059using aidl::android::media::audio::IHalAdapterVendorExtension;
Mikhail Naganov6352e822023-03-09 18:22:36 -080060using aidl::android::hardware::audio::common::getFrameSizeInBytes;
61using aidl::android::hardware::audio::common::isBitPositionFlagSet;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -080062using aidl::android::hardware::audio::common::RecordTrackMetadata;
Haofan Wangbf44e092024-07-07 15:29:38 -070063using aidl::android::hardware::audio::common::PlaybackTrackMetadata;
64using aidl::android::hardware::audio::common::SourceMetadata;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -070065using aidl::android::hardware::audio::core::sounddose::ISoundDose;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -080066using aidl::android::hardware::audio::core::AudioPatch;
Mikhail Naganov289468a2023-03-29 10:06:15 -070067using aidl::android::hardware::audio::core::AudioRoute;
Mikhail Naganovccc82112023-04-27 18:14:15 -070068using aidl::android::hardware::audio::core::IBluetooth;
69using aidl::android::hardware::audio::core::IBluetoothA2dp;
70using aidl::android::hardware::audio::core::IBluetoothLe;
Mikhail Naganovfab697c2023-01-11 19:33:13 +000071using aidl::android::hardware::audio::core::IModule;
72using aidl::android::hardware::audio::core::ITelephony;
Mikhail Naganove93a0862023-03-15 17:06:59 -070073using aidl::android::hardware::audio::core::ModuleDebug;
Mikhail Naganove7a26ad2023-05-25 17:36:48 -070074using aidl::android::hardware::audio::core::VendorParameter;
Mikhail Naganov31d46652023-01-10 18:29:25 +000075
76namespace android {
77
Mikhail Naganov5b1eed12023-01-25 11:29:11 -080078namespace {
79
Mikhail Naganovf83b9742023-04-24 13:06:04 -070080// Note: these converters are for types defined in different AIDL files. Although these
81// AIDL files are copies of each other, however formally these are different types
82// thus we don't use a conversion via a parcelable.
83ConversionResult<media::AudioRoute> ndk2cpp_AudioRoute(const AudioRoute& ndk) {
84 media::AudioRoute cpp;
85 cpp.sourcePortIds.insert(
86 cpp.sourcePortIds.end(), ndk.sourcePortIds.begin(), ndk.sourcePortIds.end());
87 cpp.sinkPortId = ndk.sinkPortId;
88 cpp.isExclusive = ndk.isExclusive;
David Li9cf5e622023-03-21 00:51:10 +080089 return cpp;
90}
91
Mikhail Naganov1fba38c2023-05-03 17:45:36 -070092template<typename T>
93std::shared_ptr<T> retrieveSubInterface(const std::shared_ptr<IModule>& module,
94 ::ndk::ScopedAStatus (IModule::*getT)(std::shared_ptr<T>*)) {
95 if (module != nullptr) {
96 std::shared_ptr<T> instance;
97 if (auto status = (module.get()->*getT)(&instance); status.isOk()) {
98 return instance;
99 }
100 }
101 return nullptr;
102}
103
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800104} // namespace
105
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700106DeviceHalAidl::DeviceHalAidl(const std::string& instance, const std::shared_ptr<IModule>& module,
107 const std::shared_ptr<IHalAdapterVendorExtension>& vext)
Mikhail Naganov1fba38c2023-05-03 17:45:36 -0700108 : ConversionHelperAidl("DeviceHalAidl"),
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700109 mInstance(instance), mModule(module), mVendorExt(vext),
Mikhail Naganovccc82112023-04-27 18:14:15 -0700110 mTelephony(retrieveSubInterface<ITelephony>(module, &IModule::getTelephony)),
111 mBluetooth(retrieveSubInterface<IBluetooth>(module, &IModule::getBluetooth)),
112 mBluetoothA2dp(retrieveSubInterface<IBluetoothA2dp>(module, &IModule::getBluetoothA2dp)),
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700113 mBluetoothLe(retrieveSubInterface<IBluetoothLe>(module, &IModule::getBluetoothLe)),
114 mSoundDose(retrieveSubInterface<ISoundDose>(module, &IModule::getSoundDose)),
115 mMapper(instance, module), mMapperAccessor(mMapper, mLock) {
Mikhail Naganov1fba38c2023-05-03 17:45:36 -0700116}
117
Mikhail Naganovf83b9742023-04-24 13:06:04 -0700118status_t DeviceHalAidl::getAudioPorts(std::vector<media::audio::common::AudioPort> *ports) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700119 std::lock_guard l(mLock);
120 return mMapper.getAudioPorts(ports, ndk2cpp_AudioPort);
Mikhail Naganovf83b9742023-04-24 13:06:04 -0700121}
122
123status_t DeviceHalAidl::getAudioRoutes(std::vector<media::AudioRoute> *routes) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700124 std::lock_guard l(mLock);
125 return mMapper.getAudioRoutes(routes, ndk2cpp_AudioRoute);
Mikhail Naganovf83b9742023-04-24 13:06:04 -0700126}
127
Mikhail Naganov1fba38c2023-05-03 17:45:36 -0700128status_t DeviceHalAidl::getSupportedModes(std::vector<media::audio::common::AudioMode> *modes) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700129 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov1fba38c2023-05-03 17:45:36 -0700130 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700131 if (mModule == nullptr) return NO_INIT;
132 if (mTelephony == nullptr) return INVALID_OPERATION;
Mikhail Naganov1fba38c2023-05-03 17:45:36 -0700133 if (modes == nullptr) {
134 return BAD_VALUE;
135 }
Mikhail Naganov1fba38c2023-05-03 17:45:36 -0700136 std::vector<AudioMode> aidlModes;
137 RETURN_STATUS_IF_ERROR(
138 statusTFromBinderStatus(mTelephony->getSupportedAudioModes(&aidlModes)));
139 *modes = VALUE_OR_RETURN_STATUS(
140 ::aidl::android::convertContainer<std::vector<media::audio::common::AudioMode>>(
141 aidlModes, ndk2cpp_AudioMode));
142 return OK;
143}
144
Mikhail Naganov31d46652023-01-10 18:29:25 +0000145status_t DeviceHalAidl::getSupportedDevices(uint32_t*) {
146 // Obsolete.
147 return INVALID_OPERATION;
Shunkai Yao51202502022-12-12 06:11:46 +0000148}
149
150status_t DeviceHalAidl::initCheck() {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700151 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800152 TIME_CHECK();
Mikhail Naganov31d46652023-01-10 18:29:25 +0000153 if (mModule == nullptr) return NO_INIT;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700154 std::lock_guard l(mLock);
155 return mMapper.initialize();
Shunkai Yao51202502022-12-12 06:11:46 +0000156}
157
158status_t DeviceHalAidl::setVoiceVolume(float volume) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700159 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000160 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700161 if (mModule == nullptr) return NO_INIT;
Mikhail Naganov1fba38c2023-05-03 17:45:36 -0700162 if (mTelephony == nullptr) return INVALID_OPERATION;
163 ITelephony::TelecomConfig inConfig{ .voiceVolume = Float{volume} }, outConfig;
164 RETURN_STATUS_IF_ERROR(
165 statusTFromBinderStatus(mTelephony->setTelecomConfig(inConfig, &outConfig)));
166 ALOGW_IF(outConfig.voiceVolume.has_value() && volume != outConfig.voiceVolume.value().value,
167 "%s: the resulting voice volume %f is not the same as requested %f",
168 __func__, outConfig.voiceVolume.value().value, volume);
169 return OK;
Shunkai Yao51202502022-12-12 06:11:46 +0000170}
171
172status_t DeviceHalAidl::setMasterVolume(float volume) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700173 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000174 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700175 if (mModule == nullptr) return NO_INIT;
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000176 return statusTFromBinderStatus(mModule->setMasterVolume(volume));
Shunkai Yao51202502022-12-12 06:11:46 +0000177}
178
179status_t DeviceHalAidl::getMasterVolume(float *volume) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700180 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000181 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700182 if (mModule == nullptr) return NO_INIT;
183 if (volume == nullptr) {
184 return BAD_VALUE;
185 }
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000186 return statusTFromBinderStatus(mModule->getMasterVolume(volume));
Shunkai Yao51202502022-12-12 06:11:46 +0000187}
188
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000189status_t DeviceHalAidl::setMode(audio_mode_t mode) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700190 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000191 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700192 if (mModule == nullptr) return NO_INIT;
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000193 AudioMode audioMode = VALUE_OR_FATAL(::aidl::android::legacy2aidl_audio_mode_t_AudioMode(mode));
Mikhail Naganov1fba38c2023-05-03 17:45:36 -0700194 if (mTelephony != nullptr) {
195 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mTelephony->switchAudioMode(audioMode)));
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000196 }
197 return statusTFromBinderStatus(mModule->updateAudioMode(audioMode));
Shunkai Yao51202502022-12-12 06:11:46 +0000198}
199
200status_t DeviceHalAidl::setMicMute(bool state) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700201 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000202 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700203 if (mModule == nullptr) return NO_INIT;
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000204 return statusTFromBinderStatus(mModule->setMicMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000205}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000206
Shunkai Yao51202502022-12-12 06:11:46 +0000207status_t DeviceHalAidl::getMicMute(bool *state) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700208 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000209 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700210 if (mModule == nullptr) return NO_INIT;
211 if (state == nullptr) {
212 return BAD_VALUE;
213 }
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000214 return statusTFromBinderStatus(mModule->getMicMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000215}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000216
Shunkai Yao51202502022-12-12 06:11:46 +0000217status_t DeviceHalAidl::setMasterMute(bool state) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700218 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000219 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700220 if (mModule == nullptr) return NO_INIT;
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000221 return statusTFromBinderStatus(mModule->setMasterMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000222}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000223
Shunkai Yao51202502022-12-12 06:11:46 +0000224status_t DeviceHalAidl::getMasterMute(bool *state) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700225 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000226 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700227 if (mModule == nullptr) return NO_INIT;
228 if (state == nullptr) {
229 return BAD_VALUE;
230 }
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000231 return statusTFromBinderStatus(mModule->getMasterMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000232}
233
Mikhail Naganovccc82112023-04-27 18:14:15 -0700234status_t DeviceHalAidl::setParameters(const String8& kvPairs) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700235 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
236 TIME_CHECK();
237 if (mModule == nullptr) return NO_INIT;
Mikhail Naganovccc82112023-04-27 18:14:15 -0700238 AudioParameter parameters(kvPairs);
239 ALOGD("%s: parameters: \"%s\"", __func__, parameters.toString().c_str());
240
241 if (status_t status = filterAndUpdateBtA2dpParameters(parameters); status != OK) {
242 ALOGW("%s: filtering or updating BT A2DP parameters failed: %d", __func__, status);
243 }
244 if (status_t status = filterAndUpdateBtHfpParameters(parameters); status != OK) {
245 ALOGW("%s: filtering or updating BT HFP parameters failed: %d", __func__, status);
246 }
247 if (status_t status = filterAndUpdateBtLeParameters(parameters); status != OK) {
248 ALOGW("%s: filtering or updating BT LE parameters failed: %d", __func__, status);
249 }
250 if (status_t status = filterAndUpdateBtScoParameters(parameters); status != OK) {
251 ALOGW("%s: filtering or updating BT SCO parameters failed: %d", __func__, status);
252 }
Mikhail Naganove92c34b2023-05-31 14:24:48 -0700253 if (status_t status = filterAndUpdateScreenParameters(parameters); status != OK) {
254 ALOGW("%s: filtering or updating screen parameters failed: %d", __func__, status);
255 }
Mikhail Naganovb9a81312023-07-18 13:55:34 -0700256 if (status_t status = filterAndUpdateTelephonyParameters(parameters); status != OK) {
257 ALOGW("%s: filtering or updating telephony parameters failed: %d", __func__, status);
258 }
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700259 return parseAndSetVendorParameters(mVendorExt, mModule, parameters);
Shunkai Yao51202502022-12-12 06:11:46 +0000260}
261
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700262status_t DeviceHalAidl::getParameters(const String8& keys, String8 *values) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700263 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000264 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700265 if (mModule == nullptr) return NO_INIT;
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700266 if (values == nullptr) {
267 return BAD_VALUE;
268 }
269 AudioParameter parameterKeys(keys), result;
270 if (status_t status = filterAndRetrieveBtA2dpParameters(parameterKeys, &result); status != OK) {
271 ALOGW("%s: filtering or retrieving BT A2DP parameters failed: %d", __func__, status);
272 }
Eric Laurent7e3c0832023-11-30 15:04:50 +0100273 if (status_t status = filterAndRetrieveBtLeParameters(parameterKeys, &result); status != OK) {
274 ALOGW("%s: filtering or retrieving BT LE parameters failed: %d", __func__, status);
275 }
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700276 *values = result.toString();
277 return parseAndGetVendorParameters(mVendorExt, mModule, parameterKeys, values);
Shunkai Yao51202502022-12-12 06:11:46 +0000278}
279
Mikhail Naganovd5b643f2024-02-15 11:51:26 -0800280status_t DeviceHalAidl::getInputBufferSize(struct audio_config* config, size_t* size) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800281 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800282 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700283 if (mModule == nullptr) return NO_INIT;
284 if (config == nullptr || size == nullptr) {
285 return BAD_VALUE;
286 }
Mikhail Naganovd5b643f2024-02-15 11:51:26 -0800287 constexpr bool isInput = true;
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800288 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
Mikhail Naganovd5b643f2024-02-15 11:51:26 -0800289 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, isInput));
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800290 AudioDevice aidlDevice;
291 aidlDevice.type.type = AudioDeviceType::IN_DEFAULT;
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800292 AudioSource aidlSource = AudioSource::DEFAULT;
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800293 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::input>(0);
294 AudioPortConfig mixPortConfig;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700295 Hal2AidlMapper::Cleanups cleanups(mMapperAccessor);
Mikhail Naganove93a0862023-03-15 17:06:59 -0700296 AudioPatch aidlPatch;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700297 {
298 std::lock_guard l(mLock);
299 RETURN_STATUS_IF_ERROR(mMapper.prepareToOpenStream(
300 0 /*handle*/, aidlDevice, aidlFlags, aidlSource,
301 &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
302 }
Mikhail Naganovd5b643f2024-02-15 11:51:26 -0800303 *config = VALUE_OR_RETURN_STATUS(
304 ::aidl::android::aidl2legacy_AudioConfig_audio_config_t(aidlConfig, isInput));
305 if (mixPortConfig.id == 0) return BAD_VALUE; // HAL suggests a different config.
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800306 *size = aidlConfig.frameCount *
307 getFrameSizeInBytes(aidlConfig.base.format, aidlConfig.base.channelMask);
308 // Do not disarm cleanups to release temporary port configs.
309 return OK;
310}
311
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800312namespace {
313
314class StreamCallbackBase {
315 protected:
316 explicit StreamCallbackBase(const sp<CallbackBroker>& broker) : mBroker(broker) {}
317 public:
318 void* getCookie() const { return mCookie; }
319 void setCookie(void* cookie) { mCookie = cookie; }
320 sp<CallbackBroker> getBroker() const {
321 if (void* cookie = mCookie; cookie != nullptr) return mBroker.promote();
322 return nullptr;
323 }
324 private:
325 const wp<CallbackBroker> mBroker;
326 std::atomic<void*> mCookie;
327};
328
329template<class C>
330class StreamCallbackBaseHelper {
331 protected:
332 explicit StreamCallbackBaseHelper(const StreamCallbackBase& base) : mBase(base) {}
333 sp<C> getCb(const sp<CallbackBroker>& broker, void* cookie);
334 using CbRef = const sp<C>&;
335 ndk::ScopedAStatus runCb(const std::function<void(CbRef cb)>& f) {
336 if (auto cb = getCb(mBase.getBroker(), mBase.getCookie()); cb != nullptr) f(cb);
337 return ndk::ScopedAStatus::ok();
338 }
339 private:
340 const StreamCallbackBase& mBase;
341};
342
343template<>
344sp<StreamOutHalInterfaceCallback> StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>::getCb(
345 const sp<CallbackBroker>& broker, void* cookie) {
346 if (broker != nullptr) return broker->getStreamOutCallback(cookie);
347 return nullptr;
348}
349
350template<>
351sp<StreamOutHalInterfaceEventCallback>
352StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>::getCb(
353 const sp<CallbackBroker>& broker, void* cookie) {
354 if (broker != nullptr) return broker->getStreamOutEventCallback(cookie);
355 return nullptr;
356}
357
358template<>
359sp<StreamOutHalInterfaceLatencyModeCallback>
360StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>::getCb(
361 const sp<CallbackBroker>& broker, void* cookie) {
362 if (broker != nullptr) return broker->getStreamOutLatencyModeCallback(cookie);
363 return nullptr;
364}
365
366/*
367Note on the callback ownership.
368
369In the Binder ownership model, the server implementation is kept alive
370as long as there is any client (proxy object) alive. This is done by
371incrementing the refcount of the server-side object by the Binder framework.
372When it detects that the last client is gone, it decrements the refcount back.
373
374Thus, it is not needed to keep any references to StreamCallback on our
375side (after we have sent an instance to the client), because we are
376the server-side. The callback object will be kept alive as long as the HAL server
377holds a strong ref to IStreamCallback proxy.
378*/
379
380class OutputStreamCallbackAidl : public StreamCallbackBase,
381 public StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>,
382 public ::aidl::android::hardware::audio::core::BnStreamCallback {
383 public:
384 explicit OutputStreamCallbackAidl(const sp<CallbackBroker>& broker)
385 : StreamCallbackBase(broker),
386 StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>(
387 *static_cast<StreamCallbackBase*>(this)) {}
388 ndk::ScopedAStatus onTransferReady() override {
389 return runCb([](CbRef cb) { cb->onWriteReady(); });
390 }
391 ndk::ScopedAStatus onError() override {
Mikhail Naganovf548cd32024-05-29 17:06:46 +0000392 return runCb([](CbRef cb) { cb->onError(true /*isHardError*/); });
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800393 }
394 ndk::ScopedAStatus onDrainReady() override {
395 return runCb([](CbRef cb) { cb->onDrainReady(); });
396 }
397};
398
399class OutputStreamEventCallbackAidl :
400 public StreamCallbackBase,
401 public StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>,
402 public StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>,
403 public ::aidl::android::hardware::audio::core::BnStreamOutEventCallback {
404 public:
405 explicit OutputStreamEventCallbackAidl(const sp<CallbackBroker>& broker)
406 : StreamCallbackBase(broker),
407 StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>(
408 *static_cast<StreamCallbackBase*>(this)),
409 StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>(
410 *static_cast<StreamCallbackBase*>(this)) {}
Ryan Prichard78c5e452024-02-08 16:16:57 -0800411 ndk::ScopedAStatus onCodecFormatChanged(const std::vector<uint8_t>& halMetadata) override {
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800412 return StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>::runCb(
413 [&halMetadata](auto cb) { cb->onCodecFormatChanged(halMetadata); });
414 }
415 ndk::ScopedAStatus onRecommendedLatencyModeChanged(
416 const std::vector<AudioLatencyMode>& in_modes) override {
417 auto halModes = VALUE_OR_FATAL(
418 ::aidl::android::convertContainer<std::vector<audio_latency_mode_t>>(
419 in_modes,
420 ::aidl::android::aidl2legacy_AudioLatencyMode_audio_latency_mode_t));
421 return StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>::runCb(
422 [&halModes](auto cb) { cb->onRecommendedLatencyModeChanged(halModes); });
423 }
424};
425
426} // namespace
427
Mikhail Naganov31d46652023-01-10 18:29:25 +0000428status_t DeviceHalAidl::openOutputStream(
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800429 audio_io_handle_t handle, audio_devices_t devices,
430 audio_output_flags_t flags, struct audio_config* config,
431 const char* address,
Haofan Wangbf44e092024-07-07 15:29:38 -0700432 sp<StreamOutHalInterface>* outStream,
433 const std::vector<playback_track_metadata_v7_t>& sourceMetadata) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800434 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700435 TIME_CHECK();
436 if (mModule == nullptr) return NO_INIT;
437 if (outStream == nullptr || config == nullptr) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000438 return BAD_VALUE;
439 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700440 constexpr bool isInput = false;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800441 int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
442 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(handle));
443 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700444 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, isInput));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800445 AudioDevice aidlDevice = VALUE_OR_RETURN_STATUS(
446 ::aidl::android::legacy2aidl_audio_device_AudioDevice(devices, address));
447 int32_t aidlOutputFlags = VALUE_OR_RETURN_STATUS(
448 ::aidl::android::legacy2aidl_audio_output_flags_t_int32_t_mask(flags));
Haofan Wangbf44e092024-07-07 15:29:38 -0700449 SourceMetadata aidlMetadata = VALUE_OR_RETURN_STATUS(
450 ::aidl::android::legacy2aidl_SourceMetadata(sourceMetadata));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800451 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::output>(aidlOutputFlags);
452 AudioPortConfig mixPortConfig;
Mikhail Naganove93a0862023-03-15 17:06:59 -0700453 AudioPatch aidlPatch;
Haofan Wangbf44e092024-07-07 15:29:38 -0700454
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700455 Hal2AidlMapper::Cleanups cleanups(mMapperAccessor);
456 {
457 std::lock_guard l(mLock);
458 RETURN_STATUS_IF_ERROR(mMapper.prepareToOpenStream(aidlHandle, aidlDevice, aidlFlags,
459 AudioSource::SYS_RESERVED_INVALID /*only needed for input*/,
460 &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
461 }
462 *config = VALUE_OR_RETURN_STATUS(
463 ::aidl::android::aidl2legacy_AudioConfig_audio_config_t(aidlConfig, isInput));
Mikhail Naganovca92a5c2023-12-07 14:00:48 -0800464 if (mixPortConfig.id == 0) return BAD_VALUE; // HAL suggests a different config.
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800465 ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamArguments args;
466 args.portConfigId = mixPortConfig.id;
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800467 const bool isOffload = isBitPositionFlagSet(
468 aidlOutputFlags, AudioOutputFlags::COMPRESS_OFFLOAD);
Kuowei Li3b9a69d2024-06-07 17:54:32 +0800469 const bool isHwAvSync = isBitPositionFlagSet(
470 aidlOutputFlags, AudioOutputFlags::HW_AV_SYNC);
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800471 std::shared_ptr<OutputStreamCallbackAidl> streamCb;
472 if (isOffload) {
473 streamCb = ndk::SharedRefBase::make<OutputStreamCallbackAidl>(this);
474 }
475 auto eventCb = ndk::SharedRefBase::make<OutputStreamEventCallbackAidl>(this);
Kuowei Li3b9a69d2024-06-07 17:54:32 +0800476 if (isOffload || isHwAvSync) {
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800477 args.offloadInfo = aidlConfig.offloadInfo;
Kuowei Li3b9a69d2024-06-07 17:54:32 +0800478 }
479 if (isOffload) {
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800480 args.callback = streamCb;
481 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800482 args.bufferSizeFrames = aidlConfig.frameCount;
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800483 args.eventCallback = eventCb;
Haofan Wangbf44e092024-07-07 15:29:38 -0700484 args.sourceMetadata = aidlMetadata;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800485 ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamReturn ret;
486 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openOutputStream(args, &ret)));
Mikhail Naganov712d71b2023-02-23 17:57:16 -0800487 StreamContextAidl context(ret.desc, isOffload);
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800488 if (!context.isValid()) {
489 ALOGE("%s: Failed to created a valid stream context from the descriptor: %s",
490 __func__, ret.desc.toString().c_str());
491 return NO_INIT;
492 }
Mikhail Naganov23224a12024-03-28 02:15:21 +0000493 auto stream = sp<StreamOutHalAidl>::make(*config, std::move(context), aidlPatch.latenciesMs[0],
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700494 std::move(ret.stream), mVendorExt, this /*callbackBroker*/);
Mikhail Naganov23224a12024-03-28 02:15:21 +0000495 *outStream = stream;
496 /* StreamOutHalInterface* */ void* cbCookie = (*outStream).get();
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800497 {
Mikhail Naganov22578412024-08-16 16:50:34 -0700498 std::lock_guard l(mCallbacksLock);
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800499 mCallbacks.emplace(cbCookie, Callbacks{});
Mikhail Naganov22578412024-08-16 16:50:34 -0700500 }
501 {
502 std::lock_guard l(mLock);
Mikhail Naganov78f7f9a2023-11-16 15:49:23 -0800503 mMapper.addStream(*outStream, mixPortConfig.id, aidlPatch.id);
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800504 }
Mikhail Naganov23224a12024-03-28 02:15:21 +0000505 if (streamCb) {
506 streamCb->setCookie(cbCookie);
507 // Although StreamOutHalAidl implements StreamOutHalInterfaceCallback,
508 // we always go via the CallbackBroker for consistency.
509 setStreamOutCallback(cbCookie, stream);
510 }
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800511 eventCb->setCookie(cbCookie);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800512 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000513 return OK;
514}
515
Mikhail Naganov31d46652023-01-10 18:29:25 +0000516status_t DeviceHalAidl::openInputStream(
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800517 audio_io_handle_t handle, audio_devices_t devices,
518 struct audio_config* config, audio_input_flags_t flags,
519 const char* address, audio_source_t source,
520 audio_devices_t outputDevice, const char* outputDeviceAddress,
Mikhail Naganov31d46652023-01-10 18:29:25 +0000521 sp<StreamInHalInterface>* inStream) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800522 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700523 TIME_CHECK();
524 if (mModule == nullptr) return NO_INIT;
525 if (inStream == nullptr || config == nullptr) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000526 return BAD_VALUE;
527 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700528 constexpr bool isInput = true;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800529 int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
530 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(handle));
531 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700532 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, isInput));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800533 AudioDevice aidlDevice = VALUE_OR_RETURN_STATUS(
534 ::aidl::android::legacy2aidl_audio_device_AudioDevice(devices, address));
535 int32_t aidlInputFlags = VALUE_OR_RETURN_STATUS(
536 ::aidl::android::legacy2aidl_audio_input_flags_t_int32_t_mask(flags));
537 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::input>(aidlInputFlags);
538 AudioSource aidlSource = VALUE_OR_RETURN_STATUS(
539 ::aidl::android::legacy2aidl_audio_source_t_AudioSource(source));
540 AudioPortConfig mixPortConfig;
Mikhail Naganove93a0862023-03-15 17:06:59 -0700541 AudioPatch aidlPatch;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700542 Hal2AidlMapper::Cleanups cleanups(mMapperAccessor);
543 {
544 std::lock_guard l(mLock);
545 RETURN_STATUS_IF_ERROR(mMapper.prepareToOpenStream(
546 aidlHandle, aidlDevice, aidlFlags, aidlSource,
547 &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
548 }
549 *config = VALUE_OR_RETURN_STATUS(
550 ::aidl::android::aidl2legacy_AudioConfig_audio_config_t(aidlConfig, isInput));
Mikhail Naganovca92a5c2023-12-07 14:00:48 -0800551 if (mixPortConfig.id == 0) return BAD_VALUE; // HAL suggests a different config.
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800552 ::aidl::android::hardware::audio::core::IModule::OpenInputStreamArguments args;
553 args.portConfigId = mixPortConfig.id;
554 RecordTrackMetadata aidlTrackMetadata{
555 .source = aidlSource, .gain = 1, .channelMask = aidlConfig.base.channelMask };
556 if (outputDevice != AUDIO_DEVICE_NONE) {
557 aidlTrackMetadata.destinationDevice = VALUE_OR_RETURN_STATUS(
558 ::aidl::android::legacy2aidl_audio_device_AudioDevice(
559 outputDevice, outputDeviceAddress));
560 }
561 args.sinkMetadata.tracks.push_back(std::move(aidlTrackMetadata));
562 args.bufferSizeFrames = aidlConfig.frameCount;
563 ::aidl::android::hardware::audio::core::IModule::OpenInputStreamReturn ret;
564 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openInputStream(args, &ret)));
Mikhail Naganov712d71b2023-02-23 17:57:16 -0800565 StreamContextAidl context(ret.desc, false /*isAsynchronous*/);
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800566 if (!context.isValid()) {
567 ALOGE("%s: Failed to created a valid stream context from the descriptor: %s",
568 __func__, ret.desc.toString().c_str());
569 return NO_INIT;
570 }
Mikhail Naganove93a0862023-03-15 17:06:59 -0700571 *inStream = sp<StreamInHalAidl>::make(*config, std::move(context), aidlPatch.latenciesMs[0],
Mikhail Naganove7a26ad2023-05-25 17:36:48 -0700572 std::move(ret.stream), mVendorExt, this /*micInfoProvider*/);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700573 {
574 std::lock_guard l(mLock);
Mikhail Naganov78f7f9a2023-11-16 15:49:23 -0800575 mMapper.addStream(*inStream, mixPortConfig.id, aidlPatch.id);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700576 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800577 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000578 return OK;
579}
580
581status_t DeviceHalAidl::supportsAudioPatches(bool* supportsPatches) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700582 if (supportsPatches == nullptr) {
583 return BAD_VALUE;
584 }
Shunkai Yao51202502022-12-12 06:11:46 +0000585 *supportsPatches = true;
586 return OK;
587}
588
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800589status_t DeviceHalAidl::createAudioPatch(unsigned int num_sources,
590 const struct audio_port_config* sources,
591 unsigned int num_sinks,
592 const struct audio_port_config* sinks,
593 audio_patch_handle_t* patch) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800594 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000595 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700596 if (mModule == nullptr) return NO_INIT;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800597 if (num_sinks > AUDIO_PATCH_PORTS_MAX || num_sources > AUDIO_PATCH_PORTS_MAX ||
598 sources == nullptr || sinks == nullptr || patch == nullptr) {
599 return BAD_VALUE;
600 }
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800601 // When the patch handle (*patch) is AUDIO_PATCH_HANDLE_NONE, it means
602 // the framework wants to create a new patch. The handle has to be generated
603 // by the HAL. Since handles generated this way can only be unique within
604 // a HAL module, the framework generates a globally unique handle, and maps
605 // it on the <HAL module, patch handle> pair.
606 // When the patch handle is set, it meant the framework intends to update
607 // an existing patch.
608 //
609 // This behavior corresponds to HAL module behavior, with the only difference
610 // that the HAL module uses `int32_t` for patch IDs. The following assert ensures
611 // that both the framework and the HAL use the same value for "no ID":
612 static_assert(AUDIO_PATCH_HANDLE_NONE == 0);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800613
614 // Upon conversion, mix port configs contain audio configuration, while
615 // device port configs contain device address. This data is used to find
616 // or create HAL configs.
617 std::vector<AudioPortConfig> aidlSources, aidlSinks;
618 for (unsigned int i = 0; i < num_sources; ++i) {
619 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
620 sources[i].role, sources[i].type)) ==
621 ::aidl::android::AudioPortDirection::INPUT;
622 aidlSources.push_back(VALUE_OR_RETURN_STATUS(
623 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
624 sources[i], isInput, 0)));
625 }
626 for (unsigned int i = 0; i < num_sinks; ++i) {
627 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
628 sinks[i].role, sinks[i].type)) ==
629 ::aidl::android::AudioPortDirection::INPUT;
630 aidlSinks.push_back(VALUE_OR_RETURN_STATUS(
631 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
632 sinks[i], isInput, 0)));
633 }
Mikhail Naganova317a802024-03-15 18:03:10 +0000634 int32_t aidlPatchId = static_cast<int32_t>(*patch);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700635 Hal2AidlMapper::Cleanups cleanups(mMapperAccessor);
636 {
637 std::lock_guard l(mLock);
Mikhail Naganova317a802024-03-15 18:03:10 +0000638 // Check for patches that only exist for the framework, or have different HAL patch ID.
639 if (int32_t aidlHalPatchId = mMapper.findFwkPatch(aidlPatchId); aidlHalPatchId != 0) {
640 if (aidlHalPatchId == aidlPatchId) {
641 // This patch was previously released by the HAL. Thus we need to pass '0'
642 // to the HAL to obtain a new patch.
643 int32_t newAidlPatchId = 0;
644 RETURN_STATUS_IF_ERROR(mMapper.createOrUpdatePatch(
645 aidlSources, aidlSinks, &newAidlPatchId, &cleanups));
646 mMapper.updateFwkPatch(aidlPatchId, newAidlPatchId);
647 } else {
648 RETURN_STATUS_IF_ERROR(mMapper.createOrUpdatePatch(
649 aidlSources, aidlSinks, &aidlHalPatchId, &cleanups));
650 }
651 } else {
652 RETURN_STATUS_IF_ERROR(mMapper.createOrUpdatePatch(
653 aidlSources, aidlSinks, &aidlPatchId, &cleanups));
654 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800655 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700656 *patch = static_cast<audio_patch_handle_t>(aidlPatchId);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800657 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000658 return OK;
659}
660
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800661status_t DeviceHalAidl::releaseAudioPatch(audio_patch_handle_t patch) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800662 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000663 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700664 if (mModule == nullptr) return NO_INIT;
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800665 static_assert(AUDIO_PATCH_HANDLE_NONE == 0);
666 if (patch == AUDIO_PATCH_HANDLE_NONE) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800667 return BAD_VALUE;
668 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700669 std::lock_guard l(mLock);
Mikhail Naganova317a802024-03-15 18:03:10 +0000670 // Check for patches that only exist for the framework, or have different HAL patch ID.
671 int32_t aidlPatchId = static_cast<int32_t>(patch);
672 if (int32_t aidlHalPatchId = mMapper.findFwkPatch(aidlPatchId); aidlHalPatchId != 0) {
673 if (aidlHalPatchId == aidlPatchId) {
674 // This patch was previously released by the HAL, just need to finish its removal.
675 mMapper.eraseFwkPatch(aidlPatchId);
676 return OK;
677 } else {
678 // This patch has a HAL patch ID which is different
679 aidlPatchId = aidlHalPatchId;
680 }
681 }
682 RETURN_STATUS_IF_ERROR(mMapper.releaseAudioPatch(aidlPatchId));
Shunkai Yao51202502022-12-12 06:11:46 +0000683 return OK;
684}
685
Mikhail Naganove93a0862023-03-15 17:06:59 -0700686status_t DeviceHalAidl::getAudioPort(struct audio_port* port) {
Mikhail Naganove93a0862023-03-15 17:06:59 -0700687 if (port == nullptr) {
688 return BAD_VALUE;
689 }
690 audio_port_v7 portV7;
691 audio_populate_audio_port_v7(port, &portV7);
692 RETURN_STATUS_IF_ERROR(getAudioPort(&portV7));
693 return audio_populate_audio_port(&portV7, port) ? OK : BAD_VALUE;
694}
695
696status_t DeviceHalAidl::getAudioPort(struct audio_port_v7 *port) {
697 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
698 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700699 if (mModule == nullptr) return NO_INIT;
Mikhail Naganove93a0862023-03-15 17:06:59 -0700700 if (port == nullptr) {
701 return BAD_VALUE;
702 }
703 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(port->role, port->type)) ==
704 ::aidl::android::AudioPortDirection::INPUT;
705 auto aidlPort = VALUE_OR_RETURN_STATUS(
706 ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
707 if (aidlPort.ext.getTag() != AudioPortExt::device) {
708 ALOGE("%s: provided port is not a device port (module %s): %s",
709 __func__, mInstance.c_str(), aidlPort.toString().c_str());
710 return BAD_VALUE;
711 }
712 const auto& matchDevice = aidlPort.ext.get<AudioPortExt::device>().device;
713 // It seems that we don't have to call HAL since all valid ports have been added either
714 // during initialization, or while handling connection of an external device.
Mikhail Naganove93a0862023-03-15 17:06:59 -0700715 const int32_t fwkId = aidlPort.id;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700716 {
717 std::lock_guard l(mLock);
718 RETURN_STATUS_IF_ERROR(mMapper.getAudioPortCached(matchDevice, &aidlPort));
719 }
Mikhail Naganove93a0862023-03-15 17:06:59 -0700720 aidlPort.id = fwkId;
721 *port = VALUE_OR_RETURN_STATUS(::aidl::android::aidl2legacy_AudioPort_audio_port_v7(
722 aidlPort, isInput));
723 return OK;
724}
725
jiabin12537fc2023-10-12 17:56:08 +0000726status_t DeviceHalAidl::getAudioMixPort(const struct audio_port_v7 *devicePort,
727 struct audio_port_v7 *mixPort) {
728 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700729 TIME_CHECK();
730 if (mModule == nullptr) return NO_INIT;
731 if (devicePort == nullptr || mixPort == nullptr ||
732 devicePort->type != AUDIO_PORT_TYPE_DEVICE || mixPort->type != AUDIO_PORT_TYPE_MIX) {
jiabin12537fc2023-10-12 17:56:08 +0000733 return BAD_VALUE;
734 }
735 const int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
736 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(mixPort->ext.mix.handle));
jiabin12537fc2023-10-12 17:56:08 +0000737 AudioPort port;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700738 {
739 std::lock_guard l(mLock);
740 RETURN_STATUS_IF_ERROR(mMapper.getAudioMixPort(aidlHandle, &port));
jiabin12537fc2023-10-12 17:56:08 +0000741 }
742 const bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
743 mixPort->role, mixPort->type)) == ::aidl::android::AudioPortDirection::INPUT;
744 *mixPort = VALUE_OR_RETURN_STATUS(::aidl::android::aidl2legacy_AudioPort_audio_port_v7(
745 port, isInput));
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700746 return OK;
jiabin12537fc2023-10-12 17:56:08 +0000747}
748
Mikhail Naganove93a0862023-03-15 17:06:59 -0700749status_t DeviceHalAidl::setAudioPortConfig(const struct audio_port_config* config) {
750 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
751 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700752 if (mModule == nullptr) return NO_INIT;
Mikhail Naganove93a0862023-03-15 17:06:59 -0700753 if (config == nullptr) {
754 return BAD_VALUE;
755 }
756 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
757 config->role, config->type)) == ::aidl::android::AudioPortDirection::INPUT;
758 AudioPortConfig requestedPortConfig = VALUE_OR_RETURN_STATUS(
759 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
760 *config, isInput, 0 /*portId*/));
761 AudioPortConfig portConfig;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700762 std::lock_guard l(mLock);
Mikhail Naganovca92a5c2023-12-07 14:00:48 -0800763 return mMapper.setPortConfig(requestedPortConfig, std::set<int32_t>(), &portConfig);
Shunkai Yao51202502022-12-12 06:11:46 +0000764}
765
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800766MicrophoneInfoProvider::Info const* DeviceHalAidl::getMicrophoneInfo() {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700767 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
768 TIME_CHECK();
769 if (!mModule) return {};
770 std::lock_guard l(mLock);
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800771 if (mMicrophones.status == Microphones::Status::UNKNOWN) {
772 TIME_CHECK();
773 std::vector<MicrophoneInfo> aidlInfo;
774 status_t status = statusTFromBinderStatus(mModule->getMicrophones(&aidlInfo));
775 if (status == OK) {
776 mMicrophones.status = Microphones::Status::QUERIED;
777 mMicrophones.info = std::move(aidlInfo);
778 } else if (status == INVALID_OPERATION) {
779 mMicrophones.status = Microphones::Status::NOT_SUPPORTED;
780 } else {
781 ALOGE("%s: Unexpected status from 'IModule.getMicrophones': %d", __func__, status);
782 return {};
783 }
784 }
785 if (mMicrophones.status == Microphones::Status::QUERIED) {
786 return &mMicrophones.info;
787 }
788 return {}; // NOT_SUPPORTED
789}
790
Shunkai Yao51202502022-12-12 06:11:46 +0000791status_t DeviceHalAidl::getMicrophones(
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800792 std::vector<audio_microphone_characteristic_t>* microphones) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700793 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
794 TIME_CHECK();
795 if (mModule == nullptr) return NO_INIT;
796 if (microphones == nullptr) {
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800797 return BAD_VALUE;
798 }
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800799 auto staticInfo = getMicrophoneInfo();
800 if (!staticInfo) return INVALID_OPERATION;
801 std::vector<MicrophoneDynamicInfo> emptyDynamicInfo;
802 emptyDynamicInfo.reserve(staticInfo->size());
803 std::transform(staticInfo->begin(), staticInfo->end(), std::back_inserter(emptyDynamicInfo),
804 [](const auto& info) { return MicrophoneDynamicInfo{ .id = info.id }; });
805 *microphones = VALUE_OR_RETURN_STATUS(
806 ::aidl::android::convertContainers<std::vector<audio_microphone_characteristic_t>>(
807 *staticInfo, emptyDynamicInfo,
808 ::aidl::android::aidl2legacy_MicrophoneInfos_audio_microphone_characteristic_t)
809 );
Shunkai Yao51202502022-12-12 06:11:46 +0000810 return OK;
811}
812
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700813status_t DeviceHalAidl::addDeviceEffect(
814 const struct audio_port_config *device, sp<EffectHalInterface> effect) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700815 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700816 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700817 if (mModule == nullptr) return NO_INIT;
818 if (device == nullptr || effect == nullptr) {
Shunkai Yao51202502022-12-12 06:11:46 +0000819 return BAD_VALUE;
820 }
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700821 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
822 device->role, device->type)) == ::aidl::android::AudioPortDirection::INPUT;
823 auto requestedPortConfig = VALUE_OR_RETURN_STATUS(
824 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
825 *device, isInput, 0));
826 if (requestedPortConfig.ext.getTag() != AudioPortExt::Tag::device) {
827 ALOGE("%s: provided port config is not a device port config: %s",
828 __func__, requestedPortConfig.toString().c_str());
829 return BAD_VALUE;
830 }
831 AudioPortConfig devicePortConfig;
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700832 Hal2AidlMapper::Cleanups cleanups(mMapperAccessor);
833 {
834 std::lock_guard l(mLock);
Mikhail Naganovca92a5c2023-12-07 14:00:48 -0800835 RETURN_STATUS_IF_ERROR(mMapper.setPortConfig(
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700836 requestedPortConfig, {} /*destinationPortIds*/, &devicePortConfig, &cleanups));
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700837 }
838 auto aidlEffect = sp<effect::EffectHalAidl>::cast(effect);
839 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->addDeviceEffect(
840 devicePortConfig.id, aidlEffect->getIEffect())));
841 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000842 return OK;
843}
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700844status_t DeviceHalAidl::removeDeviceEffect(
845 const struct audio_port_config *device, sp<EffectHalInterface> effect) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700846 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700847 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700848 if (mModule == nullptr) return NO_INIT;
849 if (device == nullptr || effect == nullptr) {
Shunkai Yao51202502022-12-12 06:11:46 +0000850 return BAD_VALUE;
851 }
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700852 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
853 device->role, device->type)) == ::aidl::android::AudioPortDirection::INPUT;
854 auto requestedPortConfig = VALUE_OR_RETURN_STATUS(
855 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
856 *device, isInput, 0));
857 if (requestedPortConfig.ext.getTag() != AudioPortExt::Tag::device) {
858 ALOGE("%s: provided port config is not a device port config: %s",
859 __func__, requestedPortConfig.toString().c_str());
860 return BAD_VALUE;
861 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700862 AudioPortConfig devicePortConfig;
863 {
864 std::lock_guard l(mLock);
865 RETURN_STATUS_IF_ERROR(mMapper.findPortConfig(
866 requestedPortConfig.ext.get<AudioPortExt::Tag::device>().device,
867 &devicePortConfig));
Mikhail Naganova82a69d2023-06-14 16:31:32 -0700868 }
869 auto aidlEffect = sp<effect::EffectHalAidl>::cast(effect);
870 return statusTFromBinderStatus(mModule->removeDeviceEffect(
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700871 devicePortConfig.id, aidlEffect->getIEffect()));
Shunkai Yao51202502022-12-12 06:11:46 +0000872}
873
874status_t DeviceHalAidl::getMmapPolicyInfos(
David Li9cf5e622023-03-21 00:51:10 +0800875 media::audio::common::AudioMMapPolicyType policyType,
876 std::vector<media::audio::common::AudioMMapPolicyInfo>* policyInfos) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700877 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000878 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700879 if (mModule == nullptr) return NO_INIT;
Mikhail Naganov25bc9a22023-04-21 18:48:16 -0700880 AudioMMapPolicyType mmapPolicyType = VALUE_OR_RETURN_STATUS(
881 cpp2ndk_AudioMMapPolicyType(policyType));
David Li9cf5e622023-03-21 00:51:10 +0800882
883 std::vector<AudioMMapPolicyInfo> mmapPolicyInfos;
884
885 if (status_t status = statusTFromBinderStatus(
886 mModule->getMmapPolicyInfos(mmapPolicyType, &mmapPolicyInfos)); status != OK) {
887 return status;
888 }
889
890 *policyInfos = VALUE_OR_RETURN_STATUS(
891 convertContainer<std::vector<media::audio::common::AudioMMapPolicyInfo>>(
892 mmapPolicyInfos, ndk2cpp_AudioMMapPolicyInfo));
Shunkai Yao51202502022-12-12 06:11:46 +0000893 return OK;
894}
895
896int32_t DeviceHalAidl::getAAudioMixerBurstCount() {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700897 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000898 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700899 if (mModule == nullptr) return NO_INIT;
David Li9cf5e622023-03-21 00:51:10 +0800900 int32_t mixerBurstCount = 0;
901 if (mModule->getAAudioMixerBurstCount(&mixerBurstCount).isOk()) {
902 return mixerBurstCount;
903 }
904 return 0;
Shunkai Yao51202502022-12-12 06:11:46 +0000905}
906
907int32_t DeviceHalAidl::getAAudioHardwareBurstMinUsec() {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700908 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000909 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700910 if (mModule == nullptr) return NO_INIT;
David Li9cf5e622023-03-21 00:51:10 +0800911 int32_t hardwareBurstMinUsec = 0;
912 if (mModule->getAAudioHardwareBurstMinUsec(&hardwareBurstMinUsec).isOk()) {
913 return hardwareBurstMinUsec;
914 }
915 return 0;
Shunkai Yao51202502022-12-12 06:11:46 +0000916}
917
918error::Result<audio_hw_sync_t> DeviceHalAidl::getHwAvSync() {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700919 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000920 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700921 if (mModule == nullptr) return NO_INIT;
Mikhail Naganov08a62ab2023-03-14 17:11:51 -0700922 int32_t aidlHwAvSync;
923 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->generateHwAvSyncId(&aidlHwAvSync)));
924 return VALUE_OR_RETURN_STATUS(
925 ::aidl::android::aidl2legacy_int32_t_audio_hw_sync_t(aidlHwAvSync));
Shunkai Yao51202502022-12-12 06:11:46 +0000926}
927
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000928status_t DeviceHalAidl::dump(int fd, const Vector<String16>& args) {
929 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700930 if (mModule == nullptr) return NO_INIT;
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000931 return mModule->dump(fd, Args(args).args(), args.size());
David Li9cf5e622023-03-21 00:51:10 +0800932}
Shunkai Yao51202502022-12-12 06:11:46 +0000933
Eric Laurent7af6ee72023-06-29 11:44:54 +0200934status_t DeviceHalAidl::supportsBluetoothVariableLatency(bool* supports) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700935 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000936 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700937 if (mModule == nullptr) return NO_INIT;
Mikhail Naganov3ac95c92023-04-12 13:14:30 -0700938 if (supports == nullptr) {
939 return BAD_VALUE;
940 }
941 return statusTFromBinderStatus(mModule->supportsVariableLatency(supports));
Shunkai Yao51202502022-12-12 06:11:46 +0000942}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000943
Vlad Popa03bd5bc2023-01-17 16:16:51 +0100944status_t DeviceHalAidl::getSoundDoseInterface(const std::string& module,
945 ::ndk::SpAIBinder* soundDoseBinder) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700946 if (soundDoseBinder == nullptr) {
947 return BAD_VALUE;
948 }
Vlad Popa03bd5bc2023-01-17 16:16:51 +0100949 if (mSoundDose == nullptr) {
Mikhail Naganovac9d4e72023-10-23 12:00:09 -0700950 ALOGE("%s failed to retrieve the sound dose interface for module %s",
951 __func__, module.c_str());
952 return BAD_VALUE;
Vlad Popa03bd5bc2023-01-17 16:16:51 +0100953 }
Vlad Popae1f33902023-10-30 19:48:25 -0700954
955 if (mSoundDose == nullptr) {
956 ALOGE("%s failed to return the sound dose interface for module %s: not implemented",
957 __func__,
958 module.c_str());
959 return NO_INIT;
960 }
961
Vlad Popa03bd5bc2023-01-17 16:16:51 +0100962 *soundDoseBinder = mSoundDose->asBinder();
963 ALOGI("%s using audio AIDL HAL sound dose interface", __func__);
Vlad Popa03bd5bc2023-01-17 16:16:51 +0100964 return OK;
965}
jiabin872de702023-04-27 22:04:31 +0000966
967status_t DeviceHalAidl::prepareToDisconnectExternalDevice(const struct audio_port_v7* port) {
jiabin62750c22023-12-21 22:06:07 +0000968 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
969 TIME_CHECK();
970 if (mModule == nullptr) return NO_INIT;
971 if (port == nullptr) {
972 return BAD_VALUE;
973 }
974 const bool isInput = VALUE_OR_RETURN_STATUS(
975 ::aidl::android::portDirection(port->role, port->type)) ==
976 ::aidl::android::AudioPortDirection::INPUT;
977 AudioPort aidlPort = VALUE_OR_RETURN_STATUS(
978 ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
979 if (aidlPort.ext.getTag() != AudioPortExt::device) {
980 ALOGE("%s: provided port is not a device port (module %s): %s",
981 __func__, mInstance.c_str(), aidlPort.toString().c_str());
982 return BAD_VALUE;
983 }
984 status_t status = NO_ERROR;
985 {
986 std::lock_guard l(mLock);
987 status = mMapper.prepareToDisconnectExternalDevice(aidlPort);
988 }
989 if (status == UNKNOWN_TRANSACTION) {
990 // If there is not AIDL API defined for `prepareToDisconnectExternalDevice`.
991 // Call `setConnectedState` instead.
992 RETURN_STATUS_IF_ERROR(setConnectedState(port, false /*connected*/));
993 std::lock_guard l(mLock);
994 mDeviceDisconnectionNotified.insert(port->id);
995 // Return that there was no error as otherwise the disconnection procedure will not be
996 // considered complete for upper layers, and 'setConnectedState' will not be called again
997 return OK;
998 } else {
999 return status;
1000 }
jiabin872de702023-04-27 22:04:31 +00001001}
1002
Mikhail Naganove93a0862023-03-15 17:06:59 -07001003status_t DeviceHalAidl::setConnectedState(const struct audio_port_v7 *port, bool connected) {
Mikhail Naganovae9063d2023-11-07 16:43:51 -08001004 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganove93a0862023-03-15 17:06:59 -07001005 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -07001006 if (mModule == nullptr) return NO_INIT;
Mikhail Naganove93a0862023-03-15 17:06:59 -07001007 if (port == nullptr) {
1008 return BAD_VALUE;
1009 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -07001010 if (!connected) {
1011 std::lock_guard l(mLock);
1012 if (mDeviceDisconnectionNotified.erase(port->id) > 0) {
1013 // For device disconnection, APM will first call `prepareToDisconnectExternalDevice`
jiabin62750c22023-12-21 22:06:07 +00001014 // and then call `setConnectedState`. If `prepareToDisconnectExternalDevice` doesn't
1015 // exit, `setConnectedState` will be called when calling
1016 // `prepareToDisconnectExternalDevice`. Do not call to the HAL if previous call is
1017 // successful. Also remove the cache here to avoid a large cache after a long run.
Mikhail Naganovac9d4e72023-10-23 12:00:09 -07001018 return OK;
1019 }
jiabin872de702023-04-27 22:04:31 +00001020 }
Mikhail Naganove93a0862023-03-15 17:06:59 -07001021 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(port->role, port->type)) ==
1022 ::aidl::android::AudioPortDirection::INPUT;
1023 AudioPort aidlPort = VALUE_OR_RETURN_STATUS(
1024 ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
1025 if (aidlPort.ext.getTag() != AudioPortExt::device) {
1026 ALOGE("%s: provided port is not a device port (module %s): %s",
1027 __func__, mInstance.c_str(), aidlPort.toString().c_str());
1028 return BAD_VALUE;
1029 }
Mikhail Naganovac9d4e72023-10-23 12:00:09 -07001030 std::lock_guard l(mLock);
1031 return mMapper.setDevicePortConnectedState(aidlPort, connected);
Mikhail Naganove93a0862023-03-15 17:06:59 -07001032}
1033
1034status_t DeviceHalAidl::setSimulateDeviceConnections(bool enabled) {
1035 TIME_CHECK();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -07001036 if (mModule == nullptr) return NO_INIT;
1037 {
1038 std::lock_guard l(mLock);
Mikhail Naganova317a802024-03-15 18:03:10 +00001039 mMapper.resetUnusedPatchesAndPortConfigs();
Mikhail Naganovac9d4e72023-10-23 12:00:09 -07001040 }
Mikhail Naganove93a0862023-03-15 17:06:59 -07001041 ModuleDebug debug{ .simulateDeviceConnections = enabled };
1042 status_t status = statusTFromBinderStatus(mModule->setModuleDebug(debug));
1043 // This is important to log as it affects HAL behavior.
1044 if (status == OK) {
1045 ALOGI("%s: set enabled: %d", __func__, enabled);
1046 } else {
1047 ALOGW("%s: set enabled to %d failed: %d", __func__, enabled, status);
1048 }
1049 return status;
1050}
1051
Mikhail Naganove7a26ad2023-05-25 17:36:48 -07001052status_t DeviceHalAidl::filterAndRetrieveBtA2dpParameters(
1053 AudioParameter &keys, AudioParameter *result) {
Mikhail Naganove7a26ad2023-05-25 17:36:48 -07001054 if (String8 key = String8(AudioParameter::keyReconfigA2dpSupported); keys.containsKey(key)) {
1055 keys.remove(key);
David Lia7761ed2023-11-03 17:22:07 +00001056 if (mBluetoothA2dp != nullptr) {
1057 bool supports;
1058 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
1059 mBluetoothA2dp->supportsOffloadReconfiguration(&supports)));
1060 result->addInt(key, supports ? 1 : 0);
1061 } else {
1062 ALOGI("%s: no IBluetoothA2dp on %s", __func__, mInstance.c_str());
1063 result->addInt(key, 0);
1064 }
Mikhail Naganove7a26ad2023-05-25 17:36:48 -07001065 }
1066 return OK;
1067}
1068
Eric Laurent7e3c0832023-11-30 15:04:50 +01001069status_t DeviceHalAidl::filterAndRetrieveBtLeParameters(
1070 AudioParameter &keys, AudioParameter *result) {
1071 if (String8 key = String8(AudioParameter::keyReconfigLeSupported); keys.containsKey(key)) {
1072 keys.remove(key);
1073 if (mBluetoothLe != nullptr) {
1074 bool supports;
1075 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
1076 mBluetoothLe->supportsOffloadReconfiguration(&supports)));
1077 result->addInt(key, supports ? 1 : 0);
1078 } else {
1079 ALOGI("%s: no mBluetoothLe on %s", __func__, mInstance.c_str());
1080 result->addInt(key, 0);
1081 }
1082 }
1083 return OK;
1084}
1085
Mikhail Naganovccc82112023-04-27 18:14:15 -07001086status_t DeviceHalAidl::filterAndUpdateBtA2dpParameters(AudioParameter &parameters) {
Mikhail Naganovccc82112023-04-27 18:14:15 -07001087 std::optional<bool> a2dpEnabled;
Mikhail Naganove7a26ad2023-05-25 17:36:48 -07001088 std::optional<std::vector<VendorParameter>> reconfigureOffload;
Mikhail Naganovccc82112023-04-27 18:14:15 -07001089 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1090 parameters, String8(AudioParameter::keyBtA2dpSuspended),
1091 [&a2dpEnabled](const String8& trueOrFalse) {
1092 if (trueOrFalse == AudioParameter::valueTrue) {
1093 a2dpEnabled = false; // 'suspended' == true
1094 return OK;
1095 } else if (trueOrFalse == AudioParameter::valueFalse) {
1096 a2dpEnabled = true; // 'suspended' == false
1097 return OK;
1098 }
1099 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1100 AudioParameter::keyBtA2dpSuspended, trueOrFalse.c_str());
1101 return BAD_VALUE;
1102 }));
Mikhail Naganove7a26ad2023-05-25 17:36:48 -07001103 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1104 parameters, String8(AudioParameter::keyReconfigA2dp),
1105 [&](const String8& value) -> status_t {
Mikhail Naganove5011002024-01-26 10:57:19 -08001106 std::vector<VendorParameter> result;
1107 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
1108 mVendorExt->parseBluetoothA2dpReconfigureOffload(
1109 std::string(value.c_str()), &result)));
1110 reconfigureOffload = std::move(result);
Mikhail Naganove7a26ad2023-05-25 17:36:48 -07001111 return OK;
1112 }));
Mikhail Naganovccc82112023-04-27 18:14:15 -07001113 if (mBluetoothA2dp != nullptr && a2dpEnabled.has_value()) {
1114 return statusTFromBinderStatus(mBluetoothA2dp->setEnabled(a2dpEnabled.value()));
1115 }
Mikhail Naganove7a26ad2023-05-25 17:36:48 -07001116 if (mBluetoothA2dp != nullptr && reconfigureOffload.has_value()) {
1117 return statusTFromBinderStatus(mBluetoothA2dp->reconfigureOffload(
1118 reconfigureOffload.value()));
1119 }
Mikhail Naganovccc82112023-04-27 18:14:15 -07001120 return OK;
1121}
1122
1123status_t DeviceHalAidl::filterAndUpdateBtHfpParameters(AudioParameter &parameters) {
Mikhail Naganovccc82112023-04-27 18:14:15 -07001124 IBluetooth::HfpConfig hfpConfig;
1125 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1126 parameters, String8(AudioParameter::keyBtHfpEnable),
1127 [&hfpConfig](const String8& trueOrFalse) {
1128 if (trueOrFalse == AudioParameter::valueTrue) {
1129 hfpConfig.isEnabled = Boolean{ .value = true };
1130 return OK;
1131 } else if (trueOrFalse == AudioParameter::valueFalse) {
1132 hfpConfig.isEnabled = Boolean{ .value = false };
1133 return OK;
1134 }
1135 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1136 AudioParameter::keyBtHfpEnable, trueOrFalse.c_str());
1137 return BAD_VALUE;
1138 }));
1139 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
1140 parameters, String8(AudioParameter::keyBtHfpSamplingRate),
1141 [&hfpConfig](int sampleRate) {
1142 return sampleRate > 0 ?
1143 hfpConfig.sampleRate = Int{ .value = sampleRate }, OK : BAD_VALUE;
1144 }));
1145 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
1146 parameters, String8(AudioParameter::keyBtHfpVolume),
1147 [&hfpConfig](int volume0to15) {
1148 if (volume0to15 >= 0 && volume0to15 <= 15) {
1149 hfpConfig.volume = Float{ .value = volume0to15 / 15.0f };
1150 return OK;
1151 }
1152 return BAD_VALUE;
1153 }));
1154 if (mBluetooth != nullptr && hfpConfig != IBluetooth::HfpConfig{}) {
1155 IBluetooth::HfpConfig newHfpConfig;
1156 return statusTFromBinderStatus(mBluetooth->setHfpConfig(hfpConfig, &newHfpConfig));
1157 }
1158 return OK;
1159}
1160
1161status_t DeviceHalAidl::filterAndUpdateBtLeParameters(AudioParameter &parameters) {
Mikhail Naganovccc82112023-04-27 18:14:15 -07001162 std::optional<bool> leEnabled;
Eric Laurent7e3c0832023-11-30 15:04:50 +01001163 std::optional<std::vector<VendorParameter>> reconfigureOffload;
Mikhail Naganovccc82112023-04-27 18:14:15 -07001164 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1165 parameters, String8(AudioParameter::keyBtLeSuspended),
1166 [&leEnabled](const String8& trueOrFalse) {
1167 if (trueOrFalse == AudioParameter::valueTrue) {
1168 leEnabled = false; // 'suspended' == true
1169 return OK;
1170 } else if (trueOrFalse == AudioParameter::valueFalse) {
1171 leEnabled = true; // 'suspended' == false
1172 return OK;
1173 }
1174 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1175 AudioParameter::keyBtLeSuspended, trueOrFalse.c_str());
1176 return BAD_VALUE;
1177 }));
Eric Laurent7e3c0832023-11-30 15:04:50 +01001178 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1179 parameters, String8(AudioParameter::keyReconfigLe),
1180 [&](const String8& value) -> status_t {
1181 if (mVendorExt != nullptr) {
1182 std::vector<VendorParameter> result;
1183 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
1184 mVendorExt->parseBluetoothLeReconfigureOffload(
1185 std::string(value.c_str()), &result)));
1186 reconfigureOffload = std::move(result);
1187 } else {
1188 reconfigureOffload = std::vector<VendorParameter>();
1189 }
1190 return OK;
1191 }));
Mikhail Naganovccc82112023-04-27 18:14:15 -07001192 if (mBluetoothLe != nullptr && leEnabled.has_value()) {
1193 return statusTFromBinderStatus(mBluetoothLe->setEnabled(leEnabled.value()));
1194 }
Eric Laurent7e3c0832023-11-30 15:04:50 +01001195 if (mBluetoothLe != nullptr && reconfigureOffload.has_value()) {
1196 return statusTFromBinderStatus(mBluetoothLe->reconfigureOffload(
1197 reconfigureOffload.value()));
1198 }
Mikhail Naganovccc82112023-04-27 18:14:15 -07001199 return OK;
1200}
1201
1202status_t DeviceHalAidl::filterAndUpdateBtScoParameters(AudioParameter &parameters) {
Mikhail Naganovccc82112023-04-27 18:14:15 -07001203 IBluetooth::ScoConfig scoConfig;
1204 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1205 parameters, String8(AudioParameter::keyBtSco),
1206 [&scoConfig](const String8& onOrOff) {
1207 if (onOrOff == AudioParameter::valueOn) {
1208 scoConfig.isEnabled = Boolean{ .value = true };
1209 return OK;
1210 } else if (onOrOff == AudioParameter::valueOff) {
1211 scoConfig.isEnabled = Boolean{ .value = false };
1212 return OK;
1213 }
1214 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1215 AudioParameter::keyBtSco, onOrOff.c_str());
1216 return BAD_VALUE;
1217 }));
1218 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1219 parameters, String8(AudioParameter::keyBtScoHeadsetName),
1220 [&scoConfig](const String8& name) {
1221 scoConfig.debugName = name;
1222 return OK;
1223 }));
1224 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1225 parameters, String8(AudioParameter::keyBtNrec),
1226 [&scoConfig](const String8& onOrOff) {
1227 if (onOrOff == AudioParameter::valueOn) {
1228 scoConfig.isNrecEnabled = Boolean{ .value = true };
1229 return OK;
1230 } else if (onOrOff == AudioParameter::valueOff) {
1231 scoConfig.isNrecEnabled = Boolean{ .value = false };
1232 return OK;
1233 }
1234 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1235 AudioParameter::keyBtNrec, onOrOff.c_str());
1236 return BAD_VALUE;
1237 }));
1238 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1239 parameters, String8(AudioParameter::keyBtScoWb),
1240 [&scoConfig](const String8& onOrOff) {
1241 if (onOrOff == AudioParameter::valueOn) {
1242 scoConfig.mode = IBluetooth::ScoConfig::Mode::SCO_WB;
1243 return OK;
1244 } else if (onOrOff == AudioParameter::valueOff) {
1245 scoConfig.mode = IBluetooth::ScoConfig::Mode::SCO;
1246 return OK;
1247 }
1248 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1249 AudioParameter::keyBtScoWb, onOrOff.c_str());
1250 return BAD_VALUE;
1251 }));
1252 if (mBluetooth != nullptr && scoConfig != IBluetooth::ScoConfig{}) {
1253 IBluetooth::ScoConfig newScoConfig;
1254 return statusTFromBinderStatus(mBluetooth->setScoConfig(scoConfig, &newScoConfig));
1255 }
1256 return OK;
1257}
1258
Mikhail Naganove92c34b2023-05-31 14:24:48 -07001259status_t DeviceHalAidl::filterAndUpdateScreenParameters(AudioParameter &parameters) {
Mikhail Naganove92c34b2023-05-31 14:24:48 -07001260 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1261 parameters, String8(AudioParameter::keyScreenState),
1262 [&](const String8& onOrOff) -> status_t {
1263 std::optional<bool> isTurnedOn;
1264 if (onOrOff == AudioParameter::valueOn) {
1265 isTurnedOn = true;
1266 } else if (onOrOff == AudioParameter::valueOff) {
1267 isTurnedOn = false;
1268 }
1269 if (!isTurnedOn.has_value()) {
1270 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1271 AudioParameter::keyScreenState, onOrOff.c_str());
1272 return BAD_VALUE;
1273 }
1274 return statusTFromBinderStatus(
1275 mModule->updateScreenState(isTurnedOn.value()));
1276 }));
1277 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
1278 parameters, String8(AudioParameter::keyScreenRotation),
1279 [&](int rotationDegrees) -> status_t {
1280 IModule::ScreenRotation rotation;
1281 switch (rotationDegrees) {
1282 case 0: rotation = IModule::ScreenRotation::DEG_0; break;
1283 case 90: rotation = IModule::ScreenRotation::DEG_90; break;
1284 case 180: rotation = IModule::ScreenRotation::DEG_180; break;
1285 case 270: rotation = IModule::ScreenRotation::DEG_270; break;
1286 default:
1287 ALOGE("setParameters: parameter key \"%s\" has invalid value %d",
1288 AudioParameter::keyScreenRotation, rotationDegrees);
1289 return BAD_VALUE;
1290 }
1291 return statusTFromBinderStatus(mModule->updateScreenRotation(rotation));
1292 }));
1293 return OK;
1294}
1295
Mikhail Naganovb9a81312023-07-18 13:55:34 -07001296status_t DeviceHalAidl::filterAndUpdateTelephonyParameters(AudioParameter &parameters) {
Mikhail Naganovb9a81312023-07-18 13:55:34 -07001297 using TtyMode = ITelephony::TelecomConfig::TtyMode;
1298 ITelephony::TelecomConfig telConfig;
1299 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1300 parameters, String8(AudioParameter::keyTtyMode),
1301 [&telConfig](const String8& mode) {
1302 if (mode == AudioParameter::valueTtyModeOff) {
1303 telConfig.ttyMode = TtyMode::OFF;
1304 return OK;
1305 } else if (mode == AudioParameter::valueTtyModeFull) {
1306 telConfig.ttyMode = TtyMode::FULL;
1307 return OK;
1308 } else if (mode == AudioParameter::valueTtyModeHco) {
1309 telConfig.ttyMode = TtyMode::HCO;
1310 return OK;
1311 } else if (mode == AudioParameter::valueTtyModeVco) {
1312 telConfig.ttyMode = TtyMode::VCO;
1313 return OK;
1314 }
1315 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1316 AudioParameter::keyTtyMode, mode.c_str());
1317 return BAD_VALUE;
1318 }));
1319 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1320 parameters, String8(AudioParameter::keyHacSetting),
1321 [&telConfig](const String8& onOrOff) {
1322 if (onOrOff == AudioParameter::valueHacOn) {
1323 telConfig.isHacEnabled = Boolean{ .value = true };
1324 return OK;
1325 } else if (onOrOff == AudioParameter::valueHacOff) {
1326 telConfig.isHacEnabled = Boolean{ .value = false };
1327 return OK;
1328 }
1329 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1330 AudioParameter::keyHacSetting, onOrOff.c_str());
1331 return BAD_VALUE;
1332 }));
1333 if (mTelephony != nullptr && telConfig != ITelephony::TelecomConfig{}) {
1334 ITelephony::TelecomConfig newTelConfig;
1335 return statusTFromBinderStatus(
1336 mTelephony->setTelecomConfig(telConfig, &newTelConfig));
1337 }
1338 return OK;
1339}
1340
Mikhail Naganovdfd594e2023-02-08 16:59:41 -08001341void DeviceHalAidl::clearCallbacks(void* cookie) {
Mikhail Naganov22578412024-08-16 16:50:34 -07001342 std::lock_guard l(mCallbacksLock);
Mikhail Naganovdfd594e2023-02-08 16:59:41 -08001343 mCallbacks.erase(cookie);
1344}
1345
1346sp<StreamOutHalInterfaceCallback> DeviceHalAidl::getStreamOutCallback(void* cookie) {
1347 return getCallbackImpl(cookie, &Callbacks::out);
1348}
1349
1350void DeviceHalAidl::setStreamOutCallback(
1351 void* cookie, const sp<StreamOutHalInterfaceCallback>& cb) {
1352 setCallbackImpl(cookie, &Callbacks::out, cb);
1353}
1354
1355sp<StreamOutHalInterfaceEventCallback> DeviceHalAidl::getStreamOutEventCallback(
1356 void* cookie) {
1357 return getCallbackImpl(cookie, &Callbacks::event);
1358}
1359
1360void DeviceHalAidl::setStreamOutEventCallback(
1361 void* cookie, const sp<StreamOutHalInterfaceEventCallback>& cb) {
1362 setCallbackImpl(cookie, &Callbacks::event, cb);
1363}
1364
1365sp<StreamOutHalInterfaceLatencyModeCallback> DeviceHalAidl::getStreamOutLatencyModeCallback(
1366 void* cookie) {
1367 return getCallbackImpl(cookie, &Callbacks::latency);
1368}
1369
1370void DeviceHalAidl::setStreamOutLatencyModeCallback(
1371 void* cookie, const sp<StreamOutHalInterfaceLatencyModeCallback>& cb) {
1372 setCallbackImpl(cookie, &Callbacks::latency, cb);
1373}
1374
Mikhail Naganov22578412024-08-16 16:50:34 -07001375template <class C>
Mikhail Naganovdfd594e2023-02-08 16:59:41 -08001376sp<C> DeviceHalAidl::getCallbackImpl(void* cookie, wp<C> DeviceHalAidl::Callbacks::* field) {
Mikhail Naganov22578412024-08-16 16:50:34 -07001377 wp<C> result;
1378 {
1379 std::lock_guard l(mCallbacksLock);
1380 if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
1381 result = (it->second).*field;
1382 }
Mikhail Naganovdfd594e2023-02-08 16:59:41 -08001383 }
Mikhail Naganov22578412024-08-16 16:50:34 -07001384 return result.promote();
Mikhail Naganovdfd594e2023-02-08 16:59:41 -08001385}
1386template<class C>
1387void DeviceHalAidl::setCallbackImpl(
1388 void* cookie, wp<C> DeviceHalAidl::Callbacks::* field, const sp<C>& cb) {
Mikhail Naganov22578412024-08-16 16:50:34 -07001389 std::lock_guard l(mCallbacksLock);
Mikhail Naganovdfd594e2023-02-08 16:59:41 -08001390 if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
1391 (it->second).*field = cb;
1392 }
1393}
1394
Mikhail Naganov31d46652023-01-10 18:29:25 +00001395} // namespace android