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