• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define LOG_TAG "DeviceHalAidl"
18 // #define LOG_NDEBUG 0
19 
20 #include <algorithm>
21 #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 &parameters) {
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 &parameters) {
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 &parameters) {
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 &parameters) {
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 &parameters) {
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 &parameters) {
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