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 ¶meters) {
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 ¶meters) {
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 ¶meters) {
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 ¶meters) {
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 ¶meters) {
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 ¶meters) {
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