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 #include <forward_list>
22
23 #include <aidl/android/hardware/audio/core/BnStreamCallback.h>
24 #include <aidl/android/hardware/audio/core/BnStreamOutEventCallback.h>
25 #include <aidl/android/hardware/audio/core/StreamDescriptor.h>
26 #include <error/expected_utils.h>
27 #include <media/AidlConversionCppNdk.h>
28 #include <media/AidlConversionNdkCpp.h>
29 #include <media/AidlConversionUtil.h>
30 #include <mediautils/TimeCheck.h>
31 #include <Utils.h>
32 #include <utils/Log.h>
33
34 #include "DeviceHalAidl.h"
35 #include "EffectHalAidl.h"
36 #include "StreamHalAidl.h"
37
38 using aidl::android::aidl_utils::statusTFromBinderStatus;
39 using aidl::android::media::audio::common::Boolean;
40 using aidl::android::media::audio::common::AudioChannelLayout;
41 using aidl::android::media::audio::common::AudioConfig;
42 using aidl::android::media::audio::common::AudioDevice;
43 using aidl::android::media::audio::common::AudioDeviceAddress;
44 using aidl::android::media::audio::common::AudioDeviceType;
45 using aidl::android::media::audio::common::AudioFormatDescription;
46 using aidl::android::media::audio::common::AudioFormatType;
47 using aidl::android::media::audio::common::AudioInputFlags;
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::AudioPortDeviceExt;
58 using aidl::android::media::audio::common::AudioPortExt;
59 using aidl::android::media::audio::common::AudioPortMixExt;
60 using aidl::android::media::audio::common::AudioPortMixExtUseCase;
61 using aidl::android::media::audio::common::AudioProfile;
62 using aidl::android::media::audio::common::AudioSource;
63 using aidl::android::media::audio::common::Float;
64 using aidl::android::media::audio::common::Int;
65 using aidl::android::media::audio::common::MicrophoneDynamicInfo;
66 using aidl::android::media::audio::common::MicrophoneInfo;
67 using aidl::android::media::audio::IHalAdapterVendorExtension;
68 using aidl::android::hardware::audio::common::getFrameSizeInBytes;
69 using aidl::android::hardware::audio::common::isBitPositionFlagSet;
70 using aidl::android::hardware::audio::common::isDefaultAudioFormat;
71 using aidl::android::hardware::audio::common::makeBitPositionFlagMask;
72 using aidl::android::hardware::audio::common::RecordTrackMetadata;
73 using aidl::android::hardware::audio::core::AudioPatch;
74 using aidl::android::hardware::audio::core::AudioRoute;
75 using aidl::android::hardware::audio::core::IBluetooth;
76 using aidl::android::hardware::audio::core::IBluetoothA2dp;
77 using aidl::android::hardware::audio::core::IBluetoothLe;
78 using aidl::android::hardware::audio::core::IModule;
79 using aidl::android::hardware::audio::core::ITelephony;
80 using aidl::android::hardware::audio::core::ModuleDebug;
81 using aidl::android::hardware::audio::core::StreamDescriptor;
82 using aidl::android::hardware::audio::core::VendorParameter;
83
84 namespace android {
85
86 namespace {
87
isConfigEqualToPortConfig(const AudioConfig & config,const AudioPortConfig & portConfig)88 bool isConfigEqualToPortConfig(const AudioConfig& config, const AudioPortConfig& portConfig) {
89 return portConfig.sampleRate.value().value == config.base.sampleRate &&
90 portConfig.channelMask.value() == config.base.channelMask &&
91 portConfig.format.value() == config.base.format;
92 }
93
setConfigFromPortConfig(AudioConfig * config,const AudioPortConfig & portConfig)94 void setConfigFromPortConfig(AudioConfig* config, const AudioPortConfig& portConfig) {
95 config->base.sampleRate = portConfig.sampleRate.value().value;
96 config->base.channelMask = portConfig.channelMask.value();
97 config->base.format = portConfig.format.value();
98 }
99
setPortConfigFromConfig(AudioPortConfig * portConfig,const AudioConfig & config)100 void setPortConfigFromConfig(AudioPortConfig* portConfig, const AudioConfig& config) {
101 if (config.base.sampleRate != 0) {
102 portConfig->sampleRate = Int{ .value = config.base.sampleRate };
103 }
104 if (config.base.channelMask != AudioChannelLayout{}) {
105 portConfig->channelMask = config.base.channelMask;
106 }
107 if (config.base.format != AudioFormatDescription{}) {
108 portConfig->format = config.base.format;
109 }
110 }
111
112 // Note: these converters are for types defined in different AIDL files. Although these
113 // AIDL files are copies of each other, however formally these are different types
114 // thus we don't use a conversion via a parcelable.
ndk2cpp_AudioRoute(const AudioRoute & ndk)115 ConversionResult<media::AudioRoute> ndk2cpp_AudioRoute(const AudioRoute& ndk) {
116 media::AudioRoute cpp;
117 cpp.sourcePortIds.insert(
118 cpp.sourcePortIds.end(), ndk.sourcePortIds.begin(), ndk.sourcePortIds.end());
119 cpp.sinkPortId = ndk.sinkPortId;
120 cpp.isExclusive = ndk.isExclusive;
121 return cpp;
122 }
123
124 template<typename T>
retrieveSubInterface(const std::shared_ptr<IModule> & module,::ndk::ScopedAStatus (IModule::* getT)(std::shared_ptr<T> *))125 std::shared_ptr<T> retrieveSubInterface(const std::shared_ptr<IModule>& module,
126 ::ndk::ScopedAStatus (IModule::*getT)(std::shared_ptr<T>*)) {
127 if (module != nullptr) {
128 std::shared_ptr<T> instance;
129 if (auto status = (module.get()->*getT)(&instance); status.isOk()) {
130 return instance;
131 }
132 }
133 return nullptr;
134 }
135
136 } // namespace
137
DeviceHalAidl(const std::string & instance,const std::shared_ptr<IModule> & module,const std::shared_ptr<IHalAdapterVendorExtension> & vext)138 DeviceHalAidl::DeviceHalAidl(const std::string& instance, const std::shared_ptr<IModule>& module,
139 const std::shared_ptr<IHalAdapterVendorExtension>& vext)
140 : ConversionHelperAidl("DeviceHalAidl"),
141 mInstance(instance), mModule(module), mVendorExt(vext),
142 mTelephony(retrieveSubInterface<ITelephony>(module, &IModule::getTelephony)),
143 mBluetooth(retrieveSubInterface<IBluetooth>(module, &IModule::getBluetooth)),
144 mBluetoothA2dp(retrieveSubInterface<IBluetoothA2dp>(module, &IModule::getBluetoothA2dp)),
145 mBluetoothLe(retrieveSubInterface<IBluetoothLe>(module, &IModule::getBluetoothLe)) {
146 }
147
getAudioPorts(std::vector<media::audio::common::AudioPort> * ports)148 status_t DeviceHalAidl::getAudioPorts(std::vector<media::audio::common::AudioPort> *ports) {
149 return ::aidl::android::convertContainer(mPorts, ports,
150 [](const Ports::value_type& pair) { return ndk2cpp_AudioPort(pair.second); });
151 }
152
getAudioRoutes(std::vector<media::AudioRoute> * routes)153 status_t DeviceHalAidl::getAudioRoutes(std::vector<media::AudioRoute> *routes) {
154 *routes = VALUE_OR_RETURN_STATUS(
155 ::aidl::android::convertContainer<std::vector<media::AudioRoute>>(
156 mRoutes, ndk2cpp_AudioRoute));
157 return OK;
158 }
159
getSupportedModes(std::vector<media::audio::common::AudioMode> * modes)160 status_t DeviceHalAidl::getSupportedModes(std::vector<media::audio::common::AudioMode> *modes) {
161 TIME_CHECK();
162 if (modes == nullptr) {
163 return BAD_VALUE;
164 }
165 if (mModule == nullptr) return NO_INIT;
166 if (mTelephony == nullptr) return INVALID_OPERATION;
167 std::vector<AudioMode> aidlModes;
168 RETURN_STATUS_IF_ERROR(
169 statusTFromBinderStatus(mTelephony->getSupportedAudioModes(&aidlModes)));
170 *modes = VALUE_OR_RETURN_STATUS(
171 ::aidl::android::convertContainer<std::vector<media::audio::common::AudioMode>>(
172 aidlModes, ndk2cpp_AudioMode));
173 return OK;
174 }
175
getSupportedDevices(uint32_t *)176 status_t DeviceHalAidl::getSupportedDevices(uint32_t*) {
177 // Obsolete.
178 return INVALID_OPERATION;
179 }
180
initCheck()181 status_t DeviceHalAidl::initCheck() {
182 TIME_CHECK();
183 if (mModule == nullptr) return NO_INIT;
184 std::vector<AudioPort> ports;
185 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->getAudioPorts(&ports)));
186 ALOGW_IF(ports.empty(), "%s: module %s returned an empty list of audio ports",
187 __func__, mInstance.c_str());
188 std::transform(ports.begin(), ports.end(), std::inserter(mPorts, mPorts.end()),
189 [](const auto& p) { return std::make_pair(p.id, p); });
190 mDefaultInputPortId = mDefaultOutputPortId = -1;
191 const int defaultDeviceFlag = 1 << AudioPortDeviceExt::FLAG_INDEX_DEFAULT_DEVICE;
192 for (const auto& pair : mPorts) {
193 const auto& p = pair.second;
194 if (p.ext.getTag() == AudioPortExt::Tag::device &&
195 (p.ext.get<AudioPortExt::Tag::device>().flags & defaultDeviceFlag) != 0) {
196 if (p.flags.getTag() == AudioIoFlags::Tag::input) {
197 mDefaultInputPortId = p.id;
198 } else if (p.flags.getTag() == AudioIoFlags::Tag::output) {
199 mDefaultOutputPortId = p.id;
200 }
201 }
202 }
203 ALOGI("%s: module %s default port ids: input %d, output %d",
204 __func__, mInstance.c_str(), mDefaultInputPortId, mDefaultOutputPortId);
205 RETURN_STATUS_IF_ERROR(updateRoutes());
206 std::vector<AudioPortConfig> portConfigs;
207 RETURN_STATUS_IF_ERROR(
208 statusTFromBinderStatus(mModule->getAudioPortConfigs(&portConfigs))); // OK if empty
209 std::transform(portConfigs.begin(), portConfigs.end(),
210 std::inserter(mPortConfigs, mPortConfigs.end()),
211 [](const auto& p) { return std::make_pair(p.id, p); });
212 std::transform(mPortConfigs.begin(), mPortConfigs.end(),
213 std::inserter(mInitialPortConfigIds, mInitialPortConfigIds.end()),
214 [](const auto& pcPair) { return pcPair.first; });
215 std::vector<AudioPatch> patches;
216 RETURN_STATUS_IF_ERROR(
217 statusTFromBinderStatus(mModule->getAudioPatches(&patches))); // OK if empty
218 std::transform(patches.begin(), patches.end(),
219 std::inserter(mPatches, mPatches.end()),
220 [](const auto& p) { return std::make_pair(p.id, p); });
221 return OK;
222 }
223
setVoiceVolume(float volume)224 status_t DeviceHalAidl::setVoiceVolume(float volume) {
225 TIME_CHECK();
226 if (!mModule) return NO_INIT;
227 if (mTelephony == nullptr) return INVALID_OPERATION;
228 ITelephony::TelecomConfig inConfig{ .voiceVolume = Float{volume} }, outConfig;
229 RETURN_STATUS_IF_ERROR(
230 statusTFromBinderStatus(mTelephony->setTelecomConfig(inConfig, &outConfig)));
231 ALOGW_IF(outConfig.voiceVolume.has_value() && volume != outConfig.voiceVolume.value().value,
232 "%s: the resulting voice volume %f is not the same as requested %f",
233 __func__, outConfig.voiceVolume.value().value, volume);
234 return OK;
235 }
236
setMasterVolume(float volume)237 status_t DeviceHalAidl::setMasterVolume(float volume) {
238 TIME_CHECK();
239 if (!mModule) return NO_INIT;
240 return statusTFromBinderStatus(mModule->setMasterVolume(volume));
241 }
242
getMasterVolume(float * volume)243 status_t DeviceHalAidl::getMasterVolume(float *volume) {
244 TIME_CHECK();
245 if (!mModule) return NO_INIT;
246 return statusTFromBinderStatus(mModule->getMasterVolume(volume));
247 }
248
setMode(audio_mode_t mode)249 status_t DeviceHalAidl::setMode(audio_mode_t mode) {
250 TIME_CHECK();
251 if (!mModule) return NO_INIT;
252 AudioMode audioMode = VALUE_OR_FATAL(::aidl::android::legacy2aidl_audio_mode_t_AudioMode(mode));
253 if (mTelephony != nullptr) {
254 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mTelephony->switchAudioMode(audioMode)));
255 }
256 return statusTFromBinderStatus(mModule->updateAudioMode(audioMode));
257 }
258
setMicMute(bool state)259 status_t DeviceHalAidl::setMicMute(bool state) {
260 TIME_CHECK();
261 if (!mModule) return NO_INIT;
262 return statusTFromBinderStatus(mModule->setMicMute(state));
263 }
264
getMicMute(bool * state)265 status_t DeviceHalAidl::getMicMute(bool *state) {
266 TIME_CHECK();
267 if (!mModule) return NO_INIT;
268 return statusTFromBinderStatus(mModule->getMicMute(state));
269 }
270
setMasterMute(bool state)271 status_t DeviceHalAidl::setMasterMute(bool state) {
272 TIME_CHECK();
273 if (!mModule) return NO_INIT;
274 return statusTFromBinderStatus(mModule->setMasterMute(state));
275 }
276
getMasterMute(bool * state)277 status_t DeviceHalAidl::getMasterMute(bool *state) {
278 TIME_CHECK();
279 if (!mModule) return NO_INIT;
280 return statusTFromBinderStatus(mModule->getMasterMute(state));
281 }
282
setParameters(const String8 & kvPairs)283 status_t DeviceHalAidl::setParameters(const String8& kvPairs) {
284 if (!mModule) return NO_INIT;
285 AudioParameter parameters(kvPairs);
286 ALOGD("%s: parameters: \"%s\"", __func__, parameters.toString().c_str());
287
288 if (status_t status = filterAndUpdateBtA2dpParameters(parameters); status != OK) {
289 ALOGW("%s: filtering or updating BT A2DP parameters failed: %d", __func__, status);
290 }
291 if (status_t status = filterAndUpdateBtHfpParameters(parameters); status != OK) {
292 ALOGW("%s: filtering or updating BT HFP parameters failed: %d", __func__, status);
293 }
294 if (status_t status = filterAndUpdateBtLeParameters(parameters); status != OK) {
295 ALOGW("%s: filtering or updating BT LE parameters failed: %d", __func__, status);
296 }
297 if (status_t status = filterAndUpdateBtScoParameters(parameters); status != OK) {
298 ALOGW("%s: filtering or updating BT SCO parameters failed: %d", __func__, status);
299 }
300 if (status_t status = filterAndUpdateScreenParameters(parameters); status != OK) {
301 ALOGW("%s: filtering or updating screen parameters failed: %d", __func__, status);
302 }
303 if (status_t status = filterAndUpdateTelephonyParameters(parameters); status != OK) {
304 ALOGW("%s: filtering or updating telephony parameters failed: %d", __func__, status);
305 }
306 return parseAndSetVendorParameters(mVendorExt, mModule, parameters);
307 }
308
getParameters(const String8 & keys,String8 * values)309 status_t DeviceHalAidl::getParameters(const String8& keys, String8 *values) {
310 TIME_CHECK();
311 if (!mModule) return NO_INIT;
312 if (values == nullptr) {
313 return BAD_VALUE;
314 }
315 AudioParameter parameterKeys(keys), result;
316 if (status_t status = filterAndRetrieveBtA2dpParameters(parameterKeys, &result); status != OK) {
317 ALOGW("%s: filtering or retrieving BT A2DP parameters failed: %d", __func__, status);
318 }
319 *values = result.toString();
320 return parseAndGetVendorParameters(mVendorExt, mModule, parameterKeys, values);
321 }
322
323 namespace {
324
325 class Cleanup {
326 public:
327 typedef void (DeviceHalAidl::*Cleaner)(int32_t);
328
Cleanup(DeviceHalAidl * device,Cleaner cleaner,int32_t id)329 Cleanup(DeviceHalAidl* device, Cleaner cleaner, int32_t id) :
330 mDevice(device), mCleaner(cleaner), mId(id) {}
~Cleanup()331 ~Cleanup() { clean(); }
clean()332 void clean() {
333 if (mDevice != nullptr) (mDevice->*mCleaner)(mId);
334 disarm();
335 }
disarm()336 void disarm() { mDevice = nullptr; }
337
338 private:
339 DeviceHalAidl* mDevice;
340 const Cleaner mCleaner;
341 const int32_t mId;
342 };
343
344 } // namespace
345
346 // Since the order of container elements destruction is unspecified,
347 // ensure that cleanups are performed from the most recent one and upwards.
348 // This is the same as if there were individual Cleanup instances on the stack,
349 // however the bonus is that we can disarm all of them with just one statement.
350 class DeviceHalAidl::Cleanups : public std::forward_list<Cleanup> {
351 public:
~Cleanups()352 ~Cleanups() { for (auto& c : *this) c.clean(); }
disarmAll()353 void disarmAll() { for (auto& c : *this) c.disarm(); }
354 };
355
getInputBufferSize(const struct audio_config * config,size_t * size)356 status_t DeviceHalAidl::getInputBufferSize(const struct audio_config* config, size_t* size) {
357 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
358 if (size == nullptr) return BAD_VALUE;
359 TIME_CHECK();
360 if (!mModule) return NO_INIT;
361 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
362 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, true /*isInput*/));
363 AudioDevice aidlDevice;
364 aidlDevice.type.type = AudioDeviceType::IN_DEFAULT;
365 AudioSource aidlSource = AudioSource::DEFAULT;
366 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::input>(0);
367 AudioPortConfig mixPortConfig;
368 Cleanups cleanups;
369 audio_config writableConfig = *config;
370 AudioPatch aidlPatch;
371 RETURN_STATUS_IF_ERROR(prepareToOpenStream(0 /*handle*/, aidlDevice, aidlFlags, aidlSource,
372 &writableConfig, &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
373 *size = aidlConfig.frameCount *
374 getFrameSizeInBytes(aidlConfig.base.format, aidlConfig.base.channelMask);
375 // Do not disarm cleanups to release temporary port configs.
376 return OK;
377 }
378
prepareToOpenStream(int32_t aidlHandle,const AudioDevice & aidlDevice,const AudioIoFlags & aidlFlags,AudioSource aidlSource,struct audio_config * config,Cleanups * cleanups,AudioConfig * aidlConfig,AudioPortConfig * mixPortConfig,AudioPatch * aidlPatch)379 status_t DeviceHalAidl::prepareToOpenStream(
380 int32_t aidlHandle, const AudioDevice& aidlDevice, const AudioIoFlags& aidlFlags,
381 AudioSource aidlSource, struct audio_config* config,
382 Cleanups* cleanups, AudioConfig* aidlConfig, AudioPortConfig* mixPortConfig,
383 AudioPatch* aidlPatch) {
384 ALOGD("%p %s::%s: handle %d, device %s, flags %s, source %s, config %s, mix port config %s",
385 this, getClassName().c_str(), __func__, aidlHandle, aidlDevice.toString().c_str(),
386 aidlFlags.toString().c_str(), toString(aidlSource).c_str(),
387 aidlConfig->toString().c_str(), mixPortConfig->toString().c_str());
388 resetUnusedPatchesAndPortConfigs();
389 const bool isInput = aidlFlags.getTag() == AudioIoFlags::Tag::input;
390 // Find / create AudioPortConfigs for the device port and the mix port,
391 // then find / create a patch between them, and open a stream on the mix port.
392 AudioPortConfig devicePortConfig;
393 bool created = false;
394 RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(aidlDevice, aidlConfig,
395 &devicePortConfig, &created));
396 if (created) {
397 cleanups->emplace_front(this, &DeviceHalAidl::resetPortConfig, devicePortConfig.id);
398 }
399 RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(*aidlConfig, aidlFlags, aidlHandle, aidlSource,
400 std::set<int32_t>{devicePortConfig.portId}, mixPortConfig, &created));
401 if (created) {
402 cleanups->emplace_front(this, &DeviceHalAidl::resetPortConfig, mixPortConfig->id);
403 }
404 setConfigFromPortConfig(aidlConfig, *mixPortConfig);
405 if (isInput) {
406 RETURN_STATUS_IF_ERROR(findOrCreatePatch(
407 {devicePortConfig.id}, {mixPortConfig->id}, aidlPatch, &created));
408 } else {
409 RETURN_STATUS_IF_ERROR(findOrCreatePatch(
410 {mixPortConfig->id}, {devicePortConfig.id}, aidlPatch, &created));
411 }
412 if (created) {
413 cleanups->emplace_front(this, &DeviceHalAidl::resetPatch, aidlPatch->id);
414 }
415 if (aidlConfig->frameCount <= 0) {
416 aidlConfig->frameCount = aidlPatch->minimumStreamBufferSizeFrames;
417 }
418 *config = VALUE_OR_RETURN_STATUS(
419 ::aidl::android::aidl2legacy_AudioConfig_audio_config_t(*aidlConfig, isInput));
420 return OK;
421 }
422
423 namespace {
424
425 class StreamCallbackBase {
426 protected:
StreamCallbackBase(const sp<CallbackBroker> & broker)427 explicit StreamCallbackBase(const sp<CallbackBroker>& broker) : mBroker(broker) {}
428 public:
getCookie() const429 void* getCookie() const { return mCookie; }
setCookie(void * cookie)430 void setCookie(void* cookie) { mCookie = cookie; }
getBroker() const431 sp<CallbackBroker> getBroker() const {
432 if (void* cookie = mCookie; cookie != nullptr) return mBroker.promote();
433 return nullptr;
434 }
435 private:
436 const wp<CallbackBroker> mBroker;
437 std::atomic<void*> mCookie;
438 };
439
440 template<class C>
441 class StreamCallbackBaseHelper {
442 protected:
StreamCallbackBaseHelper(const StreamCallbackBase & base)443 explicit StreamCallbackBaseHelper(const StreamCallbackBase& base) : mBase(base) {}
444 sp<C> getCb(const sp<CallbackBroker>& broker, void* cookie);
445 using CbRef = const sp<C>&;
runCb(const std::function<void (CbRef cb)> & f)446 ndk::ScopedAStatus runCb(const std::function<void(CbRef cb)>& f) {
447 if (auto cb = getCb(mBase.getBroker(), mBase.getCookie()); cb != nullptr) f(cb);
448 return ndk::ScopedAStatus::ok();
449 }
450 private:
451 const StreamCallbackBase& mBase;
452 };
453
454 template<>
getCb(const sp<CallbackBroker> & broker,void * cookie)455 sp<StreamOutHalInterfaceCallback> StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>::getCb(
456 const sp<CallbackBroker>& broker, void* cookie) {
457 if (broker != nullptr) return broker->getStreamOutCallback(cookie);
458 return nullptr;
459 }
460
461 template<>
462 sp<StreamOutHalInterfaceEventCallback>
getCb(const sp<CallbackBroker> & broker,void * cookie)463 StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>::getCb(
464 const sp<CallbackBroker>& broker, void* cookie) {
465 if (broker != nullptr) return broker->getStreamOutEventCallback(cookie);
466 return nullptr;
467 }
468
469 template<>
470 sp<StreamOutHalInterfaceLatencyModeCallback>
getCb(const sp<CallbackBroker> & broker,void * cookie)471 StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>::getCb(
472 const sp<CallbackBroker>& broker, void* cookie) {
473 if (broker != nullptr) return broker->getStreamOutLatencyModeCallback(cookie);
474 return nullptr;
475 }
476
477 /*
478 Note on the callback ownership.
479
480 In the Binder ownership model, the server implementation is kept alive
481 as long as there is any client (proxy object) alive. This is done by
482 incrementing the refcount of the server-side object by the Binder framework.
483 When it detects that the last client is gone, it decrements the refcount back.
484
485 Thus, it is not needed to keep any references to StreamCallback on our
486 side (after we have sent an instance to the client), because we are
487 the server-side. The callback object will be kept alive as long as the HAL server
488 holds a strong ref to IStreamCallback proxy.
489 */
490
491 class OutputStreamCallbackAidl : public StreamCallbackBase,
492 public StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>,
493 public ::aidl::android::hardware::audio::core::BnStreamCallback {
494 public:
OutputStreamCallbackAidl(const sp<CallbackBroker> & broker)495 explicit OutputStreamCallbackAidl(const sp<CallbackBroker>& broker)
496 : StreamCallbackBase(broker),
497 StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>(
498 *static_cast<StreamCallbackBase*>(this)) {}
onTransferReady()499 ndk::ScopedAStatus onTransferReady() override {
500 return runCb([](CbRef cb) { cb->onWriteReady(); });
501 }
onError()502 ndk::ScopedAStatus onError() override {
503 return runCb([](CbRef cb) { cb->onError(); });
504 }
onDrainReady()505 ndk::ScopedAStatus onDrainReady() override {
506 return runCb([](CbRef cb) { cb->onDrainReady(); });
507 }
508 };
509
510 class OutputStreamEventCallbackAidl :
511 public StreamCallbackBase,
512 public StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>,
513 public StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>,
514 public ::aidl::android::hardware::audio::core::BnStreamOutEventCallback {
515 public:
OutputStreamEventCallbackAidl(const sp<CallbackBroker> & broker)516 explicit OutputStreamEventCallbackAidl(const sp<CallbackBroker>& broker)
517 : StreamCallbackBase(broker),
518 StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>(
519 *static_cast<StreamCallbackBase*>(this)),
520 StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>(
521 *static_cast<StreamCallbackBase*>(this)) {}
onCodecFormatChanged(const std::vector<uint8_t> & in_audioMetadata)522 ndk::ScopedAStatus onCodecFormatChanged(const std::vector<uint8_t>& in_audioMetadata) override {
523 std::basic_string<uint8_t> halMetadata(in_audioMetadata.begin(), in_audioMetadata.end());
524 return StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>::runCb(
525 [&halMetadata](auto cb) { cb->onCodecFormatChanged(halMetadata); });
526 }
onRecommendedLatencyModeChanged(const std::vector<AudioLatencyMode> & in_modes)527 ndk::ScopedAStatus onRecommendedLatencyModeChanged(
528 const std::vector<AudioLatencyMode>& in_modes) override {
529 auto halModes = VALUE_OR_FATAL(
530 ::aidl::android::convertContainer<std::vector<audio_latency_mode_t>>(
531 in_modes,
532 ::aidl::android::aidl2legacy_AudioLatencyMode_audio_latency_mode_t));
533 return StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>::runCb(
534 [&halModes](auto cb) { cb->onRecommendedLatencyModeChanged(halModes); });
535 }
536 };
537
538 } // namespace
539
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)540 status_t DeviceHalAidl::openOutputStream(
541 audio_io_handle_t handle, audio_devices_t devices,
542 audio_output_flags_t flags, struct audio_config* config,
543 const char* address,
544 sp<StreamOutHalInterface>* outStream) {
545 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
546 if (!outStream || !config) {
547 return BAD_VALUE;
548 }
549 TIME_CHECK();
550 if (!mModule) return NO_INIT;
551 int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
552 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(handle));
553 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
554 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, false /*isInput*/));
555 AudioDevice aidlDevice = VALUE_OR_RETURN_STATUS(
556 ::aidl::android::legacy2aidl_audio_device_AudioDevice(devices, address));
557 int32_t aidlOutputFlags = VALUE_OR_RETURN_STATUS(
558 ::aidl::android::legacy2aidl_audio_output_flags_t_int32_t_mask(flags));
559 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::output>(aidlOutputFlags);
560 AudioPortConfig mixPortConfig;
561 Cleanups cleanups;
562 AudioPatch aidlPatch;
563 RETURN_STATUS_IF_ERROR(prepareToOpenStream(aidlHandle, aidlDevice, aidlFlags,
564 AudioSource::SYS_RESERVED_INVALID /*only needed for input*/,
565 config, &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
566 ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamArguments args;
567 args.portConfigId = mixPortConfig.id;
568 const bool isOffload = isBitPositionFlagSet(
569 aidlOutputFlags, AudioOutputFlags::COMPRESS_OFFLOAD);
570 std::shared_ptr<OutputStreamCallbackAidl> streamCb;
571 if (isOffload) {
572 streamCb = ndk::SharedRefBase::make<OutputStreamCallbackAidl>(this);
573 }
574 auto eventCb = ndk::SharedRefBase::make<OutputStreamEventCallbackAidl>(this);
575 if (isOffload) {
576 args.offloadInfo = aidlConfig.offloadInfo;
577 args.callback = streamCb;
578 }
579 args.bufferSizeFrames = aidlConfig.frameCount;
580 args.eventCallback = eventCb;
581 ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamReturn ret;
582 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openOutputStream(args, &ret)));
583 StreamContextAidl context(ret.desc, isOffload);
584 if (!context.isValid()) {
585 ALOGE("%s: Failed to created a valid stream context from the descriptor: %s",
586 __func__, ret.desc.toString().c_str());
587 return NO_INIT;
588 }
589 *outStream = sp<StreamOutHalAidl>::make(*config, std::move(context), aidlPatch.latenciesMs[0],
590 std::move(ret.stream), mVendorExt, this /*callbackBroker*/);
591 mStreams.insert(std::pair(*outStream, aidlPatch.id));
592 void* cbCookie = (*outStream).get();
593 {
594 std::lock_guard l(mLock);
595 mCallbacks.emplace(cbCookie, Callbacks{});
596 }
597 if (streamCb) streamCb->setCookie(cbCookie);
598 eventCb->setCookie(cbCookie);
599 cleanups.disarmAll();
600 return OK;
601 }
602
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)603 status_t DeviceHalAidl::openInputStream(
604 audio_io_handle_t handle, audio_devices_t devices,
605 struct audio_config* config, audio_input_flags_t flags,
606 const char* address, audio_source_t source,
607 audio_devices_t outputDevice, const char* outputDeviceAddress,
608 sp<StreamInHalInterface>* inStream) {
609 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
610 if (!inStream || !config) {
611 return BAD_VALUE;
612 }
613 TIME_CHECK();
614 if (!mModule) return NO_INIT;
615 int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
616 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(handle));
617 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
618 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, true /*isInput*/));
619 AudioDevice aidlDevice = VALUE_OR_RETURN_STATUS(
620 ::aidl::android::legacy2aidl_audio_device_AudioDevice(devices, address));
621 int32_t aidlInputFlags = VALUE_OR_RETURN_STATUS(
622 ::aidl::android::legacy2aidl_audio_input_flags_t_int32_t_mask(flags));
623 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::input>(aidlInputFlags);
624 AudioSource aidlSource = VALUE_OR_RETURN_STATUS(
625 ::aidl::android::legacy2aidl_audio_source_t_AudioSource(source));
626 AudioPortConfig mixPortConfig;
627 Cleanups cleanups;
628 AudioPatch aidlPatch;
629 RETURN_STATUS_IF_ERROR(prepareToOpenStream(aidlHandle, aidlDevice, aidlFlags, aidlSource,
630 config, &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
631 ::aidl::android::hardware::audio::core::IModule::OpenInputStreamArguments args;
632 args.portConfigId = mixPortConfig.id;
633 RecordTrackMetadata aidlTrackMetadata{
634 .source = aidlSource, .gain = 1, .channelMask = aidlConfig.base.channelMask };
635 if (outputDevice != AUDIO_DEVICE_NONE) {
636 aidlTrackMetadata.destinationDevice = VALUE_OR_RETURN_STATUS(
637 ::aidl::android::legacy2aidl_audio_device_AudioDevice(
638 outputDevice, outputDeviceAddress));
639 }
640 args.sinkMetadata.tracks.push_back(std::move(aidlTrackMetadata));
641 args.bufferSizeFrames = aidlConfig.frameCount;
642 ::aidl::android::hardware::audio::core::IModule::OpenInputStreamReturn ret;
643 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openInputStream(args, &ret)));
644 StreamContextAidl context(ret.desc, false /*isAsynchronous*/);
645 if (!context.isValid()) {
646 ALOGE("%s: Failed to created a valid stream context from the descriptor: %s",
647 __func__, ret.desc.toString().c_str());
648 return NO_INIT;
649 }
650 *inStream = sp<StreamInHalAidl>::make(*config, std::move(context), aidlPatch.latenciesMs[0],
651 std::move(ret.stream), mVendorExt, this /*micInfoProvider*/);
652 mStreams.insert(std::pair(*inStream, aidlPatch.id));
653 cleanups.disarmAll();
654 return OK;
655 }
656
supportsAudioPatches(bool * supportsPatches)657 status_t DeviceHalAidl::supportsAudioPatches(bool* supportsPatches) {
658 *supportsPatches = true;
659 return OK;
660 }
661
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)662 status_t DeviceHalAidl::createAudioPatch(unsigned int num_sources,
663 const struct audio_port_config* sources,
664 unsigned int num_sinks,
665 const struct audio_port_config* sinks,
666 audio_patch_handle_t* patch) {
667 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
668 TIME_CHECK();
669 if (!mModule) return NO_INIT;
670 if (num_sinks > AUDIO_PATCH_PORTS_MAX || num_sources > AUDIO_PATCH_PORTS_MAX ||
671 sources == nullptr || sinks == nullptr || patch == nullptr) {
672 return BAD_VALUE;
673 }
674 // When the patch handle (*patch) is AUDIO_PATCH_HANDLE_NONE, it means
675 // the framework wants to create a new patch. The handle has to be generated
676 // by the HAL. Since handles generated this way can only be unique within
677 // a HAL module, the framework generates a globally unique handle, and maps
678 // it on the <HAL module, patch handle> pair.
679 // When the patch handle is set, it meant the framework intends to update
680 // an existing patch.
681 //
682 // This behavior corresponds to HAL module behavior, with the only difference
683 // that the HAL module uses `int32_t` for patch IDs. The following assert ensures
684 // that both the framework and the HAL use the same value for "no ID":
685 static_assert(AUDIO_PATCH_HANDLE_NONE == 0);
686 int32_t halPatchId = static_cast<int32_t>(*patch);
687
688 // Upon conversion, mix port configs contain audio configuration, while
689 // device port configs contain device address. This data is used to find
690 // or create HAL configs.
691 std::vector<AudioPortConfig> aidlSources, aidlSinks;
692 for (unsigned int i = 0; i < num_sources; ++i) {
693 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
694 sources[i].role, sources[i].type)) ==
695 ::aidl::android::AudioPortDirection::INPUT;
696 aidlSources.push_back(VALUE_OR_RETURN_STATUS(
697 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
698 sources[i], isInput, 0)));
699 }
700 for (unsigned int i = 0; i < num_sinks; ++i) {
701 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
702 sinks[i].role, sinks[i].type)) ==
703 ::aidl::android::AudioPortDirection::INPUT;
704 aidlSinks.push_back(VALUE_OR_RETURN_STATUS(
705 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
706 sinks[i], isInput, 0)));
707 }
708 Cleanups cleanups;
709 auto existingPatchIt = halPatchId != 0 ? mPatches.find(halPatchId): mPatches.end();
710 AudioPatch aidlPatch;
711 if (existingPatchIt != mPatches.end()) {
712 aidlPatch = existingPatchIt->second;
713 aidlPatch.sourcePortConfigIds.clear();
714 aidlPatch.sinkPortConfigIds.clear();
715 }
716 // The IDs will be found by 'fillPortConfigs', however the original 'aidlSources' and
717 // 'aidlSinks' will not be updated because 'setAudioPatch' only needs IDs. Here we log
718 // the source arguments, where only the audio configuration and device specifications
719 // are relevant.
720 ALOGD("%s: [disregard IDs] sources: %s, sinks: %s",
721 __func__, ::android::internal::ToString(aidlSources).c_str(),
722 ::android::internal::ToString(aidlSinks).c_str());
723 auto fillPortConfigs = [&](
724 const std::vector<AudioPortConfig>& configs,
725 const std::set<int32_t>& destinationPortIds,
726 std::vector<int32_t>* ids, std::set<int32_t>* portIds) -> status_t {
727 for (const auto& s : configs) {
728 AudioPortConfig portConfig;
729 bool created = false;
730 RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(
731 s, destinationPortIds, &portConfig, &created));
732 if (created) {
733 cleanups.emplace_front(this, &DeviceHalAidl::resetPortConfig, portConfig.id);
734 }
735 ids->push_back(portConfig.id);
736 if (portIds != nullptr) {
737 portIds->insert(portConfig.portId);
738 }
739 }
740 return OK;
741 };
742 // When looking up port configs, the destinationPortId is only used for mix ports.
743 // Thus, we process device port configs first, and look up the destination port ID from them.
744 bool sourceIsDevice = std::any_of(aidlSources.begin(), aidlSources.end(),
745 [](const auto& config) { return config.ext.getTag() == AudioPortExt::device; });
746 const std::vector<AudioPortConfig>& devicePortConfigs =
747 sourceIsDevice ? aidlSources : aidlSinks;
748 std::vector<int32_t>* devicePortConfigIds =
749 sourceIsDevice ? &aidlPatch.sourcePortConfigIds : &aidlPatch.sinkPortConfigIds;
750 const std::vector<AudioPortConfig>& mixPortConfigs =
751 sourceIsDevice ? aidlSinks : aidlSources;
752 std::vector<int32_t>* mixPortConfigIds =
753 sourceIsDevice ? &aidlPatch.sinkPortConfigIds : &aidlPatch.sourcePortConfigIds;
754 std::set<int32_t> devicePortIds;
755 RETURN_STATUS_IF_ERROR(fillPortConfigs(
756 devicePortConfigs, std::set<int32_t>(), devicePortConfigIds, &devicePortIds));
757 RETURN_STATUS_IF_ERROR(fillPortConfigs(
758 mixPortConfigs, devicePortIds, mixPortConfigIds, nullptr));
759 if (existingPatchIt != mPatches.end()) {
760 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
761 mModule->setAudioPatch(aidlPatch, &aidlPatch)));
762 existingPatchIt->second = aidlPatch;
763 } else {
764 bool created = false;
765 RETURN_STATUS_IF_ERROR(findOrCreatePatch(aidlPatch, &aidlPatch, &created));
766 // Since no cleanup of the patch is needed, 'created' is ignored.
767 halPatchId = aidlPatch.id;
768 *patch = static_cast<audio_patch_handle_t>(halPatchId);
769 }
770 cleanups.disarmAll();
771 return OK;
772 }
773
releaseAudioPatch(audio_patch_handle_t patch)774 status_t DeviceHalAidl::releaseAudioPatch(audio_patch_handle_t patch) {
775 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
776 TIME_CHECK();
777 if (!mModule) return NO_INIT;
778 static_assert(AUDIO_PATCH_HANDLE_NONE == 0);
779 if (patch == AUDIO_PATCH_HANDLE_NONE) {
780 return BAD_VALUE;
781 }
782 int32_t halPatchId = static_cast<int32_t>(patch);
783 auto patchIt = mPatches.find(halPatchId);
784 if (patchIt == mPatches.end()) {
785 ALOGE("%s: patch with id %d not found", __func__, halPatchId);
786 return BAD_VALUE;
787 }
788 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->resetAudioPatch(halPatchId)));
789 mPatches.erase(patchIt);
790 return OK;
791 }
792
getAudioPort(struct audio_port * port)793 status_t DeviceHalAidl::getAudioPort(struct audio_port* port) {
794 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
795 TIME_CHECK();
796 if (!mModule) return NO_INIT;
797 if (port == nullptr) {
798 return BAD_VALUE;
799 }
800 audio_port_v7 portV7;
801 audio_populate_audio_port_v7(port, &portV7);
802 RETURN_STATUS_IF_ERROR(getAudioPort(&portV7));
803 return audio_populate_audio_port(&portV7, port) ? OK : BAD_VALUE;
804 }
805
getAudioPort(struct audio_port_v7 * port)806 status_t DeviceHalAidl::getAudioPort(struct audio_port_v7 *port) {
807 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
808 TIME_CHECK();
809 if (!mModule) return NO_INIT;
810 if (port == nullptr) {
811 return BAD_VALUE;
812 }
813 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(port->role, port->type)) ==
814 ::aidl::android::AudioPortDirection::INPUT;
815 auto aidlPort = VALUE_OR_RETURN_STATUS(
816 ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
817 if (aidlPort.ext.getTag() != AudioPortExt::device) {
818 ALOGE("%s: provided port is not a device port (module %s): %s",
819 __func__, mInstance.c_str(), aidlPort.toString().c_str());
820 return BAD_VALUE;
821 }
822 const auto& matchDevice = aidlPort.ext.get<AudioPortExt::device>().device;
823 // It seems that we don't have to call HAL since all valid ports have been added either
824 // during initialization, or while handling connection of an external device.
825 auto portsIt = findPort(matchDevice);
826 if (portsIt == mPorts.end()) {
827 ALOGE("%s: device port for device %s is not found in the module %s",
828 __func__, matchDevice.toString().c_str(), mInstance.c_str());
829 return BAD_VALUE;
830 }
831 const int32_t fwkId = aidlPort.id;
832 aidlPort = portsIt->second;
833 aidlPort.id = fwkId;
834 *port = VALUE_OR_RETURN_STATUS(::aidl::android::aidl2legacy_AudioPort_audio_port_v7(
835 aidlPort, isInput));
836 return OK;
837 }
838
setAudioPortConfig(const struct audio_port_config * config)839 status_t DeviceHalAidl::setAudioPortConfig(const struct audio_port_config* config) {
840 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
841 TIME_CHECK();
842 if (!mModule) return NO_INIT;
843 if (config == nullptr) {
844 return BAD_VALUE;
845 }
846 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
847 config->role, config->type)) == ::aidl::android::AudioPortDirection::INPUT;
848 AudioPortConfig requestedPortConfig = VALUE_OR_RETURN_STATUS(
849 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
850 *config, isInput, 0 /*portId*/));
851 AudioPortConfig portConfig;
852 bool created = false;
853 RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(
854 requestedPortConfig, std::set<int32_t>(), &portConfig, &created));
855 return OK;
856 }
857
getMicrophoneInfo()858 MicrophoneInfoProvider::Info const* DeviceHalAidl::getMicrophoneInfo() {
859 if (mMicrophones.status == Microphones::Status::UNKNOWN) {
860 TIME_CHECK();
861 std::vector<MicrophoneInfo> aidlInfo;
862 status_t status = statusTFromBinderStatus(mModule->getMicrophones(&aidlInfo));
863 if (status == OK) {
864 mMicrophones.status = Microphones::Status::QUERIED;
865 mMicrophones.info = std::move(aidlInfo);
866 } else if (status == INVALID_OPERATION) {
867 mMicrophones.status = Microphones::Status::NOT_SUPPORTED;
868 } else {
869 ALOGE("%s: Unexpected status from 'IModule.getMicrophones': %d", __func__, status);
870 return {};
871 }
872 }
873 if (mMicrophones.status == Microphones::Status::QUERIED) {
874 return &mMicrophones.info;
875 }
876 return {}; // NOT_SUPPORTED
877 }
878
getMicrophones(std::vector<audio_microphone_characteristic_t> * microphones)879 status_t DeviceHalAidl::getMicrophones(
880 std::vector<audio_microphone_characteristic_t>* microphones) {
881 if (!microphones) {
882 return BAD_VALUE;
883 }
884 TIME_CHECK();
885 if (!mModule) return NO_INIT;
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 TIME_CHECK();
903 if (!mModule) return NO_INIT;
904 if (!effect) {
905 return BAD_VALUE;
906 }
907 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
908 device->role, device->type)) == ::aidl::android::AudioPortDirection::INPUT;
909 auto requestedPortConfig = VALUE_OR_RETURN_STATUS(
910 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
911 *device, isInput, 0));
912 if (requestedPortConfig.ext.getTag() != AudioPortExt::Tag::device) {
913 ALOGE("%s: provided port config is not a device port config: %s",
914 __func__, requestedPortConfig.toString().c_str());
915 return BAD_VALUE;
916 }
917 AudioPortConfig devicePortConfig;
918 bool created;
919 RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(
920 requestedPortConfig, {} /*destinationPortIds*/, &devicePortConfig, &created));
921 Cleanups cleanups;
922 if (created) {
923 cleanups.emplace_front(this, &DeviceHalAidl::resetPortConfig, devicePortConfig.id);
924 }
925 auto aidlEffect = sp<effect::EffectHalAidl>::cast(effect);
926 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->addDeviceEffect(
927 devicePortConfig.id, aidlEffect->getIEffect())));
928 cleanups.disarmAll();
929 return OK;
930 }
removeDeviceEffect(const struct audio_port_config * device,sp<EffectHalInterface> effect)931 status_t DeviceHalAidl::removeDeviceEffect(
932 const struct audio_port_config *device, sp<EffectHalInterface> effect) {
933 TIME_CHECK();
934 if (!mModule) return NO_INIT;
935 if (!effect) {
936 return BAD_VALUE;
937 }
938 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
939 device->role, device->type)) == ::aidl::android::AudioPortDirection::INPUT;
940 auto requestedPortConfig = VALUE_OR_RETURN_STATUS(
941 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
942 *device, isInput, 0));
943 if (requestedPortConfig.ext.getTag() != AudioPortExt::Tag::device) {
944 ALOGE("%s: provided port config is not a device port config: %s",
945 __func__, requestedPortConfig.toString().c_str());
946 return BAD_VALUE;
947 }
948 auto existingPortConfigIt = findPortConfig(
949 requestedPortConfig.ext.get<AudioPortExt::Tag::device>().device);
950 if (existingPortConfigIt == mPortConfigs.end()) {
951 ALOGE("%s: could not find a configured device port for the config %s",
952 __func__, requestedPortConfig.toString().c_str());
953 return BAD_VALUE;
954 }
955 auto aidlEffect = sp<effect::EffectHalAidl>::cast(effect);
956 return statusTFromBinderStatus(mModule->removeDeviceEffect(
957 existingPortConfigIt->first, aidlEffect->getIEffect()));
958 }
959
getMmapPolicyInfos(media::audio::common::AudioMMapPolicyType policyType,std::vector<media::audio::common::AudioMMapPolicyInfo> * policyInfos)960 status_t DeviceHalAidl::getMmapPolicyInfos(
961 media::audio::common::AudioMMapPolicyType policyType,
962 std::vector<media::audio::common::AudioMMapPolicyInfo>* policyInfos) {
963 TIME_CHECK();
964 AudioMMapPolicyType mmapPolicyType = VALUE_OR_RETURN_STATUS(
965 cpp2ndk_AudioMMapPolicyType(policyType));
966
967 std::vector<AudioMMapPolicyInfo> mmapPolicyInfos;
968
969 if (status_t status = statusTFromBinderStatus(
970 mModule->getMmapPolicyInfos(mmapPolicyType, &mmapPolicyInfos)); status != OK) {
971 return status;
972 }
973
974 *policyInfos = VALUE_OR_RETURN_STATUS(
975 convertContainer<std::vector<media::audio::common::AudioMMapPolicyInfo>>(
976 mmapPolicyInfos, ndk2cpp_AudioMMapPolicyInfo));
977 return OK;
978 }
979
getAAudioMixerBurstCount()980 int32_t DeviceHalAidl::getAAudioMixerBurstCount() {
981 TIME_CHECK();
982 int32_t mixerBurstCount = 0;
983 if (mModule->getAAudioMixerBurstCount(&mixerBurstCount).isOk()) {
984 return mixerBurstCount;
985 }
986 return 0;
987 }
988
getAAudioHardwareBurstMinUsec()989 int32_t DeviceHalAidl::getAAudioHardwareBurstMinUsec() {
990 TIME_CHECK();
991 int32_t hardwareBurstMinUsec = 0;
992 if (mModule->getAAudioHardwareBurstMinUsec(&hardwareBurstMinUsec).isOk()) {
993 return hardwareBurstMinUsec;
994 }
995 return 0;
996 }
997
getHwAvSync()998 error::Result<audio_hw_sync_t> DeviceHalAidl::getHwAvSync() {
999 TIME_CHECK();
1000 if (!mModule) return NO_INIT;
1001 int32_t aidlHwAvSync;
1002 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->generateHwAvSyncId(&aidlHwAvSync)));
1003 return VALUE_OR_RETURN_STATUS(
1004 ::aidl::android::aidl2legacy_int32_t_audio_hw_sync_t(aidlHwAvSync));
1005 }
1006
dump(int fd,const Vector<String16> & args)1007 status_t DeviceHalAidl::dump(int fd, const Vector<String16>& args) {
1008 TIME_CHECK();
1009 if (!mModule) return NO_INIT;
1010 return mModule->dump(fd, Args(args).args(), args.size());
1011 }
1012
supportsBluetoothVariableLatency(bool * supports)1013 status_t DeviceHalAidl::supportsBluetoothVariableLatency(bool* supports) {
1014 TIME_CHECK();
1015 if (!mModule) return NO_INIT;
1016 if (supports == nullptr) {
1017 return BAD_VALUE;
1018 }
1019 return statusTFromBinderStatus(mModule->supportsVariableLatency(supports));
1020 }
1021
getSoundDoseInterface(const std::string & module,::ndk::SpAIBinder * soundDoseBinder)1022 status_t DeviceHalAidl::getSoundDoseInterface(const std::string& module,
1023 ::ndk::SpAIBinder* soundDoseBinder) {
1024 TIME_CHECK();
1025 if (!mModule) return NO_INIT;
1026 if (mSoundDose == nullptr) {
1027 ndk::ScopedAStatus status = mModule->getSoundDose(&mSoundDose);
1028 if (!status.isOk()) {
1029 ALOGE("%s failed to return the sound dose interface for module %s: %s",
1030 __func__,
1031 module.c_str(),
1032 status.getDescription().c_str());
1033 return BAD_VALUE;
1034 }
1035 }
1036 *soundDoseBinder = mSoundDose->asBinder();
1037 ALOGI("%s using audio AIDL HAL sound dose interface", __func__);
1038
1039 return OK;
1040 }
1041
prepareToDisconnectExternalDevice(const struct audio_port_v7 * port)1042 status_t DeviceHalAidl::prepareToDisconnectExternalDevice(const struct audio_port_v7* port) {
1043 // There is not AIDL API defined for `prepareToDisconnectExternalDevice`.
1044 // Call `setConnectedState` instead.
1045 // TODO(b/279824103): call prepareToDisconnectExternalDevice when it is added.
1046 if (const status_t status = setConnectedState(port, false /*connected*/); status == NO_ERROR) {
1047 mDeviceDisconnectionNotified.insert(port->id);
1048 }
1049 // Return that there was no error as otherwise the disconnection procedure will not be
1050 // considered complete for upper layers, and 'setConnectedState' will not be called again.
1051 return NO_ERROR;
1052 }
1053
setConnectedState(const struct audio_port_v7 * port,bool connected)1054 status_t DeviceHalAidl::setConnectedState(const struct audio_port_v7 *port, bool connected) {
1055 TIME_CHECK();
1056 if (!mModule) return NO_INIT;
1057 if (port == nullptr) {
1058 return BAD_VALUE;
1059 }
1060 if (!connected && mDeviceDisconnectionNotified.erase(port->id) > 0) {
1061 // For device disconnection, APM will first call `prepareToDisconnectExternalDevice`
1062 // and then call `setConnectedState`. However, there is no API for
1063 // `prepareToDisconnectExternalDevice` yet. In that case, `setConnectedState` will be
1064 // called when calling `prepareToDisconnectExternalDevice`. Do not call to the HAL if
1065 // previous call is successful. Also remove the cache here to avoid a large cache after
1066 // a long run.
1067 return NO_ERROR;
1068 }
1069 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(port->role, port->type)) ==
1070 ::aidl::android::AudioPortDirection::INPUT;
1071 AudioPort aidlPort = VALUE_OR_RETURN_STATUS(
1072 ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
1073 if (aidlPort.ext.getTag() != AudioPortExt::device) {
1074 ALOGE("%s: provided port is not a device port (module %s): %s",
1075 __func__, mInstance.c_str(), aidlPort.toString().c_str());
1076 return BAD_VALUE;
1077 }
1078 if (connected) {
1079 AudioDevice matchDevice = aidlPort.ext.get<AudioPortExt::device>().device;
1080 // Reset the device address to find the "template" port.
1081 matchDevice.address = AudioDeviceAddress::make<AudioDeviceAddress::id>();
1082 auto portsIt = findPort(matchDevice);
1083 if (portsIt == mPorts.end()) {
1084 // Since 'setConnectedState' is called for all modules, it is normal when the device
1085 // port not found in every one of them.
1086 return BAD_VALUE;
1087 } else {
1088 ALOGD("%s: device port for device %s found in the module %s",
1089 __func__, matchDevice.toString().c_str(), mInstance.c_str());
1090 }
1091 resetUnusedPatchesAndPortConfigs();
1092 // Use the ID of the "template" port, use all the information from the provided port.
1093 aidlPort.id = portsIt->first;
1094 AudioPort connectedPort;
1095 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->connectExternalDevice(
1096 aidlPort, &connectedPort)));
1097 const auto [it, inserted] = mPorts.insert(std::make_pair(connectedPort.id, connectedPort));
1098 LOG_ALWAYS_FATAL_IF(!inserted,
1099 "%s: module %s, duplicate port ID received from HAL: %s, existing port: %s",
1100 __func__, mInstance.c_str(), connectedPort.toString().c_str(),
1101 it->second.toString().c_str());
1102 mConnectedPorts[connectedPort.id] = false;
1103 } else { // !connected
1104 AudioDevice matchDevice = aidlPort.ext.get<AudioPortExt::device>().device;
1105 auto portsIt = findPort(matchDevice);
1106 if (portsIt == mPorts.end()) {
1107 // Since 'setConnectedState' is called for all modules, it is normal when the device
1108 // port not found in every one of them.
1109 return BAD_VALUE;
1110 } else {
1111 ALOGD("%s: device port for device %s found in the module %s",
1112 __func__, matchDevice.toString().c_str(), mInstance.c_str());
1113 }
1114 resetUnusedPatchesAndPortConfigs();
1115 // Streams are closed by AudioFlinger independently from device disconnections.
1116 // It is possible that the stream has not been closed yet.
1117 const int32_t portId = portsIt->second.id;
1118 if (!isPortHeldByAStream(portId)) {
1119 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
1120 mModule->disconnectExternalDevice(portId)));
1121 mPorts.erase(portsIt);
1122 mConnectedPorts.erase(portId);
1123 } else {
1124 ALOGD("%s: since device port ID %d is used by a stream, "
1125 "external device disconnection postponed", __func__, portId);
1126 mConnectedPorts[portId] = true;
1127 }
1128 }
1129 return updateRoutes();
1130 }
1131
setSimulateDeviceConnections(bool enabled)1132 status_t DeviceHalAidl::setSimulateDeviceConnections(bool enabled) {
1133 TIME_CHECK();
1134 if (!mModule) return NO_INIT;
1135 resetUnusedPatchesAndPortConfigs();
1136 ModuleDebug debug{ .simulateDeviceConnections = enabled };
1137 status_t status = statusTFromBinderStatus(mModule->setModuleDebug(debug));
1138 // This is important to log as it affects HAL behavior.
1139 if (status == OK) {
1140 ALOGI("%s: set enabled: %d", __func__, enabled);
1141 } else {
1142 ALOGW("%s: set enabled to %d failed: %d", __func__, enabled, status);
1143 }
1144 return status;
1145 }
1146
audioDeviceMatches(const AudioDevice & device,const AudioPort & p)1147 bool DeviceHalAidl::audioDeviceMatches(const AudioDevice& device, const AudioPort& p) {
1148 if (p.ext.getTag() != AudioPortExt::Tag::device) return false;
1149 return p.ext.get<AudioPortExt::Tag::device>().device == device;
1150 }
1151
audioDeviceMatches(const AudioDevice & device,const AudioPortConfig & p)1152 bool DeviceHalAidl::audioDeviceMatches(const AudioDevice& device, const AudioPortConfig& p) {
1153 if (p.ext.getTag() != AudioPortExt::Tag::device) return false;
1154 if (device.type.type == AudioDeviceType::IN_DEFAULT) {
1155 return p.portId == mDefaultInputPortId;
1156 } else if (device.type.type == AudioDeviceType::OUT_DEFAULT) {
1157 return p.portId == mDefaultOutputPortId;
1158 }
1159 return p.ext.get<AudioPortExt::Tag::device>().device == device;
1160 }
1161
createOrUpdatePortConfig(const AudioPortConfig & requestedPortConfig,PortConfigs::iterator * result,bool * created)1162 status_t DeviceHalAidl::createOrUpdatePortConfig(
1163 const AudioPortConfig& requestedPortConfig, PortConfigs::iterator* result, bool* created) {
1164 TIME_CHECK();
1165 AudioPortConfig appliedPortConfig;
1166 bool applied = false;
1167 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPortConfig(
1168 requestedPortConfig, &appliedPortConfig, &applied)));
1169 if (!applied) {
1170 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPortConfig(
1171 appliedPortConfig, &appliedPortConfig, &applied)));
1172 if (!applied) {
1173 ALOGE("%s: module %s did not apply suggested config %s",
1174 __func__, mInstance.c_str(), appliedPortConfig.toString().c_str());
1175 return NO_INIT;
1176 }
1177 }
1178
1179 int32_t id = appliedPortConfig.id;
1180 if (requestedPortConfig.id != 0 && requestedPortConfig.id != id) {
1181 LOG_ALWAYS_FATAL("%s: requested port config id %d changed to %d", __func__,
1182 requestedPortConfig.id, id);
1183 }
1184
1185 auto [it, inserted] = mPortConfigs.insert_or_assign(std::move(id),
1186 std::move(appliedPortConfig));
1187 *result = it;
1188 *created = inserted;
1189 return OK;
1190 }
1191
filterAndRetrieveBtA2dpParameters(AudioParameter & keys,AudioParameter * result)1192 status_t DeviceHalAidl::filterAndRetrieveBtA2dpParameters(
1193 AudioParameter &keys, AudioParameter *result) {
1194 TIME_CHECK();
1195 if (String8 key = String8(AudioParameter::keyReconfigA2dpSupported); keys.containsKey(key)) {
1196 keys.remove(key);
1197 bool supports;
1198 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
1199 mBluetoothA2dp->supportsOffloadReconfiguration(&supports)));
1200 result->addInt(key, supports ? 1 : 0);
1201 }
1202 return OK;
1203 }
1204
filterAndUpdateBtA2dpParameters(AudioParameter & parameters)1205 status_t DeviceHalAidl::filterAndUpdateBtA2dpParameters(AudioParameter ¶meters) {
1206 TIME_CHECK();
1207 std::optional<bool> a2dpEnabled;
1208 std::optional<std::vector<VendorParameter>> reconfigureOffload;
1209 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1210 parameters, String8(AudioParameter::keyBtA2dpSuspended),
1211 [&a2dpEnabled](const String8& trueOrFalse) {
1212 if (trueOrFalse == AudioParameter::valueTrue) {
1213 a2dpEnabled = false; // 'suspended' == true
1214 return OK;
1215 } else if (trueOrFalse == AudioParameter::valueFalse) {
1216 a2dpEnabled = true; // 'suspended' == false
1217 return OK;
1218 }
1219 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1220 AudioParameter::keyBtA2dpSuspended, trueOrFalse.c_str());
1221 return BAD_VALUE;
1222 }));
1223 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1224 parameters, String8(AudioParameter::keyReconfigA2dp),
1225 [&](const String8& value) -> status_t {
1226 if (mVendorExt != nullptr) {
1227 std::vector<VendorParameter> result;
1228 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
1229 mVendorExt->parseBluetoothA2dpReconfigureOffload(
1230 std::string(value.c_str()), &result)));
1231 reconfigureOffload = std::move(result);
1232 } else {
1233 reconfigureOffload = std::vector<VendorParameter>();
1234 }
1235 return OK;
1236 }));
1237 if (mBluetoothA2dp != nullptr && a2dpEnabled.has_value()) {
1238 return statusTFromBinderStatus(mBluetoothA2dp->setEnabled(a2dpEnabled.value()));
1239 }
1240 if (mBluetoothA2dp != nullptr && reconfigureOffload.has_value()) {
1241 return statusTFromBinderStatus(mBluetoothA2dp->reconfigureOffload(
1242 reconfigureOffload.value()));
1243 }
1244 return OK;
1245 }
1246
filterAndUpdateBtHfpParameters(AudioParameter & parameters)1247 status_t DeviceHalAidl::filterAndUpdateBtHfpParameters(AudioParameter ¶meters) {
1248 TIME_CHECK();
1249 IBluetooth::HfpConfig hfpConfig;
1250 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1251 parameters, String8(AudioParameter::keyBtHfpEnable),
1252 [&hfpConfig](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 ALOGE("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 ?
1268 hfpConfig.sampleRate = Int{ .value = sampleRate }, OK : BAD_VALUE;
1269 }));
1270 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
1271 parameters, String8(AudioParameter::keyBtHfpVolume),
1272 [&hfpConfig](int volume0to15) {
1273 if (volume0to15 >= 0 && volume0to15 <= 15) {
1274 hfpConfig.volume = Float{ .value = volume0to15 / 15.0f };
1275 return OK;
1276 }
1277 return BAD_VALUE;
1278 }));
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 TIME_CHECK();
1288 std::optional<bool> leEnabled;
1289 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1290 parameters, String8(AudioParameter::keyBtLeSuspended),
1291 [&leEnabled](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 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1300 AudioParameter::keyBtLeSuspended, trueOrFalse.c_str());
1301 return BAD_VALUE;
1302 }));
1303 if (mBluetoothLe != nullptr && leEnabled.has_value()) {
1304 return statusTFromBinderStatus(mBluetoothLe->setEnabled(leEnabled.value()));
1305 }
1306 return OK;
1307 }
1308
filterAndUpdateBtScoParameters(AudioParameter & parameters)1309 status_t DeviceHalAidl::filterAndUpdateBtScoParameters(AudioParameter ¶meters) {
1310 TIME_CHECK();
1311 IBluetooth::ScoConfig scoConfig;
1312 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1313 parameters, String8(AudioParameter::keyBtSco),
1314 [&scoConfig](const String8& onOrOff) {
1315 if (onOrOff == AudioParameter::valueOn) {
1316 scoConfig.isEnabled = Boolean{ .value = true };
1317 return OK;
1318 } else if (onOrOff == AudioParameter::valueOff) {
1319 scoConfig.isEnabled = Boolean{ .value = false };
1320 return OK;
1321 }
1322 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1323 AudioParameter::keyBtSco, onOrOff.c_str());
1324 return BAD_VALUE;
1325 }));
1326 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1327 parameters, String8(AudioParameter::keyBtScoHeadsetName),
1328 [&scoConfig](const String8& name) {
1329 scoConfig.debugName = name;
1330 return OK;
1331 }));
1332 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1333 parameters, String8(AudioParameter::keyBtNrec),
1334 [&scoConfig](const String8& onOrOff) {
1335 if (onOrOff == AudioParameter::valueOn) {
1336 scoConfig.isNrecEnabled = Boolean{ .value = true };
1337 return OK;
1338 } else if (onOrOff == AudioParameter::valueOff) {
1339 scoConfig.isNrecEnabled = Boolean{ .value = false };
1340 return OK;
1341 }
1342 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1343 AudioParameter::keyBtNrec, onOrOff.c_str());
1344 return BAD_VALUE;
1345 }));
1346 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1347 parameters, String8(AudioParameter::keyBtScoWb),
1348 [&scoConfig](const String8& onOrOff) {
1349 if (onOrOff == AudioParameter::valueOn) {
1350 scoConfig.mode = IBluetooth::ScoConfig::Mode::SCO_WB;
1351 return OK;
1352 } else if (onOrOff == AudioParameter::valueOff) {
1353 scoConfig.mode = IBluetooth::ScoConfig::Mode::SCO;
1354 return OK;
1355 }
1356 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1357 AudioParameter::keyBtScoWb, onOrOff.c_str());
1358 return BAD_VALUE;
1359 }));
1360 if (mBluetooth != nullptr && scoConfig != IBluetooth::ScoConfig{}) {
1361 IBluetooth::ScoConfig newScoConfig;
1362 return statusTFromBinderStatus(mBluetooth->setScoConfig(scoConfig, &newScoConfig));
1363 }
1364 return OK;
1365 }
1366
filterAndUpdateScreenParameters(AudioParameter & parameters)1367 status_t DeviceHalAidl::filterAndUpdateScreenParameters(AudioParameter ¶meters) {
1368 TIME_CHECK();
1369 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1370 parameters, String8(AudioParameter::keyScreenState),
1371 [&](const String8& onOrOff) -> status_t {
1372 std::optional<bool> isTurnedOn;
1373 if (onOrOff == AudioParameter::valueOn) {
1374 isTurnedOn = true;
1375 } else if (onOrOff == AudioParameter::valueOff) {
1376 isTurnedOn = false;
1377 }
1378 if (!isTurnedOn.has_value()) {
1379 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1380 AudioParameter::keyScreenState, onOrOff.c_str());
1381 return BAD_VALUE;
1382 }
1383 return statusTFromBinderStatus(
1384 mModule->updateScreenState(isTurnedOn.value()));
1385 }));
1386 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
1387 parameters, String8(AudioParameter::keyScreenRotation),
1388 [&](int rotationDegrees) -> status_t {
1389 IModule::ScreenRotation rotation;
1390 switch (rotationDegrees) {
1391 case 0: rotation = IModule::ScreenRotation::DEG_0; break;
1392 case 90: rotation = IModule::ScreenRotation::DEG_90; break;
1393 case 180: rotation = IModule::ScreenRotation::DEG_180; break;
1394 case 270: rotation = IModule::ScreenRotation::DEG_270; break;
1395 default:
1396 ALOGE("setParameters: parameter key \"%s\" has invalid value %d",
1397 AudioParameter::keyScreenRotation, rotationDegrees);
1398 return BAD_VALUE;
1399 }
1400 return statusTFromBinderStatus(mModule->updateScreenRotation(rotation));
1401 }));
1402 return OK;
1403 }
1404
filterAndUpdateTelephonyParameters(AudioParameter & parameters)1405 status_t DeviceHalAidl::filterAndUpdateTelephonyParameters(AudioParameter ¶meters) {
1406 TIME_CHECK();
1407 using TtyMode = ITelephony::TelecomConfig::TtyMode;
1408 ITelephony::TelecomConfig telConfig;
1409 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1410 parameters, String8(AudioParameter::keyTtyMode),
1411 [&telConfig](const String8& mode) {
1412 if (mode == AudioParameter::valueTtyModeOff) {
1413 telConfig.ttyMode = TtyMode::OFF;
1414 return OK;
1415 } else if (mode == AudioParameter::valueTtyModeFull) {
1416 telConfig.ttyMode = TtyMode::FULL;
1417 return OK;
1418 } else if (mode == AudioParameter::valueTtyModeHco) {
1419 telConfig.ttyMode = TtyMode::HCO;
1420 return OK;
1421 } else if (mode == AudioParameter::valueTtyModeVco) {
1422 telConfig.ttyMode = TtyMode::VCO;
1423 return OK;
1424 }
1425 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1426 AudioParameter::keyTtyMode, mode.c_str());
1427 return BAD_VALUE;
1428 }));
1429 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
1430 parameters, String8(AudioParameter::keyHacSetting),
1431 [&telConfig](const String8& onOrOff) {
1432 if (onOrOff == AudioParameter::valueHacOn) {
1433 telConfig.isHacEnabled = Boolean{ .value = true };
1434 return OK;
1435 } else if (onOrOff == AudioParameter::valueHacOff) {
1436 telConfig.isHacEnabled = Boolean{ .value = false };
1437 return OK;
1438 }
1439 ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
1440 AudioParameter::keyHacSetting, onOrOff.c_str());
1441 return BAD_VALUE;
1442 }));
1443 if (mTelephony != nullptr && telConfig != ITelephony::TelecomConfig{}) {
1444 ITelephony::TelecomConfig newTelConfig;
1445 return statusTFromBinderStatus(
1446 mTelephony->setTelecomConfig(telConfig, &newTelConfig));
1447 }
1448 return OK;
1449 }
1450
findOrCreatePatch(const AudioPatch & requestedPatch,AudioPatch * patch,bool * created)1451 status_t DeviceHalAidl::findOrCreatePatch(
1452 const AudioPatch& requestedPatch, AudioPatch* patch, bool* created) {
1453 std::set<int32_t> sourcePortConfigIds(requestedPatch.sourcePortConfigIds.begin(),
1454 requestedPatch.sourcePortConfigIds.end());
1455 std::set<int32_t> sinkPortConfigIds(requestedPatch.sinkPortConfigIds.begin(),
1456 requestedPatch.sinkPortConfigIds.end());
1457 return findOrCreatePatch(sourcePortConfigIds, sinkPortConfigIds, patch, created);
1458 }
1459
findOrCreatePatch(const std::set<int32_t> & sourcePortConfigIds,const std::set<int32_t> & sinkPortConfigIds,AudioPatch * patch,bool * created)1460 status_t DeviceHalAidl::findOrCreatePatch(
1461 const std::set<int32_t>& sourcePortConfigIds, const std::set<int32_t>& sinkPortConfigIds,
1462 AudioPatch* patch, bool* created) {
1463 auto patchIt = findPatch(sourcePortConfigIds, sinkPortConfigIds);
1464 if (patchIt == mPatches.end()) {
1465 TIME_CHECK();
1466 AudioPatch requestedPatch, appliedPatch;
1467 requestedPatch.sourcePortConfigIds.insert(requestedPatch.sourcePortConfigIds.end(),
1468 sourcePortConfigIds.begin(), sourcePortConfigIds.end());
1469 requestedPatch.sinkPortConfigIds.insert(requestedPatch.sinkPortConfigIds.end(),
1470 sinkPortConfigIds.begin(), sinkPortConfigIds.end());
1471 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPatch(
1472 requestedPatch, &appliedPatch)));
1473 patchIt = mPatches.insert(mPatches.end(), std::make_pair(appliedPatch.id, appliedPatch));
1474 *created = true;
1475 } else {
1476 *created = false;
1477 }
1478 *patch = patchIt->second;
1479 return OK;
1480 }
1481
findOrCreatePortConfig(const AudioDevice & device,const AudioConfig * config,AudioPortConfig * portConfig,bool * created)1482 status_t DeviceHalAidl::findOrCreatePortConfig(const AudioDevice& device, const AudioConfig* config,
1483 AudioPortConfig* portConfig, bool* created) {
1484 auto portConfigIt = findPortConfig(device);
1485 if (portConfigIt == mPortConfigs.end()) {
1486 auto portsIt = findPort(device);
1487 if (portsIt == mPorts.end()) {
1488 ALOGE("%s: device port for device %s is not found in the module %s",
1489 __func__, device.toString().c_str(), mInstance.c_str());
1490 return BAD_VALUE;
1491 }
1492 AudioPortConfig requestedPortConfig;
1493 requestedPortConfig.portId = portsIt->first;
1494 if (config != nullptr) {
1495 setPortConfigFromConfig(&requestedPortConfig, *config);
1496 }
1497 RETURN_STATUS_IF_ERROR(createOrUpdatePortConfig(requestedPortConfig, &portConfigIt,
1498 created));
1499 } else {
1500 *created = false;
1501 }
1502 *portConfig = portConfigIt->second;
1503 return OK;
1504 }
1505
findOrCreatePortConfig(const AudioConfig & config,const std::optional<AudioIoFlags> & flags,int32_t ioHandle,AudioSource source,const std::set<int32_t> & destinationPortIds,AudioPortConfig * portConfig,bool * created)1506 status_t DeviceHalAidl::findOrCreatePortConfig(
1507 const AudioConfig& config, const std::optional<AudioIoFlags>& flags, int32_t ioHandle,
1508 AudioSource source, const std::set<int32_t>& destinationPortIds,
1509 AudioPortConfig* portConfig, bool* created) {
1510 // These flags get removed one by one in this order when retrying port finding.
1511 static const std::vector<AudioInputFlags> kOptionalInputFlags{
1512 AudioInputFlags::FAST, AudioInputFlags::RAW };
1513 auto portConfigIt = findPortConfig(config, flags, ioHandle);
1514 if (portConfigIt == mPortConfigs.end() && flags.has_value()) {
1515 auto optionalInputFlagsIt = kOptionalInputFlags.begin();
1516 AudioIoFlags matchFlags = flags.value();
1517 auto portsIt = findPort(config, matchFlags, destinationPortIds);
1518 while (portsIt == mPorts.end() && matchFlags.getTag() == AudioIoFlags::Tag::input
1519 && optionalInputFlagsIt != kOptionalInputFlags.end()) {
1520 if (!isBitPositionFlagSet(
1521 matchFlags.get<AudioIoFlags::Tag::input>(), *optionalInputFlagsIt)) {
1522 ++optionalInputFlagsIt;
1523 continue;
1524 }
1525 matchFlags.set<AudioIoFlags::Tag::input>(matchFlags.get<AudioIoFlags::Tag::input>() &
1526 ~makeBitPositionFlagMask(*optionalInputFlagsIt++));
1527 portsIt = findPort(config, matchFlags, destinationPortIds);
1528 ALOGI("%s: mix port for config %s, flags %s was not found in the module %s, "
1529 "retried with flags %s", __func__, config.toString().c_str(),
1530 flags.value().toString().c_str(), mInstance.c_str(),
1531 matchFlags.toString().c_str());
1532 }
1533 if (portsIt == mPorts.end()) {
1534 ALOGE("%s: mix port for config %s, flags %s is not found in the module %s",
1535 __func__, config.toString().c_str(), matchFlags.toString().c_str(),
1536 mInstance.c_str());
1537 return BAD_VALUE;
1538 }
1539 AudioPortConfig requestedPortConfig;
1540 requestedPortConfig.portId = portsIt->first;
1541 setPortConfigFromConfig(&requestedPortConfig, config);
1542 requestedPortConfig.ext = AudioPortMixExt{ .handle = ioHandle };
1543 if (matchFlags.getTag() == AudioIoFlags::Tag::input
1544 && source != AudioSource::SYS_RESERVED_INVALID) {
1545 requestedPortConfig.ext.get<AudioPortExt::Tag::mix>().usecase =
1546 AudioPortMixExtUseCase::make<AudioPortMixExtUseCase::Tag::source>(source);
1547 }
1548 RETURN_STATUS_IF_ERROR(createOrUpdatePortConfig(requestedPortConfig, &portConfigIt,
1549 created));
1550 } else if (portConfigIt == mPortConfigs.end() && !flags.has_value()) {
1551 ALOGW("%s: mix port config for %s, handle %d not found in the module %s, "
1552 "and was not created as flags are not specified",
1553 __func__, config.toString().c_str(), ioHandle, mInstance.c_str());
1554 return BAD_VALUE;
1555 } else {
1556 AudioPortConfig requestedPortConfig = portConfigIt->second;
1557 if (requestedPortConfig.ext.getTag() == AudioPortExt::Tag::mix) {
1558 AudioPortMixExt& mixExt = requestedPortConfig.ext.get<AudioPortExt::Tag::mix>();
1559 if (mixExt.usecase.getTag() == AudioPortMixExtUseCase::Tag::source &&
1560 source != AudioSource::SYS_RESERVED_INVALID) {
1561 mixExt.usecase.get<AudioPortMixExtUseCase::Tag::source>() = source;
1562 }
1563 }
1564
1565 if (requestedPortConfig != portConfigIt->second) {
1566 RETURN_STATUS_IF_ERROR(createOrUpdatePortConfig(requestedPortConfig, &portConfigIt,
1567 created));
1568 } else {
1569 *created = false;
1570 }
1571 }
1572 *portConfig = portConfigIt->second;
1573 return OK;
1574 }
1575
findOrCreatePortConfig(const AudioPortConfig & requestedPortConfig,const std::set<int32_t> & destinationPortIds,AudioPortConfig * portConfig,bool * created)1576 status_t DeviceHalAidl::findOrCreatePortConfig(
1577 const AudioPortConfig& requestedPortConfig, const std::set<int32_t>& destinationPortIds,
1578 AudioPortConfig* portConfig, bool* created) {
1579 using Tag = AudioPortExt::Tag;
1580 if (requestedPortConfig.ext.getTag() == Tag::mix) {
1581 if (const auto& p = requestedPortConfig;
1582 !p.sampleRate.has_value() || !p.channelMask.has_value() ||
1583 !p.format.has_value()) {
1584 ALOGW("%s: provided mix port config is not fully specified: %s",
1585 __func__, p.toString().c_str());
1586 return BAD_VALUE;
1587 }
1588 AudioConfig config;
1589 setConfigFromPortConfig(&config, requestedPortConfig);
1590 AudioSource source = requestedPortConfig.ext.get<Tag::mix>().usecase.getTag() ==
1591 AudioPortMixExtUseCase::Tag::source ?
1592 requestedPortConfig.ext.get<Tag::mix>().usecase.
1593 get<AudioPortMixExtUseCase::Tag::source>() : AudioSource::SYS_RESERVED_INVALID;
1594 return findOrCreatePortConfig(config, requestedPortConfig.flags,
1595 requestedPortConfig.ext.get<Tag::mix>().handle, source, destinationPortIds,
1596 portConfig, created);
1597 } else if (requestedPortConfig.ext.getTag() == Tag::device) {
1598 return findOrCreatePortConfig(
1599 requestedPortConfig.ext.get<Tag::device>().device, nullptr /*config*/,
1600 portConfig, created);
1601 }
1602 ALOGW("%s: unsupported audio port config: %s",
1603 __func__, requestedPortConfig.toString().c_str());
1604 return BAD_VALUE;
1605 }
1606
findPatch(const std::set<int32_t> & sourcePortConfigIds,const std::set<int32_t> & sinkPortConfigIds)1607 DeviceHalAidl::Patches::iterator DeviceHalAidl::findPatch(
1608 const std::set<int32_t>& sourcePortConfigIds, const std::set<int32_t>& sinkPortConfigIds) {
1609 return std::find_if(mPatches.begin(), mPatches.end(),
1610 [&](const auto& pair) {
1611 const auto& p = pair.second;
1612 std::set<int32_t> patchSrcs(
1613 p.sourcePortConfigIds.begin(), p.sourcePortConfigIds.end());
1614 std::set<int32_t> patchSinks(
1615 p.sinkPortConfigIds.begin(), p.sinkPortConfigIds.end());
1616 return sourcePortConfigIds == patchSrcs && sinkPortConfigIds == patchSinks; });
1617 }
1618
findPort(const AudioDevice & device)1619 DeviceHalAidl::Ports::iterator DeviceHalAidl::findPort(const AudioDevice& device) {
1620 if (device.type.type == AudioDeviceType::IN_DEFAULT) {
1621 return mPorts.find(mDefaultInputPortId);
1622 } else if (device.type.type == AudioDeviceType::OUT_DEFAULT) {
1623 return mPorts.find(mDefaultOutputPortId);
1624 }
1625 if (device.address.getTag() != AudioDeviceAddress::id ||
1626 !device.address.get<AudioDeviceAddress::id>().empty()) {
1627 return std::find_if(mPorts.begin(), mPorts.end(),
1628 [&](const auto& pair) { return audioDeviceMatches(device, pair.second); });
1629 }
1630 // For connection w/o an address, two ports can be found: the template port,
1631 // and a connected port (if exists). Make sure we return the connected port.
1632 DeviceHalAidl::Ports::iterator portIt = mPorts.end();
1633 for (auto it = mPorts.begin(); it != mPorts.end(); ++it) {
1634 if (audioDeviceMatches(device, it->second)) {
1635 if (mConnectedPorts.find(it->first) != mConnectedPorts.end()) {
1636 return it;
1637 } else {
1638 // Will return 'it' if there is no connected port.
1639 portIt = it;
1640 }
1641 }
1642 }
1643 return portIt;
1644 }
1645
findPort(const AudioConfig & config,const AudioIoFlags & flags,const std::set<int32_t> & destinationPortIds)1646 DeviceHalAidl::Ports::iterator DeviceHalAidl::findPort(
1647 const AudioConfig& config, const AudioIoFlags& flags,
1648 const std::set<int32_t>& destinationPortIds) {
1649 auto belongsToProfile = [&config](const AudioProfile& prof) {
1650 return (isDefaultAudioFormat(config.base.format) || prof.format == config.base.format) &&
1651 (config.base.channelMask.getTag() == AudioChannelLayout::none ||
1652 std::find(prof.channelMasks.begin(), prof.channelMasks.end(),
1653 config.base.channelMask) != prof.channelMasks.end()) &&
1654 (config.base.sampleRate == 0 ||
1655 std::find(prof.sampleRates.begin(), prof.sampleRates.end(),
1656 config.base.sampleRate) != prof.sampleRates.end());
1657 };
1658 static const std::vector<AudioOutputFlags> kOptionalOutputFlags{AudioOutputFlags::BIT_PERFECT};
1659 int optionalFlags = 0;
1660 auto flagMatches = [&flags, &optionalFlags](const AudioIoFlags& portFlags) {
1661 // Ports should be able to match if the optional flags are not requested.
1662 return portFlags == flags ||
1663 (portFlags.getTag() == AudioIoFlags::Tag::output &&
1664 AudioIoFlags::make<AudioIoFlags::Tag::output>(
1665 portFlags.get<AudioIoFlags::Tag::output>() &
1666 ~optionalFlags) == flags);
1667 };
1668 auto matcher = [&](const auto& pair) {
1669 const auto& p = pair.second;
1670 return p.ext.getTag() == AudioPortExt::Tag::mix &&
1671 flagMatches(p.flags) &&
1672 (destinationPortIds.empty() ||
1673 std::any_of(destinationPortIds.begin(), destinationPortIds.end(),
1674 [&](const int32_t destId) { return mRoutingMatrix.count(
1675 std::make_pair(p.id, destId)) != 0; })) &&
1676 (p.profiles.empty() ||
1677 std::find_if(p.profiles.begin(), p.profiles.end(), belongsToProfile) !=
1678 p.profiles.end()); };
1679 auto result = std::find_if(mPorts.begin(), mPorts.end(), matcher);
1680 if (result == mPorts.end() && flags.getTag() == AudioIoFlags::Tag::output) {
1681 auto optionalOutputFlagsIt = kOptionalOutputFlags.begin();
1682 while (result == mPorts.end() && optionalOutputFlagsIt != kOptionalOutputFlags.end()) {
1683 if (isBitPositionFlagSet(
1684 flags.get<AudioIoFlags::Tag::output>(), *optionalOutputFlagsIt)) {
1685 // If the flag is set by the request, it must be matched.
1686 ++optionalOutputFlagsIt;
1687 continue;
1688 }
1689 optionalFlags |= makeBitPositionFlagMask(*optionalOutputFlagsIt++);
1690 result = std::find_if(mPorts.begin(), mPorts.end(), matcher);
1691 ALOGI("%s: port for config %s, flags %s was not found in the module %s, "
1692 "retried with excluding optional flags %#x", __func__, config.toString().c_str(),
1693 flags.toString().c_str(), mInstance.c_str(), optionalFlags);
1694 }
1695 }
1696 return result;
1697 }
1698
findPortConfig(const AudioDevice & device)1699 DeviceHalAidl::PortConfigs::iterator DeviceHalAidl::findPortConfig(const AudioDevice& device) {
1700 return std::find_if(mPortConfigs.begin(), mPortConfigs.end(),
1701 [&](const auto& pair) { return audioDeviceMatches(device, pair.second); });
1702 }
1703
findPortConfig(const AudioConfig & config,const std::optional<AudioIoFlags> & flags,int32_t ioHandle)1704 DeviceHalAidl::PortConfigs::iterator DeviceHalAidl::findPortConfig(
1705 const AudioConfig& config, const std::optional<AudioIoFlags>& flags, int32_t ioHandle) {
1706 using Tag = AudioPortExt::Tag;
1707 return std::find_if(mPortConfigs.begin(), mPortConfigs.end(),
1708 [&](const auto& pair) {
1709 const auto& p = pair.second;
1710 LOG_ALWAYS_FATAL_IF(p.ext.getTag() == Tag::mix &&
1711 !p.sampleRate.has_value() || !p.channelMask.has_value() ||
1712 !p.format.has_value() || !p.flags.has_value(),
1713 "%s: stored mix port config is not fully specified: %s",
1714 __func__, p.toString().c_str());
1715 return p.ext.getTag() == Tag::mix &&
1716 isConfigEqualToPortConfig(config, p) &&
1717 (!flags.has_value() || p.flags.value() == flags.value()) &&
1718 p.ext.template get<Tag::mix>().handle == ioHandle; });
1719 }
1720
isPortHeldByAStream(int32_t portId)1721 bool DeviceHalAidl::isPortHeldByAStream(int32_t portId) {
1722 // It is assumed that mStreams has already been cleaned up.
1723 for (const auto& streamPair : mStreams) {
1724 int32_t patchId = streamPair.second;
1725 auto patchIt = mPatches.find(patchId);
1726 if (patchIt == mPatches.end()) continue;
1727 for (int32_t id : patchIt->second.sourcePortConfigIds) {
1728 auto portConfigIt = mPortConfigs.find(id);
1729 if (portConfigIt != mPortConfigs.end() && portConfigIt->second.portId == portId) {
1730 return true;
1731 }
1732 }
1733 for (int32_t id : patchIt->second.sinkPortConfigIds) {
1734 auto portConfigIt = mPortConfigs.find(id);
1735 if (portConfigIt != mPortConfigs.end() && portConfigIt->second.portId == portId) {
1736 return true;
1737 }
1738 }
1739 }
1740 return false;
1741 }
1742
resetPatch(int32_t patchId)1743 void DeviceHalAidl::resetPatch(int32_t patchId) {
1744 if (auto it = mPatches.find(patchId); it != mPatches.end()) {
1745 mPatches.erase(it);
1746 TIME_CHECK();
1747 if (ndk::ScopedAStatus status = mModule->resetAudioPatch(patchId); !status.isOk()) {
1748 ALOGE("%s: error while resetting patch %d: %s",
1749 __func__, patchId, status.getDescription().c_str());
1750 }
1751 return;
1752 }
1753 ALOGE("%s: patch id %d not found", __func__, patchId);
1754 }
1755
resetPortConfig(int32_t portConfigId)1756 void DeviceHalAidl::resetPortConfig(int32_t portConfigId) {
1757 if (auto it = mPortConfigs.find(portConfigId); it != mPortConfigs.end()) {
1758 mPortConfigs.erase(it);
1759 TIME_CHECK();
1760 if (ndk::ScopedAStatus status = mModule->resetAudioPortConfig(portConfigId);
1761 !status.isOk()) {
1762 ALOGE("%s: error while resetting port config %d: %s",
1763 __func__, portConfigId, status.getDescription().c_str());
1764 }
1765 return;
1766 }
1767 ALOGE("%s: port config id %d not found", __func__, portConfigId);
1768 }
1769
resetUnusedPatches()1770 void DeviceHalAidl::resetUnusedPatches() {
1771 // Since patches can be created independently of streams via 'createAudioPatch',
1772 // here we only clean up patches for released streams.
1773 for (auto it = mStreams.begin(); it != mStreams.end(); ) {
1774 if (auto streamSp = it->first.promote(); streamSp) {
1775 ++it;
1776 } else {
1777 resetPatch(it->second);
1778 it = mStreams.erase(it);
1779 }
1780 }
1781 }
1782
resetUnusedPatchesAndPortConfigs()1783 void DeviceHalAidl::resetUnusedPatchesAndPortConfigs() {
1784 resetUnusedPatches();
1785 resetUnusedPortConfigs();
1786 }
1787
resetUnusedPortConfigs()1788 void DeviceHalAidl::resetUnusedPortConfigs() {
1789 // The assumption is that port configs are used to create patches
1790 // (or to open streams, but that involves creation of patches, too). Thus,
1791 // orphaned port configs can and should be reset.
1792 std::map<int32_t, int32_t /*portID*/> portConfigIds;
1793 std::transform(mPortConfigs.begin(), mPortConfigs.end(),
1794 std::inserter(portConfigIds, portConfigIds.end()),
1795 [](const auto& pcPair) { return std::make_pair(pcPair.first, pcPair.second.portId); });
1796 for (const auto& p : mPatches) {
1797 for (int32_t id : p.second.sourcePortConfigIds) portConfigIds.erase(id);
1798 for (int32_t id : p.second.sinkPortConfigIds) portConfigIds.erase(id);
1799 }
1800 for (int32_t id : mInitialPortConfigIds) {
1801 portConfigIds.erase(id);
1802 }
1803 std::set<int32_t> retryDeviceDisconnection;
1804 for (const auto& portConfigAndIdPair : portConfigIds) {
1805 resetPortConfig(portConfigAndIdPair.first);
1806 if (const auto it = mConnectedPorts.find(portConfigAndIdPair.second);
1807 it != mConnectedPorts.end() && it->second) {
1808 retryDeviceDisconnection.insert(portConfigAndIdPair.second);
1809 }
1810 }
1811 for (int32_t portId : retryDeviceDisconnection) {
1812 if (!isPortHeldByAStream(portId)) {
1813 TIME_CHECK();
1814 if (auto status = mModule->disconnectExternalDevice(portId); status.isOk()) {
1815 mPorts.erase(portId);
1816 mConnectedPorts.erase(portId);
1817 ALOGD("%s: executed postponed external device disconnection for port ID %d",
1818 __func__, portId);
1819 }
1820 }
1821 }
1822 if (!retryDeviceDisconnection.empty()) {
1823 updateRoutes();
1824 }
1825 }
1826
updateRoutes()1827 status_t DeviceHalAidl::updateRoutes() {
1828 TIME_CHECK();
1829 RETURN_STATUS_IF_ERROR(
1830 statusTFromBinderStatus(mModule->getAudioRoutes(&mRoutes)));
1831 ALOGW_IF(mRoutes.empty(), "%s: module %s returned an empty list of audio routes",
1832 __func__, mInstance.c_str());
1833 mRoutingMatrix.clear();
1834 for (const auto& r : mRoutes) {
1835 for (auto portId : r.sourcePortIds) {
1836 mRoutingMatrix.emplace(r.sinkPortId, portId);
1837 mRoutingMatrix.emplace(portId, r.sinkPortId);
1838 }
1839 }
1840 return OK;
1841 }
1842
clearCallbacks(void * cookie)1843 void DeviceHalAidl::clearCallbacks(void* cookie) {
1844 std::lock_guard l(mLock);
1845 mCallbacks.erase(cookie);
1846 }
1847
getStreamOutCallback(void * cookie)1848 sp<StreamOutHalInterfaceCallback> DeviceHalAidl::getStreamOutCallback(void* cookie) {
1849 return getCallbackImpl(cookie, &Callbacks::out);
1850 }
1851
setStreamOutCallback(void * cookie,const sp<StreamOutHalInterfaceCallback> & cb)1852 void DeviceHalAidl::setStreamOutCallback(
1853 void* cookie, const sp<StreamOutHalInterfaceCallback>& cb) {
1854 setCallbackImpl(cookie, &Callbacks::out, cb);
1855 }
1856
getStreamOutEventCallback(void * cookie)1857 sp<StreamOutHalInterfaceEventCallback> DeviceHalAidl::getStreamOutEventCallback(
1858 void* cookie) {
1859 return getCallbackImpl(cookie, &Callbacks::event);
1860 }
1861
setStreamOutEventCallback(void * cookie,const sp<StreamOutHalInterfaceEventCallback> & cb)1862 void DeviceHalAidl::setStreamOutEventCallback(
1863 void* cookie, const sp<StreamOutHalInterfaceEventCallback>& cb) {
1864 setCallbackImpl(cookie, &Callbacks::event, cb);
1865 }
1866
getStreamOutLatencyModeCallback(void * cookie)1867 sp<StreamOutHalInterfaceLatencyModeCallback> DeviceHalAidl::getStreamOutLatencyModeCallback(
1868 void* cookie) {
1869 return getCallbackImpl(cookie, &Callbacks::latency);
1870 }
1871
setStreamOutLatencyModeCallback(void * cookie,const sp<StreamOutHalInterfaceLatencyModeCallback> & cb)1872 void DeviceHalAidl::setStreamOutLatencyModeCallback(
1873 void* cookie, const sp<StreamOutHalInterfaceLatencyModeCallback>& cb) {
1874 setCallbackImpl(cookie, &Callbacks::latency, cb);
1875 }
1876
1877 template<class C>
getCallbackImpl(void * cookie,wp<C> DeviceHalAidl::Callbacks::* field)1878 sp<C> DeviceHalAidl::getCallbackImpl(void* cookie, wp<C> DeviceHalAidl::Callbacks::* field) {
1879 std::lock_guard l(mLock);
1880 if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
1881 return ((it->second).*field).promote();
1882 }
1883 return nullptr;
1884 }
1885 template<class C>
setCallbackImpl(void * cookie,wp<C> DeviceHalAidl::Callbacks::* field,const sp<C> & cb)1886 void DeviceHalAidl::setCallbackImpl(
1887 void* cookie, wp<C> DeviceHalAidl::Callbacks::* field, const sp<C>& cb) {
1888 std::lock_guard l(mLock);
1889 if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
1890 (it->second).*field = cb;
1891 }
1892 }
1893
1894 } // namespace android
1895