1 /*
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"
18 // #define LOG_NDEBUG 0
19
20 #include <algorithm>
21
22 #include <aidl/android/hardware/audio/core/BnStreamCallback.h>
23 #include <aidl/android/hardware/audio/core/BnStreamOutEventCallback.h>
24 #include <aidl/android/hardware/audio/core/StreamDescriptor.h>
25 #include <error/expected_utils.h>
26 #include <media/AidlConversionCppNdk.h>
27 #include <media/AidlConversionNdkCpp.h>
28 #include <media/AidlConversionUtil.h>
29 #include <mediautils/TimeCheck.h>
30 #include <system/audio.h>
31 #include <Utils.h>
32 #include <utils/Log.h>
33
34 #include "DeviceHalAidl.h"
35 #include "EffectHalAidl.h"
36 #include "StreamHalAidl.h"
37
38 using aidl::android::aidl_utils::statusTFromBinderStatus;
39 using aidl::android::media::audio::common::Boolean;
40 using aidl::android::media::audio::common::AudioConfig;
41 using aidl::android::media::audio::common::AudioDevice;
42 using aidl::android::media::audio::common::AudioDeviceType;
43 using aidl::android::media::audio::common::AudioIoFlags;
44 using aidl::android::media::audio::common::AudioLatencyMode;
45 using aidl::android::media::audio::common::AudioMMapPolicy;
46 using aidl::android::media::audio::common::AudioMMapPolicyInfo;
47 using aidl::android::media::audio::common::AudioMMapPolicyType;
48 using aidl::android::media::audio::common::AudioMode;
49 using aidl::android::media::audio::common::AudioOutputFlags;
50 using aidl::android::media::audio::common::AudioPort;
51 using aidl::android::media::audio::common::AudioPortConfig;
52 using aidl::android::media::audio::common::AudioPortExt;
53 using aidl::android::media::audio::common::AudioSource;
54 using aidl::android::media::audio::common::Float;
55 using aidl::android::media::audio::common::Int;
56 using aidl::android::media::audio::common::MicrophoneDynamicInfo;
57 using aidl::android::media::audio::common::MicrophoneInfo;
58 using aidl::android::media::audio::IHalAdapterVendorExtension;
59 using aidl::android::hardware::audio::common::getFrameSizeInBytes;
60 using aidl::android::hardware::audio::common::isBitPositionFlagSet;
61 using aidl::android::hardware::audio::common::kDumpFromAudioServerArgument;
62 using aidl::android::hardware::audio::common::RecordTrackMetadata;
63 using aidl::android::hardware::audio::core::sounddose::ISoundDose;
64 using aidl::android::hardware::audio::core::AudioPatch;
65 using aidl::android::hardware::audio::core::AudioRoute;
66 using aidl::android::hardware::audio::core::IBluetooth;
67 using aidl::android::hardware::audio::core::IBluetoothA2dp;
68 using aidl::android::hardware::audio::core::IBluetoothLe;
69 using aidl::android::hardware::audio::core::IModule;
70 using aidl::android::hardware::audio::core::ITelephony;
71 using aidl::android::hardware::audio::core::ModuleDebug;
72 using aidl::android::hardware::audio::core::VendorParameter;
73
74 namespace android {
75
76 namespace {
77
78 // 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.
ndk2cpp_AudioRoute(const AudioRoute & ndk)81 ConversionResult<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;
87 return cpp;
88 }
89
90 template<typename T>
retrieveSubInterface(const std::shared_ptr<IModule> & module,::ndk::ScopedAStatus (IModule::* getT)(std::shared_ptr<T> *))91 std::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
102 } // namespace
103
DeviceHalAidl(const std::string & instance,const std::shared_ptr<IModule> & module,const std::shared_ptr<IHalAdapterVendorExtension> & vext)104 DeviceHalAidl::DeviceHalAidl(const std::string& instance, const std::shared_ptr<IModule>& module,
105 const std::shared_ptr<IHalAdapterVendorExtension>& vext)
106 : ConversionHelperAidl("DeviceHalAidl"),
107 mInstance(instance), mModule(module), mVendorExt(vext),
108 mTelephony(retrieveSubInterface<ITelephony>(module, &IModule::getTelephony)),
109 mBluetooth(retrieveSubInterface<IBluetooth>(module, &IModule::getBluetooth)),
110 mBluetoothA2dp(retrieveSubInterface<IBluetoothA2dp>(module, &IModule::getBluetoothA2dp)),
111 mBluetoothLe(retrieveSubInterface<IBluetoothLe>(module, &IModule::getBluetoothLe)),
112 mSoundDose(retrieveSubInterface<ISoundDose>(module, &IModule::getSoundDose)),
113 mMapper(instance, module), mMapperAccessor(mMapper, mLock) {
114 }
115
getAudioPorts(std::vector<media::audio::common::AudioPort> * ports)116 status_t DeviceHalAidl::getAudioPorts(std::vector<media::audio::common::AudioPort> *ports) {
117 std::lock_guard l(mLock);
118 return mMapper.getAudioPorts(ports, ndk2cpp_AudioPort);
119 }
120
getAudioRoutes(std::vector<media::AudioRoute> * routes)121 status_t DeviceHalAidl::getAudioRoutes(std::vector<media::AudioRoute> *routes) {
122 std::lock_guard l(mLock);
123 return mMapper.getAudioRoutes(routes, ndk2cpp_AudioRoute);
124 }
125
getSupportedModes(std::vector<media::audio::common::AudioMode> * modes)126 status_t DeviceHalAidl::getSupportedModes(std::vector<media::audio::common::AudioMode> *modes) {
127 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
128 TIME_CHECK();
129 if (mModule == nullptr) return NO_INIT;
130 if (mTelephony == nullptr) return INVALID_OPERATION;
131 if (modes == nullptr) {
132 return BAD_VALUE;
133 }
134 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
getSupportedDevices(uint32_t *)143 status_t DeviceHalAidl::getSupportedDevices(uint32_t*) {
144 // Obsolete.
145 return INVALID_OPERATION;
146 }
147
initCheck()148 status_t DeviceHalAidl::initCheck() {
149 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
150 TIME_CHECK();
151 if (mModule == nullptr) return NO_INIT;
152 std::lock_guard l(mLock);
153 return mMapper.initialize();
154 }
155
setVoiceVolume(float volume)156 status_t DeviceHalAidl::setVoiceVolume(float volume) {
157 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
158 TIME_CHECK();
159 if (mModule == nullptr) return NO_INIT;
160 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;
168 }
169
setMasterVolume(float volume)170 status_t DeviceHalAidl::setMasterVolume(float volume) {
171 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
172 TIME_CHECK();
173 if (mModule == nullptr) return NO_INIT;
174 return statusTFromBinderStatus(mModule->setMasterVolume(volume));
175 }
176
getMasterVolume(float * volume)177 status_t DeviceHalAidl::getMasterVolume(float *volume) {
178 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
179 TIME_CHECK();
180 if (mModule == nullptr) return NO_INIT;
181 if (volume == nullptr) {
182 return BAD_VALUE;
183 }
184 return statusTFromBinderStatus(mModule->getMasterVolume(volume));
185 }
186
setMode(audio_mode_t mode)187 status_t DeviceHalAidl::setMode(audio_mode_t mode) {
188 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
189 TIME_CHECK();
190 if (mModule == nullptr) return NO_INIT;
191 AudioMode audioMode = VALUE_OR_FATAL(::aidl::android::legacy2aidl_audio_mode_t_AudioMode(mode));
192 if (mTelephony != nullptr) {
193 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mTelephony->switchAudioMode(audioMode)));
194 }
195 return statusTFromBinderStatus(mModule->updateAudioMode(audioMode));
196 }
197
setMicMute(bool state)198 status_t DeviceHalAidl::setMicMute(bool state) {
199 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
200 TIME_CHECK();
201 if (mModule == nullptr) return NO_INIT;
202 return statusTFromBinderStatus(mModule->setMicMute(state));
203 }
204
getMicMute(bool * state)205 status_t DeviceHalAidl::getMicMute(bool *state) {
206 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
207 TIME_CHECK();
208 if (mModule == nullptr) return NO_INIT;
209 if (state == nullptr) {
210 return BAD_VALUE;
211 }
212 return statusTFromBinderStatus(mModule->getMicMute(state));
213 }
214
setMasterMute(bool state)215 status_t DeviceHalAidl::setMasterMute(bool state) {
216 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
217 TIME_CHECK();
218 if (mModule == nullptr) return NO_INIT;
219 return statusTFromBinderStatus(mModule->setMasterMute(state));
220 }
221
getMasterMute(bool * state)222 status_t DeviceHalAidl::getMasterMute(bool *state) {
223 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
224 TIME_CHECK();
225 if (mModule == nullptr) return NO_INIT;
226 if (state == nullptr) {
227 return BAD_VALUE;
228 }
229 return statusTFromBinderStatus(mModule->getMasterMute(state));
230 }
231
setParameters(const String8 & kvPairs)232 status_t DeviceHalAidl::setParameters(const String8& kvPairs) {
233 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
234 TIME_CHECK();
235 if (mModule == nullptr) return NO_INIT;
236 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 }
251 if (status_t status = filterAndUpdateScreenParameters(parameters); status != OK) {
252 ALOGW("%s: filtering or updating screen parameters failed: %d", __func__, status);
253 }
254 if (status_t status = filterAndUpdateTelephonyParameters(parameters); status != OK) {
255 ALOGW("%s: filtering or updating telephony parameters failed: %d", __func__, status);
256 }
257 return parseAndSetVendorParameters(mVendorExt, mModule, parameters);
258 }
259
getParameters(const String8 & keys,String8 * values)260 status_t DeviceHalAidl::getParameters(const String8& keys, String8 *values) {
261 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
262 TIME_CHECK();
263 if (mModule == nullptr) return NO_INIT;
264 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 }
271 if (status_t status = filterAndRetrieveBtLeParameters(parameterKeys, &result); status != OK) {
272 ALOGW("%s: filtering or retrieving BT LE parameters failed: %d", __func__, status);
273 }
274 *values = result.toString();
275 return parseAndGetVendorParameters(mVendorExt, mModule, parameterKeys, values);
276 }
277
getInputBufferSize(struct audio_config * config,size_t * size)278 status_t DeviceHalAidl::getInputBufferSize(struct audio_config* config, size_t* size) {
279 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
280 TIME_CHECK();
281 if (mModule == nullptr) return NO_INIT;
282 if (config == nullptr || size == nullptr) {
283 return BAD_VALUE;
284 }
285 constexpr bool isInput = true;
286 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
287 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, isInput));
288 AudioDevice aidlDevice;
289 aidlDevice.type.type = AudioDeviceType::IN_DEFAULT;
290 AudioSource aidlSource = AudioSource::DEFAULT;
291 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::input>(0);
292 AudioPortConfig mixPortConfig;
293 Hal2AidlMapper::Cleanups cleanups(mMapperAccessor);
294 AudioPatch aidlPatch;
295 {
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 }
301 *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.
304 *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
310 namespace {
311
312 class StreamCallbackBase {
313 protected:
StreamCallbackBase(const sp<CallbackBroker> & broker)314 explicit StreamCallbackBase(const sp<CallbackBroker>& broker) : mBroker(broker) {}
315 public:
getCookie() const316 void* getCookie() const { return mCookie; }
setCookie(void * cookie)317 void setCookie(void* cookie) { mCookie = cookie; }
getBroker() const318 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
327 template<class C>
328 class StreamCallbackBaseHelper {
329 protected:
StreamCallbackBaseHelper(const StreamCallbackBase & base)330 explicit StreamCallbackBaseHelper(const StreamCallbackBase& base) : mBase(base) {}
331 sp<C> getCb(const sp<CallbackBroker>& broker, void* cookie);
332 using CbRef = const sp<C>&;
runCb(const std::function<void (CbRef cb)> & f)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
341 template<>
getCb(const sp<CallbackBroker> & broker,void * cookie)342 sp<StreamOutHalInterfaceCallback> StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>::getCb(
343 const sp<CallbackBroker>& broker, void* cookie) {
344 if (broker != nullptr) return broker->getStreamOutCallback(cookie);
345 return nullptr;
346 }
347
348 template<>
349 sp<StreamOutHalInterfaceEventCallback>
getCb(const sp<CallbackBroker> & broker,void * cookie)350 StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>::getCb(
351 const sp<CallbackBroker>& broker, void* cookie) {
352 if (broker != nullptr) return broker->getStreamOutEventCallback(cookie);
353 return nullptr;
354 }
355
356 template<>
357 sp<StreamOutHalInterfaceLatencyModeCallback>
getCb(const sp<CallbackBroker> & broker,void * cookie)358 StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>::getCb(
359 const sp<CallbackBroker>& broker, void* cookie) {
360 if (broker != nullptr) return broker->getStreamOutLatencyModeCallback(cookie);
361 return nullptr;
362 }
363
364 /*
365 Note on the callback ownership.
366
367 In the Binder ownership model, the server implementation is kept alive
368 as long as there is any client (proxy object) alive. This is done by
369 incrementing the refcount of the server-side object by the Binder framework.
370 When it detects that the last client is gone, it decrements the refcount back.
371
372 Thus, it is not needed to keep any references to StreamCallback on our
373 side (after we have sent an instance to the client), because we are
374 the server-side. The callback object will be kept alive as long as the HAL server
375 holds a strong ref to IStreamCallback proxy.
376 */
377
378 class OutputStreamCallbackAidl : public StreamCallbackBase,
379 public StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>,
380 public ::aidl::android::hardware::audio::core::BnStreamCallback {
381 public:
OutputStreamCallbackAidl(const sp<CallbackBroker> & broker)382 explicit OutputStreamCallbackAidl(const sp<CallbackBroker>& broker)
383 : StreamCallbackBase(broker),
384 StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>(
385 *static_cast<StreamCallbackBase*>(this)) {}
onTransferReady()386 ndk::ScopedAStatus onTransferReady() override {
387 return runCb([](CbRef cb) { cb->onWriteReady(); });
388 }
onError()389 ndk::ScopedAStatus onError() override {
390 return runCb([](CbRef cb) { cb->onError(true /*isHardError*/); });
391 }
onDrainReady()392 ndk::ScopedAStatus onDrainReady() override {
393 return runCb([](CbRef cb) { cb->onDrainReady(); });
394 }
395 };
396
397 class OutputStreamEventCallbackAidl :
398 public StreamCallbackBase,
399 public StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>,
400 public StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>,
401 public ::aidl::android::hardware::audio::core::BnStreamOutEventCallback {
402 public:
OutputStreamEventCallbackAidl(const sp<CallbackBroker> & broker)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)) {}
onCodecFormatChanged(const std::vector<uint8_t> & halMetadata)409 ndk::ScopedAStatus onCodecFormatChanged(const std::vector<uint8_t>& halMetadata) override {
410 return StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>::runCb(
411 [&halMetadata](auto cb) { cb->onCodecFormatChanged(halMetadata); });
412 }
onRecommendedLatencyModeChanged(const std::vector<AudioLatencyMode> & in_modes)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
openOutputStream(audio_io_handle_t handle,audio_devices_t devices,audio_output_flags_t flags,struct audio_config * config,const char * address,sp<StreamOutHalInterface> * outStream)426 status_t DeviceHalAidl::openOutputStream(
427 audio_io_handle_t handle, audio_devices_t devices,
428 audio_output_flags_t flags, struct audio_config* config,
429 const char* address,
430 sp<StreamOutHalInterface>* outStream) {
431 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
432 TIME_CHECK();
433 if (mModule == nullptr) return NO_INIT;
434 if (outStream == nullptr || config == nullptr) {
435 return BAD_VALUE;
436 }
437 constexpr bool isInput = false;
438 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(
441 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, isInput));
442 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;
448 AudioPatch aidlPatch;
449 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));
458 if (mixPortConfig.id == 0) return BAD_VALUE; // HAL suggests a different config.
459 ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamArguments args;
460 args.portConfigId = mixPortConfig.id;
461 const bool isOffload = isBitPositionFlagSet(
462 aidlOutputFlags, AudioOutputFlags::COMPRESS_OFFLOAD);
463 const bool isHwAvSync = isBitPositionFlagSet(
464 aidlOutputFlags, AudioOutputFlags::HW_AV_SYNC);
465 std::shared_ptr<OutputStreamCallbackAidl> streamCb;
466 if (isOffload) {
467 streamCb = ndk::SharedRefBase::make<OutputStreamCallbackAidl>(this);
468 }
469 auto eventCb = ndk::SharedRefBase::make<OutputStreamEventCallbackAidl>(this);
470 if (isOffload || isHwAvSync) {
471 args.offloadInfo = aidlConfig.offloadInfo;
472 }
473 if (isOffload) {
474 args.callback = streamCb;
475 }
476 args.bufferSizeFrames = aidlConfig.frameCount;
477 args.eventCallback = eventCb;
478 ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamReturn ret;
479 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openOutputStream(args, &ret)));
480 StreamContextAidl context(ret.desc, isOffload);
481 if (!context.isValid()) {
482 ALOGE("%s: Failed to created a valid stream context from the descriptor: %s",
483 __func__, ret.desc.toString().c_str());
484 return NO_INIT;
485 }
486 auto stream = sp<StreamOutHalAidl>::make(*config, std::move(context), aidlPatch.latenciesMs[0],
487 std::move(ret.stream), mVendorExt, this /*callbackBroker*/);
488 *outStream = stream;
489 /* StreamOutHalInterface* */ void* cbCookie = (*outStream).get();
490 {
491 std::lock_guard l(mLock);
492 mCallbacks.emplace(cbCookie, Callbacks{});
493 mMapper.addStream(*outStream, mixPortConfig.id, aidlPatch.id);
494 }
495 if (streamCb) {
496 streamCb->setCookie(cbCookie);
497 // Although StreamOutHalAidl implements StreamOutHalInterfaceCallback,
498 // we always go via the CallbackBroker for consistency.
499 setStreamOutCallback(cbCookie, stream);
500 }
501 eventCb->setCookie(cbCookie);
502 cleanups.disarmAll();
503 return OK;
504 }
505
openInputStream(audio_io_handle_t handle,audio_devices_t devices,struct audio_config * config,audio_input_flags_t flags,const char * address,audio_source_t source,audio_devices_t outputDevice,const char * outputDeviceAddress,sp<StreamInHalInterface> * inStream)506 status_t DeviceHalAidl::openInputStream(
507 audio_io_handle_t handle, audio_devices_t devices,
508 struct audio_config* config, audio_input_flags_t flags,
509 const char* address, audio_source_t source,
510 audio_devices_t outputDevice, const char* outputDeviceAddress,
511 sp<StreamInHalInterface>* inStream) {
512 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
513 TIME_CHECK();
514 if (mModule == nullptr) return NO_INIT;
515 if (inStream == nullptr || config == nullptr) {
516 return BAD_VALUE;
517 }
518 constexpr bool isInput = true;
519 int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
520 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(handle));
521 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
522 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, isInput));
523 AudioDevice aidlDevice = VALUE_OR_RETURN_STATUS(
524 ::aidl::android::legacy2aidl_audio_device_AudioDevice(devices, address));
525 int32_t aidlInputFlags = VALUE_OR_RETURN_STATUS(
526 ::aidl::android::legacy2aidl_audio_input_flags_t_int32_t_mask(flags));
527 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::input>(aidlInputFlags);
528 AudioSource aidlSource = VALUE_OR_RETURN_STATUS(
529 ::aidl::android::legacy2aidl_audio_source_t_AudioSource(source));
530 AudioPortConfig mixPortConfig;
531 AudioPatch aidlPatch;
532 Hal2AidlMapper::Cleanups cleanups(mMapperAccessor);
533 {
534 std::lock_guard l(mLock);
535 RETURN_STATUS_IF_ERROR(mMapper.prepareToOpenStream(
536 aidlHandle, aidlDevice, aidlFlags, aidlSource,
537 &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
538 }
539 *config = VALUE_OR_RETURN_STATUS(
540 ::aidl::android::aidl2legacy_AudioConfig_audio_config_t(aidlConfig, isInput));
541 if (mixPortConfig.id == 0) return BAD_VALUE; // HAL suggests a different config.
542 ::aidl::android::hardware::audio::core::IModule::OpenInputStreamArguments args;
543 args.portConfigId = mixPortConfig.id;
544 RecordTrackMetadata aidlTrackMetadata{
545 .source = aidlSource, .gain = 1, .channelMask = aidlConfig.base.channelMask };
546 if (outputDevice != AUDIO_DEVICE_NONE) {
547 aidlTrackMetadata.destinationDevice = VALUE_OR_RETURN_STATUS(
548 ::aidl::android::legacy2aidl_audio_device_AudioDevice(
549 outputDevice, outputDeviceAddress));
550 }
551 args.sinkMetadata.tracks.push_back(std::move(aidlTrackMetadata));
552 args.bufferSizeFrames = aidlConfig.frameCount;
553 ::aidl::android::hardware::audio::core::IModule::OpenInputStreamReturn ret;
554 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openInputStream(args, &ret)));
555 StreamContextAidl context(ret.desc, false /*isAsynchronous*/);
556 if (!context.isValid()) {
557 ALOGE("%s: Failed to created a valid stream context from the descriptor: %s",
558 __func__, ret.desc.toString().c_str());
559 return NO_INIT;
560 }
561 *inStream = sp<StreamInHalAidl>::make(*config, std::move(context), aidlPatch.latenciesMs[0],
562 std::move(ret.stream), mVendorExt, this /*micInfoProvider*/);
563 {
564 std::lock_guard l(mLock);
565 mMapper.addStream(*inStream, mixPortConfig.id, aidlPatch.id);
566 }
567 cleanups.disarmAll();
568 return OK;
569 }
570
supportsAudioPatches(bool * supportsPatches)571 status_t DeviceHalAidl::supportsAudioPatches(bool* supportsPatches) {
572 if (supportsPatches == nullptr) {
573 return BAD_VALUE;
574 }
575 *supportsPatches = true;
576 return OK;
577 }
578
createAudioPatch(unsigned int num_sources,const struct audio_port_config * sources,unsigned int num_sinks,const struct audio_port_config * sinks,audio_patch_handle_t * patch)579 status_t DeviceHalAidl::createAudioPatch(unsigned int num_sources,
580 const struct audio_port_config* sources,
581 unsigned int num_sinks,
582 const struct audio_port_config* sinks,
583 audio_patch_handle_t* patch) {
584 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
585 TIME_CHECK();
586 if (mModule == nullptr) return NO_INIT;
587 if (num_sinks > AUDIO_PATCH_PORTS_MAX || num_sources > AUDIO_PATCH_PORTS_MAX ||
588 sources == nullptr || sinks == nullptr || patch == nullptr) {
589 return BAD_VALUE;
590 }
591 // When the patch handle (*patch) is AUDIO_PATCH_HANDLE_NONE, it means
592 // the framework wants to create a new patch. The handle has to be generated
593 // by the HAL. Since handles generated this way can only be unique within
594 // a HAL module, the framework generates a globally unique handle, and maps
595 // it on the <HAL module, patch handle> pair.
596 // When the patch handle is set, it meant the framework intends to update
597 // an existing patch.
598 //
599 // This behavior corresponds to HAL module behavior, with the only difference
600 // that the HAL module uses `int32_t` for patch IDs. The following assert ensures
601 // that both the framework and the HAL use the same value for "no ID":
602 static_assert(AUDIO_PATCH_HANDLE_NONE == 0);
603
604 // Upon conversion, mix port configs contain audio configuration, while
605 // device port configs contain device address. This data is used to find
606 // or create HAL configs.
607 std::vector<AudioPortConfig> aidlSources, aidlSinks;
608 for (unsigned int i = 0; i < num_sources; ++i) {
609 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
610 sources[i].role, sources[i].type)) ==
611 ::aidl::android::AudioPortDirection::INPUT;
612 aidlSources.push_back(VALUE_OR_RETURN_STATUS(
613 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
614 sources[i], isInput, 0)));
615 }
616 for (unsigned int i = 0; i < num_sinks; ++i) {
617 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
618 sinks[i].role, sinks[i].type)) ==
619 ::aidl::android::AudioPortDirection::INPUT;
620 aidlSinks.push_back(VALUE_OR_RETURN_STATUS(
621 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
622 sinks[i], isInput, 0)));
623 }
624 int32_t aidlPatchId = static_cast<int32_t>(*patch);
625 Hal2AidlMapper::Cleanups cleanups(mMapperAccessor);
626 {
627 std::lock_guard l(mLock);
628 // Check for patches that only exist for the framework, or have different HAL patch ID.
629 if (int32_t aidlHalPatchId = mMapper.findFwkPatch(aidlPatchId); aidlHalPatchId != 0) {
630 if (aidlHalPatchId == aidlPatchId) {
631 // This patch was previously released by the HAL. Thus we need to pass '0'
632 // to the HAL to obtain a new patch.
633 int32_t newAidlPatchId = 0;
634 RETURN_STATUS_IF_ERROR(mMapper.createOrUpdatePatch(
635 aidlSources, aidlSinks, &newAidlPatchId, &cleanups));
636 mMapper.updateFwkPatch(aidlPatchId, newAidlPatchId);
637 } else {
638 RETURN_STATUS_IF_ERROR(mMapper.createOrUpdatePatch(
639 aidlSources, aidlSinks, &aidlHalPatchId, &cleanups));
640 }
641 } else {
642 RETURN_STATUS_IF_ERROR(mMapper.createOrUpdatePatch(
643 aidlSources, aidlSinks, &aidlPatchId, &cleanups));
644 }
645 }
646 *patch = static_cast<audio_patch_handle_t>(aidlPatchId);
647 cleanups.disarmAll();
648 return OK;
649 }
650
releaseAudioPatch(audio_patch_handle_t patch)651 status_t DeviceHalAidl::releaseAudioPatch(audio_patch_handle_t patch) {
652 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
653 TIME_CHECK();
654 if (mModule == nullptr) return NO_INIT;
655 static_assert(AUDIO_PATCH_HANDLE_NONE == 0);
656 if (patch == AUDIO_PATCH_HANDLE_NONE) {
657 return BAD_VALUE;
658 }
659 std::lock_guard l(mLock);
660 // Check for patches that only exist for the framework, or have different HAL patch ID.
661 int32_t aidlPatchId = static_cast<int32_t>(patch);
662 if (int32_t aidlHalPatchId = mMapper.findFwkPatch(aidlPatchId); aidlHalPatchId != 0) {
663 if (aidlHalPatchId == aidlPatchId) {
664 // This patch was previously released by the HAL, just need to finish its removal.
665 mMapper.eraseFwkPatch(aidlPatchId);
666 return OK;
667 } else {
668 // This patch has a HAL patch ID which is different
669 aidlPatchId = aidlHalPatchId;
670 }
671 }
672 RETURN_STATUS_IF_ERROR(mMapper.releaseAudioPatch(aidlPatchId));
673 return OK;
674 }
675
getAudioPort(struct audio_port * port)676 status_t DeviceHalAidl::getAudioPort(struct audio_port* port) {
677 if (port == nullptr) {
678 return BAD_VALUE;
679 }
680 audio_port_v7 portV7;
681 audio_populate_audio_port_v7(port, &portV7);
682 RETURN_STATUS_IF_ERROR(getAudioPort(&portV7));
683 return audio_populate_audio_port(&portV7, port) ? OK : BAD_VALUE;
684 }
685
getAudioPort(struct audio_port_v7 * port)686 status_t DeviceHalAidl::getAudioPort(struct audio_port_v7 *port) {
687 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
688 TIME_CHECK();
689 if (mModule == nullptr) return NO_INIT;
690 if (port == nullptr) {
691 return BAD_VALUE;
692 }
693 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(port->role, port->type)) ==
694 ::aidl::android::AudioPortDirection::INPUT;
695 auto aidlPort = VALUE_OR_RETURN_STATUS(
696 ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
697 if (aidlPort.ext.getTag() != AudioPortExt::device) {
698 ALOGE("%s: provided port is not a device port (module %s): %s",
699 __func__, mInstance.c_str(), aidlPort.toString().c_str());
700 return BAD_VALUE;
701 }
702 const auto& matchDevice = aidlPort.ext.get<AudioPortExt::device>().device;
703 // It seems that we don't have to call HAL since all valid ports have been added either
704 // during initialization, or while handling connection of an external device.
705 const int32_t fwkId = aidlPort.id;
706 {
707 std::lock_guard l(mLock);
708 RETURN_STATUS_IF_ERROR(mMapper.getAudioPortCached(matchDevice, &aidlPort));
709 }
710 aidlPort.id = fwkId;
711 *port = VALUE_OR_RETURN_STATUS(::aidl::android::aidl2legacy_AudioPort_audio_port_v7(
712 aidlPort, isInput));
713 return OK;
714 }
715
getAudioMixPort(const struct audio_port_v7 * devicePort,struct audio_port_v7 * mixPort)716 status_t DeviceHalAidl::getAudioMixPort(const struct audio_port_v7 *devicePort,
717 struct audio_port_v7 *mixPort) {
718 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
719 TIME_CHECK();
720 if (mModule == nullptr) return NO_INIT;
721 if (devicePort == nullptr || mixPort == nullptr ||
722 devicePort->type != AUDIO_PORT_TYPE_DEVICE || mixPort->type != AUDIO_PORT_TYPE_MIX) {
723 return BAD_VALUE;
724 }
725 const int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
726 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(mixPort->ext.mix.handle));
727 AudioPort port;
728 {
729 std::lock_guard l(mLock);
730 RETURN_STATUS_IF_ERROR(mMapper.getAudioMixPort(aidlHandle, &port));
731 }
732 const bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
733 mixPort->role, mixPort->type)) == ::aidl::android::AudioPortDirection::INPUT;
734 *mixPort = VALUE_OR_RETURN_STATUS(::aidl::android::aidl2legacy_AudioPort_audio_port_v7(
735 port, isInput));
736 return OK;
737 }
738
setAudioPortConfig(const struct audio_port_config * config)739 status_t DeviceHalAidl::setAudioPortConfig(const struct audio_port_config* config) {
740 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
741 TIME_CHECK();
742 if (mModule == nullptr) return NO_INIT;
743 if (config == nullptr) {
744 return BAD_VALUE;
745 }
746 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
747 config->role, config->type)) == ::aidl::android::AudioPortDirection::INPUT;
748 AudioPortConfig requestedPortConfig = VALUE_OR_RETURN_STATUS(
749 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
750 *config, isInput, 0 /*portId*/));
751 AudioPortConfig portConfig;
752 std::lock_guard l(mLock);
753 return mMapper.setPortConfig(requestedPortConfig, std::set<int32_t>(), &portConfig);
754 }
755
getMicrophoneInfo()756 MicrophoneInfoProvider::Info const* DeviceHalAidl::getMicrophoneInfo() {
757 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
758 TIME_CHECK();
759 if (!mModule) return {};
760 std::lock_guard l(mLock);
761 if (mMicrophones.status == Microphones::Status::UNKNOWN) {
762 TIME_CHECK();
763 std::vector<MicrophoneInfo> aidlInfo;
764 status_t status = statusTFromBinderStatus(mModule->getMicrophones(&aidlInfo));
765 if (status == OK) {
766 mMicrophones.status = Microphones::Status::QUERIED;
767 mMicrophones.info = std::move(aidlInfo);
768 } else if (status == INVALID_OPERATION) {
769 mMicrophones.status = Microphones::Status::NOT_SUPPORTED;
770 } else {
771 ALOGE("%s: Unexpected status from 'IModule.getMicrophones': %d", __func__, status);
772 return {};
773 }
774 }
775 if (mMicrophones.status == Microphones::Status::QUERIED) {
776 return &mMicrophones.info;
777 }
778 return {}; // NOT_SUPPORTED
779 }
780
getMicrophones(std::vector<audio_microphone_characteristic_t> * microphones)781 status_t DeviceHalAidl::getMicrophones(
782 std::vector<audio_microphone_characteristic_t>* microphones) {
783 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
784 TIME_CHECK();
785 if (mModule == nullptr) return NO_INIT;
786 if (microphones == nullptr) {
787 return BAD_VALUE;
788 }
789 auto staticInfo = getMicrophoneInfo();
790 if (!staticInfo) return INVALID_OPERATION;
791 std::vector<MicrophoneDynamicInfo> emptyDynamicInfo;
792 emptyDynamicInfo.reserve(staticInfo->size());
793 std::transform(staticInfo->begin(), staticInfo->end(), std::back_inserter(emptyDynamicInfo),
794 [](const auto& info) { return MicrophoneDynamicInfo{ .id = info.id }; });
795 *microphones = VALUE_OR_RETURN_STATUS(
796 ::aidl::android::convertContainers<std::vector<audio_microphone_characteristic_t>>(
797 *staticInfo, emptyDynamicInfo,
798 ::aidl::android::aidl2legacy_MicrophoneInfos_audio_microphone_characteristic_t)
799 );
800 return OK;
801 }
802
addDeviceEffect(const struct audio_port_config * device,sp<EffectHalInterface> effect)803 status_t DeviceHalAidl::addDeviceEffect(
804 const struct audio_port_config *device, sp<EffectHalInterface> effect) {
805 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
806 TIME_CHECK();
807 if (mModule == nullptr) return NO_INIT;
808 if (device == nullptr || effect == nullptr) {
809 return BAD_VALUE;
810 }
811 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
812 device->role, device->type)) == ::aidl::android::AudioPortDirection::INPUT;
813 auto requestedPortConfig = VALUE_OR_RETURN_STATUS(
814 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
815 *device, isInput, 0));
816 if (requestedPortConfig.ext.getTag() != AudioPortExt::Tag::device) {
817 ALOGE("%s: provided port config is not a device port config: %s",
818 __func__, requestedPortConfig.toString().c_str());
819 return BAD_VALUE;
820 }
821 AudioPortConfig devicePortConfig;
822 Hal2AidlMapper::Cleanups cleanups(mMapperAccessor);
823 {
824 std::lock_guard l(mLock);
825 RETURN_STATUS_IF_ERROR(mMapper.setPortConfig(
826 requestedPortConfig, {} /*destinationPortIds*/, &devicePortConfig, &cleanups));
827 }
828 auto aidlEffect = sp<effect::EffectHalAidl>::cast(effect);
829 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->addDeviceEffect(
830 devicePortConfig.id, aidlEffect->getIEffect())));
831 cleanups.disarmAll();
832 return OK;
833 }
removeDeviceEffect(const struct audio_port_config * device,sp<EffectHalInterface> effect)834 status_t DeviceHalAidl::removeDeviceEffect(
835 const struct audio_port_config *device, sp<EffectHalInterface> effect) {
836 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
837 TIME_CHECK();
838 if (mModule == nullptr) return NO_INIT;
839 if (device == nullptr || effect == nullptr) {
840 return BAD_VALUE;
841 }
842 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
843 device->role, device->type)) == ::aidl::android::AudioPortDirection::INPUT;
844 auto requestedPortConfig = VALUE_OR_RETURN_STATUS(
845 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
846 *device, isInput, 0));
847 if (requestedPortConfig.ext.getTag() != AudioPortExt::Tag::device) {
848 ALOGE("%s: provided port config is not a device port config: %s",
849 __func__, requestedPortConfig.toString().c_str());
850 return BAD_VALUE;
851 }
852 AudioPortConfig devicePortConfig;
853 {
854 std::lock_guard l(mLock);
855 RETURN_STATUS_IF_ERROR(mMapper.findPortConfig(
856 requestedPortConfig.ext.get<AudioPortExt::Tag::device>().device,
857 &devicePortConfig));
858 }
859 auto aidlEffect = sp<effect::EffectHalAidl>::cast(effect);
860 return statusTFromBinderStatus(mModule->removeDeviceEffect(
861 devicePortConfig.id, aidlEffect->getIEffect()));
862 }
863
getMmapPolicyInfos(media::audio::common::AudioMMapPolicyType policyType,std::vector<media::audio::common::AudioMMapPolicyInfo> * policyInfos)864 status_t DeviceHalAidl::getMmapPolicyInfos(
865 media::audio::common::AudioMMapPolicyType policyType,
866 std::vector<media::audio::common::AudioMMapPolicyInfo>* policyInfos) {
867 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
868 TIME_CHECK();
869 if (mModule == nullptr) return NO_INIT;
870 AudioMMapPolicyType mmapPolicyType = VALUE_OR_RETURN_STATUS(
871 cpp2ndk_AudioMMapPolicyType(policyType));
872
873 std::vector<AudioMMapPolicyInfo> mmapPolicyInfos;
874
875 if (status_t status = statusTFromBinderStatus(
876 mModule->getMmapPolicyInfos(mmapPolicyType, &mmapPolicyInfos)); status != OK) {
877 return status;
878 }
879
880 *policyInfos = VALUE_OR_RETURN_STATUS(
881 convertContainer<std::vector<media::audio::common::AudioMMapPolicyInfo>>(
882 mmapPolicyInfos, ndk2cpp_AudioMMapPolicyInfo));
883 return OK;
884 }
885
getAAudioMixerBurstCount()886 int32_t DeviceHalAidl::getAAudioMixerBurstCount() {
887 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
888 TIME_CHECK();
889 if (mModule == nullptr) return NO_INIT;
890 int32_t mixerBurstCount = 0;
891 if (mModule->getAAudioMixerBurstCount(&mixerBurstCount).isOk()) {
892 return mixerBurstCount;
893 }
894 return 0;
895 }
896
getAAudioHardwareBurstMinUsec()897 int32_t DeviceHalAidl::getAAudioHardwareBurstMinUsec() {
898 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
899 TIME_CHECK();
900 if (mModule == nullptr) return NO_INIT;
901 int32_t hardwareBurstMinUsec = 0;
902 if (mModule->getAAudioHardwareBurstMinUsec(&hardwareBurstMinUsec).isOk()) {
903 return hardwareBurstMinUsec;
904 }
905 return 0;
906 }
907
getHwAvSync()908 error::Result<audio_hw_sync_t> DeviceHalAidl::getHwAvSync() {
909 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
910 TIME_CHECK();
911 if (mModule == nullptr) return NO_INIT;
912 int32_t aidlHwAvSync;
913 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->generateHwAvSyncId(&aidlHwAvSync)));
914 return VALUE_OR_RETURN_STATUS(
915 ::aidl::android::aidl2legacy_int32_t_audio_hw_sync_t(aidlHwAvSync));
916 }
917
dump(int fd,const Vector<String16> & args)918 status_t DeviceHalAidl::dump(int fd, const Vector<String16>& args) {
919 TIME_CHECK();
920 if (mModule == nullptr) return NO_INIT;
921 Vector<String16> newArgs = args;
922 newArgs.push(String16(kDumpFromAudioServerArgument));
923 return mModule->dump(fd, Args(newArgs).args(), newArgs.size());
924 }
925
supportsBluetoothVariableLatency(bool * supports)926 status_t DeviceHalAidl::supportsBluetoothVariableLatency(bool* supports) {
927 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
928 TIME_CHECK();
929 if (mModule == nullptr) return NO_INIT;
930 if (supports == nullptr) {
931 return BAD_VALUE;
932 }
933 return statusTFromBinderStatus(mModule->supportsVariableLatency(supports));
934 }
935
getSoundDoseInterface(const std::string & module,::ndk::SpAIBinder * soundDoseBinder)936 status_t DeviceHalAidl::getSoundDoseInterface(const std::string& module,
937 ::ndk::SpAIBinder* soundDoseBinder) {
938 if (soundDoseBinder == nullptr) {
939 return BAD_VALUE;
940 }
941 if (mSoundDose == nullptr) {
942 ALOGE("%s failed to retrieve the sound dose interface for module %s",
943 __func__, module.c_str());
944 return BAD_VALUE;
945 }
946
947 if (mSoundDose == nullptr) {
948 ALOGE("%s failed to return the sound dose interface for module %s: not implemented",
949 __func__,
950 module.c_str());
951 return NO_INIT;
952 }
953
954 *soundDoseBinder = mSoundDose->asBinder();
955 ALOGI("%s using audio AIDL HAL sound dose interface", __func__);
956 return OK;
957 }
958
prepareToDisconnectExternalDevice(const struct audio_port_v7 * port)959 status_t DeviceHalAidl::prepareToDisconnectExternalDevice(const struct audio_port_v7* port) {
960 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
961 TIME_CHECK();
962 if (mModule == nullptr) return NO_INIT;
963 if (port == nullptr) {
964 return BAD_VALUE;
965 }
966 const bool isInput = VALUE_OR_RETURN_STATUS(
967 ::aidl::android::portDirection(port->role, port->type)) ==
968 ::aidl::android::AudioPortDirection::INPUT;
969 AudioPort aidlPort = VALUE_OR_RETURN_STATUS(
970 ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
971 if (aidlPort.ext.getTag() != AudioPortExt::device) {
972 ALOGE("%s: provided port is not a device port (module %s): %s",
973 __func__, mInstance.c_str(), aidlPort.toString().c_str());
974 return BAD_VALUE;
975 }
976 status_t status = NO_ERROR;
977 {
978 std::lock_guard l(mLock);
979 status = mMapper.prepareToDisconnectExternalDevice(aidlPort);
980 }
981 if (status == UNKNOWN_TRANSACTION) {
982 // If there is not AIDL API defined for `prepareToDisconnectExternalDevice`.
983 // Call `setConnectedState` instead.
984 RETURN_STATUS_IF_ERROR(setConnectedState(port, false /*connected*/));
985 std::lock_guard l(mLock);
986 mDeviceDisconnectionNotified.insert(port->id);
987 // Return that there was no error as otherwise the disconnection procedure will not be
988 // considered complete for upper layers, and 'setConnectedState' will not be called again
989 return OK;
990 } else {
991 return status;
992 }
993 }
994
setConnectedState(const struct audio_port_v7 * port,bool connected)995 status_t DeviceHalAidl::setConnectedState(const struct audio_port_v7 *port, bool connected) {
996 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
997 TIME_CHECK();
998 if (mModule == nullptr) return NO_INIT;
999 if (port == nullptr) {
1000 return BAD_VALUE;
1001 }
1002 if (!connected) {
1003 std::lock_guard l(mLock);
1004 if (mDeviceDisconnectionNotified.erase(port->id) > 0) {
1005 // For device disconnection, APM will first call `prepareToDisconnectExternalDevice`
1006 // and then call `setConnectedState`. If `prepareToDisconnectExternalDevice` doesn't
1007 // exit, `setConnectedState` will be called when calling
1008 // `prepareToDisconnectExternalDevice`. Do not call to the HAL if previous call is
1009 // successful. Also remove the cache here to avoid a large cache after a long run.
1010 return OK;
1011 }
1012 }
1013 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(port->role, port->type)) ==
1014 ::aidl::android::AudioPortDirection::INPUT;
1015 AudioPort aidlPort = VALUE_OR_RETURN_STATUS(
1016 ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
1017 if (aidlPort.ext.getTag() != AudioPortExt::device) {
1018 ALOGE("%s: provided port is not a device port (module %s): %s",
1019 __func__, mInstance.c_str(), aidlPort.toString().c_str());
1020 return BAD_VALUE;
1021 }
1022 std::lock_guard l(mLock);
1023 return mMapper.setDevicePortConnectedState(aidlPort, connected);
1024 }
1025
setSimulateDeviceConnections(bool enabled)1026 status_t DeviceHalAidl::setSimulateDeviceConnections(bool enabled) {
1027 TIME_CHECK();
1028 if (mModule == nullptr) return NO_INIT;
1029 {
1030 std::lock_guard l(mLock);
1031 mMapper.resetUnusedPatchesAndPortConfigs();
1032 }
1033 ModuleDebug debug{ .simulateDeviceConnections = enabled };
1034 status_t status = statusTFromBinderStatus(mModule->setModuleDebug(debug));
1035 // This is important to log as it affects HAL behavior.
1036 if (status == OK) {
1037 ALOGI("%s: set enabled: %d", __func__, enabled);
1038 } else {
1039 ALOGW("%s: set enabled to %d failed: %d", __func__, enabled, status);
1040 }
1041 return status;
1042 }
1043
filterAndRetrieveBtA2dpParameters(AudioParameter & keys,AudioParameter * result)1044 status_t DeviceHalAidl::filterAndRetrieveBtA2dpParameters(
1045 AudioParameter &keys, AudioParameter *result) {
1046 if (String8 key = String8(AudioParameter::keyReconfigA2dpSupported); keys.containsKey(key)) {
1047 keys.remove(key);
1048 if (mBluetoothA2dp != nullptr) {
1049 bool supports;
1050 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
1051 mBluetoothA2dp->supportsOffloadReconfiguration(&supports)));
1052 result->addInt(key, supports ? 1 : 0);
1053 } else {
1054 ALOGI("%s: no IBluetoothA2dp on %s", __func__, mInstance.c_str());
1055 result->addInt(key, 0);
1056 }
1057 }
1058 return OK;
1059 }
1060
filterAndRetrieveBtLeParameters(AudioParameter & keys,AudioParameter * result)1061 status_t DeviceHalAidl::filterAndRetrieveBtLeParameters(
1062 AudioParameter &keys, AudioParameter *result) {
1063 if (String8 key = String8(AudioParameter::keyReconfigLeSupported); keys.containsKey(key)) {
1064 keys.remove(key);
1065 if (mBluetoothLe != nullptr) {
1066 bool supports;
1067 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
1068 mBluetoothLe->supportsOffloadReconfiguration(&supports)));
1069 result->addInt(key, supports ? 1 : 0);
1070 } else {
1071 ALOGI("%s: no mBluetoothLe on %s", __func__, mInstance.c_str());
1072 result->addInt(key, 0);
1073 }
1074 }
1075 return OK;
1076 }
1077
filterAndUpdateBtA2dpParameters(AudioParameter & parameters)1078 status_t DeviceHalAidl::filterAndUpdateBtA2dpParameters(AudioParameter ¶meters) {
1079 std::optional<bool> a2dpEnabled;
1080 std::optional<std::vector<VendorParameter>> reconfigureOffload;
1081 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1082 parameters, String8(AudioParameter::keyBtA2dpSuspended),
1083 [&a2dpEnabled](const String8& trueOrFalse) {
1084 if (trueOrFalse == AudioParameter::valueTrue) {
1085 a2dpEnabled = false; // 'suspended' == true
1086 return OK;
1087 } else if (trueOrFalse == AudioParameter::valueFalse) {
1088 a2dpEnabled = true; // 'suspended' == false
1089 return OK;
1090 }
1091 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1092 AudioParameter::keyBtA2dpSuspended, trueOrFalse.c_str());
1093 return BAD_VALUE;
1094 }));
1095 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1096 parameters, String8(AudioParameter::keyReconfigA2dp),
1097 [&](const String8& value) -> status_t {
1098 std::vector<VendorParameter> result;
1099 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
1100 mVendorExt->parseBluetoothA2dpReconfigureOffload(
1101 std::string(value.c_str()), &result)));
1102 reconfigureOffload = std::move(result);
1103 return OK;
1104 }));
1105 if (mBluetoothA2dp != nullptr && a2dpEnabled.has_value()) {
1106 return statusTFromBinderStatus(mBluetoothA2dp->setEnabled(a2dpEnabled.value()));
1107 }
1108 if (mBluetoothA2dp != nullptr && reconfigureOffload.has_value()) {
1109 return statusTFromBinderStatus(mBluetoothA2dp->reconfigureOffload(
1110 reconfigureOffload.value()));
1111 }
1112 return OK;
1113 }
1114
filterAndUpdateBtHfpParameters(AudioParameter & parameters)1115 status_t DeviceHalAidl::filterAndUpdateBtHfpParameters(AudioParameter ¶meters) {
1116 IBluetooth::HfpConfig hfpConfig;
1117 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1118 parameters, String8(AudioParameter::keyBtHfpEnable),
1119 [&hfpConfig](const String8& trueOrFalse) {
1120 if (trueOrFalse == AudioParameter::valueTrue) {
1121 hfpConfig.isEnabled = Boolean{ .value = true };
1122 return OK;
1123 } else if (trueOrFalse == AudioParameter::valueFalse) {
1124 hfpConfig.isEnabled = Boolean{ .value = false };
1125 return OK;
1126 }
1127 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1128 AudioParameter::keyBtHfpEnable, trueOrFalse.c_str());
1129 return BAD_VALUE;
1130 }));
1131 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
1132 parameters, String8(AudioParameter::keyBtHfpSamplingRate),
1133 [&hfpConfig](int sampleRate) {
1134 return sampleRate > 0 ?
1135 hfpConfig.sampleRate = Int{ .value = sampleRate }, OK : BAD_VALUE;
1136 }));
1137 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
1138 parameters, String8(AudioParameter::keyBtHfpVolume),
1139 [&hfpConfig](int volume0to15) {
1140 if (volume0to15 >= 0 && volume0to15 <= 15) {
1141 hfpConfig.volume = Float{ .value = volume0to15 / 15.0f };
1142 return OK;
1143 }
1144 return BAD_VALUE;
1145 }));
1146 if (mBluetooth != nullptr && hfpConfig != IBluetooth::HfpConfig{}) {
1147 IBluetooth::HfpConfig newHfpConfig;
1148 return statusTFromBinderStatus(mBluetooth->setHfpConfig(hfpConfig, &newHfpConfig));
1149 }
1150 return OK;
1151 }
1152
filterAndUpdateBtLeParameters(AudioParameter & parameters)1153 status_t DeviceHalAidl::filterAndUpdateBtLeParameters(AudioParameter ¶meters) {
1154 std::optional<bool> leEnabled;
1155 std::optional<std::vector<VendorParameter>> reconfigureOffload;
1156 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1157 parameters, String8(AudioParameter::keyBtLeSuspended),
1158 [&leEnabled](const String8& trueOrFalse) {
1159 if (trueOrFalse == AudioParameter::valueTrue) {
1160 leEnabled = false; // 'suspended' == true
1161 return OK;
1162 } else if (trueOrFalse == AudioParameter::valueFalse) {
1163 leEnabled = true; // 'suspended' == false
1164 return OK;
1165 }
1166 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1167 AudioParameter::keyBtLeSuspended, trueOrFalse.c_str());
1168 return BAD_VALUE;
1169 }));
1170 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1171 parameters, String8(AudioParameter::keyReconfigLe),
1172 [&](const String8& value) -> status_t {
1173 if (mVendorExt != nullptr) {
1174 std::vector<VendorParameter> result;
1175 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
1176 mVendorExt->parseBluetoothLeReconfigureOffload(
1177 std::string(value.c_str()), &result)));
1178 reconfigureOffload = std::move(result);
1179 } else {
1180 reconfigureOffload = std::vector<VendorParameter>();
1181 }
1182 return OK;
1183 }));
1184 if (mBluetoothLe != nullptr && leEnabled.has_value()) {
1185 return statusTFromBinderStatus(mBluetoothLe->setEnabled(leEnabled.value()));
1186 }
1187 if (mBluetoothLe != nullptr && reconfigureOffload.has_value()) {
1188 return statusTFromBinderStatus(mBluetoothLe->reconfigureOffload(
1189 reconfigureOffload.value()));
1190 }
1191 return OK;
1192 }
1193
filterAndUpdateBtScoParameters(AudioParameter & parameters)1194 status_t DeviceHalAidl::filterAndUpdateBtScoParameters(AudioParameter ¶meters) {
1195 IBluetooth::ScoConfig scoConfig;
1196 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1197 parameters, String8(AudioParameter::keyBtSco),
1198 [&scoConfig](const String8& onOrOff) {
1199 if (onOrOff == AudioParameter::valueOn) {
1200 scoConfig.isEnabled = Boolean{ .value = true };
1201 return OK;
1202 } else if (onOrOff == AudioParameter::valueOff) {
1203 scoConfig.isEnabled = Boolean{ .value = false };
1204 return OK;
1205 }
1206 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1207 AudioParameter::keyBtSco, onOrOff.c_str());
1208 return BAD_VALUE;
1209 }));
1210 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1211 parameters, String8(AudioParameter::keyBtScoHeadsetName),
1212 [&scoConfig](const String8& name) {
1213 scoConfig.debugName = name;
1214 return OK;
1215 }));
1216 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1217 parameters, String8(AudioParameter::keyBtNrec),
1218 [&scoConfig](const String8& onOrOff) {
1219 if (onOrOff == AudioParameter::valueOn) {
1220 scoConfig.isNrecEnabled = Boolean{ .value = true };
1221 return OK;
1222 } else if (onOrOff == AudioParameter::valueOff) {
1223 scoConfig.isNrecEnabled = Boolean{ .value = false };
1224 return OK;
1225 }
1226 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1227 AudioParameter::keyBtNrec, onOrOff.c_str());
1228 return BAD_VALUE;
1229 }));
1230 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1231 parameters, String8(AudioParameter::keyBtScoWb),
1232 [&scoConfig](const String8& onOrOff) {
1233 if (onOrOff == AudioParameter::valueOn) {
1234 scoConfig.mode = IBluetooth::ScoConfig::Mode::SCO_WB;
1235 return OK;
1236 } else if (onOrOff == AudioParameter::valueOff) {
1237 scoConfig.mode = IBluetooth::ScoConfig::Mode::SCO;
1238 return OK;
1239 }
1240 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1241 AudioParameter::keyBtScoWb, onOrOff.c_str());
1242 return BAD_VALUE;
1243 }));
1244 if (mBluetooth != nullptr && scoConfig != IBluetooth::ScoConfig{}) {
1245 IBluetooth::ScoConfig newScoConfig;
1246 return statusTFromBinderStatus(mBluetooth->setScoConfig(scoConfig, &newScoConfig));
1247 }
1248 return OK;
1249 }
1250
filterAndUpdateScreenParameters(AudioParameter & parameters)1251 status_t DeviceHalAidl::filterAndUpdateScreenParameters(AudioParameter ¶meters) {
1252 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1253 parameters, String8(AudioParameter::keyScreenState),
1254 [&](const String8& onOrOff) -> status_t {
1255 std::optional<bool> isTurnedOn;
1256 if (onOrOff == AudioParameter::valueOn) {
1257 isTurnedOn = true;
1258 } else if (onOrOff == AudioParameter::valueOff) {
1259 isTurnedOn = false;
1260 }
1261 if (!isTurnedOn.has_value()) {
1262 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1263 AudioParameter::keyScreenState, onOrOff.c_str());
1264 return BAD_VALUE;
1265 }
1266 return statusTFromBinderStatus(
1267 mModule->updateScreenState(isTurnedOn.value()));
1268 }));
1269 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
1270 parameters, String8(AudioParameter::keyScreenRotation),
1271 [&](int rotationDegrees) -> status_t {
1272 IModule::ScreenRotation rotation;
1273 switch (rotationDegrees) {
1274 case 0: rotation = IModule::ScreenRotation::DEG_0; break;
1275 case 90: rotation = IModule::ScreenRotation::DEG_90; break;
1276 case 180: rotation = IModule::ScreenRotation::DEG_180; break;
1277 case 270: rotation = IModule::ScreenRotation::DEG_270; break;
1278 default:
1279 ALOGE("setParameters: parameter key \"%s\" has invalid value %d",
1280 AudioParameter::keyScreenRotation, rotationDegrees);
1281 return BAD_VALUE;
1282 }
1283 return statusTFromBinderStatus(mModule->updateScreenRotation(rotation));
1284 }));
1285 return OK;
1286 }
1287
filterAndUpdateTelephonyParameters(AudioParameter & parameters)1288 status_t DeviceHalAidl::filterAndUpdateTelephonyParameters(AudioParameter ¶meters) {
1289 using TtyMode = ITelephony::TelecomConfig::TtyMode;
1290 ITelephony::TelecomConfig telConfig;
1291 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1292 parameters, String8(AudioParameter::keyTtyMode),
1293 [&telConfig](const String8& mode) {
1294 if (mode == AudioParameter::valueTtyModeOff) {
1295 telConfig.ttyMode = TtyMode::OFF;
1296 return OK;
1297 } else if (mode == AudioParameter::valueTtyModeFull) {
1298 telConfig.ttyMode = TtyMode::FULL;
1299 return OK;
1300 } else if (mode == AudioParameter::valueTtyModeHco) {
1301 telConfig.ttyMode = TtyMode::HCO;
1302 return OK;
1303 } else if (mode == AudioParameter::valueTtyModeVco) {
1304 telConfig.ttyMode = TtyMode::VCO;
1305 return OK;
1306 }
1307 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1308 AudioParameter::keyTtyMode, mode.c_str());
1309 return BAD_VALUE;
1310 }));
1311 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1312 parameters, String8(AudioParameter::keyHacSetting),
1313 [&telConfig](const String8& onOrOff) {
1314 if (onOrOff == AudioParameter::valueHacOn) {
1315 telConfig.isHacEnabled = Boolean{ .value = true };
1316 return OK;
1317 } else if (onOrOff == AudioParameter::valueHacOff) {
1318 telConfig.isHacEnabled = Boolean{ .value = false };
1319 return OK;
1320 }
1321 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1322 AudioParameter::keyHacSetting, onOrOff.c_str());
1323 return BAD_VALUE;
1324 }));
1325 if (mTelephony != nullptr && telConfig != ITelephony::TelecomConfig{}) {
1326 ITelephony::TelecomConfig newTelConfig;
1327 return statusTFromBinderStatus(
1328 mTelephony->setTelecomConfig(telConfig, &newTelConfig));
1329 }
1330 return OK;
1331 }
1332
clearCallbacks(void * cookie)1333 void DeviceHalAidl::clearCallbacks(void* cookie) {
1334 std::lock_guard l(mLock);
1335 mCallbacks.erase(cookie);
1336 }
1337
getStreamOutCallback(void * cookie)1338 sp<StreamOutHalInterfaceCallback> DeviceHalAidl::getStreamOutCallback(void* cookie) {
1339 return getCallbackImpl(cookie, &Callbacks::out);
1340 }
1341
setStreamOutCallback(void * cookie,const sp<StreamOutHalInterfaceCallback> & cb)1342 void DeviceHalAidl::setStreamOutCallback(
1343 void* cookie, const sp<StreamOutHalInterfaceCallback>& cb) {
1344 setCallbackImpl(cookie, &Callbacks::out, cb);
1345 }
1346
getStreamOutEventCallback(void * cookie)1347 sp<StreamOutHalInterfaceEventCallback> DeviceHalAidl::getStreamOutEventCallback(
1348 void* cookie) {
1349 return getCallbackImpl(cookie, &Callbacks::event);
1350 }
1351
setStreamOutEventCallback(void * cookie,const sp<StreamOutHalInterfaceEventCallback> & cb)1352 void DeviceHalAidl::setStreamOutEventCallback(
1353 void* cookie, const sp<StreamOutHalInterfaceEventCallback>& cb) {
1354 setCallbackImpl(cookie, &Callbacks::event, cb);
1355 }
1356
getStreamOutLatencyModeCallback(void * cookie)1357 sp<StreamOutHalInterfaceLatencyModeCallback> DeviceHalAidl::getStreamOutLatencyModeCallback(
1358 void* cookie) {
1359 return getCallbackImpl(cookie, &Callbacks::latency);
1360 }
1361
setStreamOutLatencyModeCallback(void * cookie,const sp<StreamOutHalInterfaceLatencyModeCallback> & cb)1362 void DeviceHalAidl::setStreamOutLatencyModeCallback(
1363 void* cookie, const sp<StreamOutHalInterfaceLatencyModeCallback>& cb) {
1364 setCallbackImpl(cookie, &Callbacks::latency, cb);
1365 }
1366
1367 template<class C>
getCallbackImpl(void * cookie,wp<C> DeviceHalAidl::Callbacks::* field)1368 sp<C> DeviceHalAidl::getCallbackImpl(void* cookie, wp<C> DeviceHalAidl::Callbacks::* field) {
1369 std::lock_guard l(mLock);
1370 if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
1371 return ((it->second).*field).promote();
1372 }
1373 return nullptr;
1374 }
1375 template<class C>
setCallbackImpl(void * cookie,wp<C> DeviceHalAidl::Callbacks::* field,const sp<C> & cb)1376 void DeviceHalAidl::setCallbackImpl(
1377 void* cookie, wp<C> DeviceHalAidl::Callbacks::* field, const sp<C>& cb) {
1378 std::lock_guard l(mLock);
1379 if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
1380 (it->second).*field = cb;
1381 }
1382 }
1383
1384 } // namespace android
1385