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