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 &parameters) {
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 &parameters) {
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 &parameters) {
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 &parameters) {
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 &parameters) {
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 &parameters) {
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