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