1 /*
2 * Copyright (C) 2018 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 "DeviceHAL"
18
19 #include "core/default/Device.h"
20 #include "common/all-versions/default/EffectMap.h"
21 #include "core/default/StreamIn.h"
22 #include "core/default/StreamOut.h"
23 #include "core/default/Util.h"
24
25 //#define LOG_NDEBUG 0
26
27 #include <inttypes.h>
28 #include <memory.h>
29 #include <string.h>
30 #include <algorithm>
31
32 #include <android/log.h>
33 #include <mediautils/MemoryLeakTrackUtil.h>
34 #include <memunreachable/memunreachable.h>
35
36 #include <HidlUtils.h>
37
38 namespace android {
39 namespace hardware {
40 namespace audio {
41 namespace CPP_VERSION {
42 namespace implementation {
43
44 using ::android::hardware::audio::common::CPP_VERSION::implementation::HidlUtils;
45
Device(audio_hw_device_t * device)46 Device::Device(audio_hw_device_t* device) : mIsClosed(false), mDevice(device) {}
47
~Device()48 Device::~Device() {
49 (void)doClose();
50 mDevice = nullptr;
51 }
52
analyzeStatus(const char * funcName,int status,const std::vector<int> & ignoreErrors)53 Result Device::analyzeStatus(const char* funcName, int status,
54 const std::vector<int>& ignoreErrors) {
55 return util::analyzeStatus("Device", funcName, status, ignoreErrors);
56 }
57
closeInputStream(audio_stream_in_t * stream)58 void Device::closeInputStream(audio_stream_in_t* stream) {
59 mDevice->close_input_stream(mDevice, stream);
60 LOG_ALWAYS_FATAL_IF(mOpenedStreamsCount == 0, "mOpenedStreamsCount is already 0");
61 --mOpenedStreamsCount;
62 }
63
closeOutputStream(audio_stream_out_t * stream)64 void Device::closeOutputStream(audio_stream_out_t* stream) {
65 mDevice->close_output_stream(mDevice, stream);
66 LOG_ALWAYS_FATAL_IF(mOpenedStreamsCount == 0, "mOpenedStreamsCount is already 0");
67 --mOpenedStreamsCount;
68 }
69
halGetParameters(const char * keys)70 char* Device::halGetParameters(const char* keys) {
71 return mDevice->get_parameters(mDevice, keys);
72 }
73
halSetParameters(const char * keysAndValues)74 int Device::halSetParameters(const char* keysAndValues) {
75 return mDevice->set_parameters(mDevice, keysAndValues);
76 }
77
78 // Methods from ::android::hardware::audio::CPP_VERSION::IDevice follow.
initCheck()79 Return<Result> Device::initCheck() {
80 return analyzeStatus("init_check", mDevice->init_check(mDevice));
81 }
82
setMasterVolume(float volume)83 Return<Result> Device::setMasterVolume(float volume) {
84 if (mDevice->set_master_volume == NULL) {
85 return Result::NOT_SUPPORTED;
86 }
87 if (!isGainNormalized(volume)) {
88 ALOGW("Can not set a master volume (%f) outside [0,1]", volume);
89 return Result::INVALID_ARGUMENTS;
90 }
91 return analyzeStatus("set_master_volume", mDevice->set_master_volume(mDevice, volume),
92 {ENOSYS} /*ignore*/);
93 }
94
getMasterVolume(getMasterVolume_cb _hidl_cb)95 Return<void> Device::getMasterVolume(getMasterVolume_cb _hidl_cb) {
96 Result retval(Result::NOT_SUPPORTED);
97 float volume = 0;
98 if (mDevice->get_master_volume != NULL) {
99 retval = analyzeStatus("get_master_volume", mDevice->get_master_volume(mDevice, &volume),
100 {ENOSYS} /*ignore*/);
101 }
102 _hidl_cb(retval, volume);
103 return Void();
104 }
105
setMicMute(bool mute)106 Return<Result> Device::setMicMute(bool mute) {
107 return analyzeStatus("set_mic_mute", mDevice->set_mic_mute(mDevice, mute), {ENOSYS} /*ignore*/);
108 }
109
getMicMute(getMicMute_cb _hidl_cb)110 Return<void> Device::getMicMute(getMicMute_cb _hidl_cb) {
111 bool mute = false;
112 Result retval = analyzeStatus("get_mic_mute", mDevice->get_mic_mute(mDevice, &mute),
113 {ENOSYS} /*ignore*/);
114 _hidl_cb(retval, mute);
115 return Void();
116 }
117
setMasterMute(bool mute)118 Return<Result> Device::setMasterMute(bool mute) {
119 Result retval(Result::NOT_SUPPORTED);
120 if (mDevice->set_master_mute != NULL) {
121 retval = analyzeStatus("set_master_mute", mDevice->set_master_mute(mDevice, mute),
122 {ENOSYS} /*ignore*/);
123 }
124 return retval;
125 }
126
getMasterMute(getMasterMute_cb _hidl_cb)127 Return<void> Device::getMasterMute(getMasterMute_cb _hidl_cb) {
128 Result retval(Result::NOT_SUPPORTED);
129 bool mute = false;
130 if (mDevice->get_master_mute != NULL) {
131 retval = analyzeStatus("get_master_mute", mDevice->get_master_mute(mDevice, &mute),
132 {ENOSYS} /*ignore*/);
133 }
134 _hidl_cb(retval, mute);
135 return Void();
136 }
137
getInputBufferSize(const AudioConfig & config,getInputBufferSize_cb _hidl_cb)138 Return<void> Device::getInputBufferSize(const AudioConfig& config, getInputBufferSize_cb _hidl_cb) {
139 audio_config_t halConfig;
140 Result retval(Result::INVALID_ARGUMENTS);
141 uint64_t bufferSize = 0;
142 if (HidlUtils::audioConfigToHal(config, &halConfig) == NO_ERROR) {
143 size_t halBufferSize = mDevice->get_input_buffer_size(mDevice, &halConfig);
144 if (halBufferSize != 0) {
145 retval = Result::OK;
146 bufferSize = halBufferSize;
147 }
148 }
149 _hidl_cb(retval, bufferSize);
150 return Void();
151 }
152
openOutputStreamImpl(int32_t ioHandle,const DeviceAddress & device,const AudioConfig & config,const AudioOutputFlags & flags,AudioConfig * suggestedConfig)153 std::tuple<Result, sp<IStreamOut>> Device::openOutputStreamImpl(int32_t ioHandle,
154 const DeviceAddress& device,
155 const AudioConfig& config,
156 const AudioOutputFlags& flags,
157 AudioConfig* suggestedConfig) {
158 audio_config_t halConfig;
159 if (HidlUtils::audioConfigToHal(config, &halConfig) != NO_ERROR) {
160 return {Result::INVALID_ARGUMENTS, nullptr};
161 }
162 audio_stream_out_t* halStream;
163 audio_devices_t halDevice;
164 char halDeviceAddress[AUDIO_DEVICE_MAX_ADDRESS_LEN];
165 if (CoreUtils::deviceAddressToHal(device, &halDevice, halDeviceAddress) != NO_ERROR) {
166 return {Result::INVALID_ARGUMENTS, nullptr};
167 }
168 audio_output_flags_t halFlags;
169 if (CoreUtils::audioOutputFlagsToHal(flags, &halFlags) != NO_ERROR) {
170 return {Result::INVALID_ARGUMENTS, nullptr};
171 }
172 ALOGV("open_output_stream handle: %d devices: %x flags: %#x "
173 "srate: %d format %#x channels %x address %s",
174 ioHandle, halDevice, halFlags, halConfig.sample_rate, halConfig.format,
175 halConfig.channel_mask, halDeviceAddress);
176 int status = mDevice->open_output_stream(mDevice, ioHandle, halDevice, halFlags, &halConfig,
177 &halStream, halDeviceAddress);
178 ALOGV("open_output_stream status %d stream %p", status, halStream);
179 sp<IStreamOut> streamOut;
180 if (status == OK) {
181 streamOut = new StreamOut(this, halStream);
182 ++mOpenedStreamsCount;
183 }
184 status_t convertStatus =
185 HidlUtils::audioConfigFromHal(halConfig, false /*isInput*/, suggestedConfig);
186 ALOGW_IF(convertStatus != OK, "%s: suggested config with incompatible fields", __func__);
187 return {analyzeStatus("open_output_stream", status, {EINVAL} /*ignore*/), streamOut};
188 }
189
openInputStreamImpl(int32_t ioHandle,const DeviceAddress & device,const AudioConfig & config,const AudioInputFlags & flags,AudioSource source,AudioConfig * suggestedConfig)190 std::tuple<Result, sp<IStreamIn>> Device::openInputStreamImpl(
191 int32_t ioHandle, const DeviceAddress& device, const AudioConfig& config,
192 const AudioInputFlags& flags, AudioSource source, AudioConfig* suggestedConfig) {
193 audio_config_t halConfig;
194 if (HidlUtils::audioConfigToHal(config, &halConfig) != NO_ERROR) {
195 return {Result::INVALID_ARGUMENTS, nullptr};
196 }
197 audio_stream_in_t* halStream;
198 audio_devices_t halDevice;
199 char halDeviceAddress[AUDIO_DEVICE_MAX_ADDRESS_LEN];
200 if (CoreUtils::deviceAddressToHal(device, &halDevice, halDeviceAddress) != NO_ERROR) {
201 return {Result::INVALID_ARGUMENTS, nullptr};
202 }
203 audio_input_flags_t halFlags;
204 audio_source_t halSource;
205 if (CoreUtils::audioInputFlagsToHal(flags, &halFlags) != NO_ERROR ||
206 HidlUtils::audioSourceToHal(source, &halSource) != NO_ERROR) {
207 return {Result::INVALID_ARGUMENTS, nullptr};
208 }
209 ALOGV("open_input_stream handle: %d devices: %x flags: %#x "
210 "srate: %d format %#x channels %x address %s source %d",
211 ioHandle, halDevice, halFlags, halConfig.sample_rate, halConfig.format,
212 halConfig.channel_mask, halDeviceAddress, halSource);
213 int status = mDevice->open_input_stream(mDevice, ioHandle, halDevice, &halConfig, &halStream,
214 halFlags, halDeviceAddress, halSource);
215 ALOGV("open_input_stream status %d stream %p", status, halStream);
216 sp<IStreamIn> streamIn;
217 if (status == OK) {
218 streamIn = new StreamIn(this, halStream);
219 ++mOpenedStreamsCount;
220 }
221 status_t convertStatus =
222 HidlUtils::audioConfigFromHal(halConfig, true /*isInput*/, suggestedConfig);
223 ALOGW_IF(convertStatus != OK, "%s: suggested config with incompatible fields", __func__);
224 return {analyzeStatus("open_input_stream", status, {EINVAL} /*ignore*/), streamIn};
225 }
226
227 #if MAJOR_VERSION == 2
openOutputStream(int32_t ioHandle,const DeviceAddress & device,const AudioConfig & config,AudioOutputFlags flags,openOutputStream_cb _hidl_cb)228 Return<void> Device::openOutputStream(int32_t ioHandle, const DeviceAddress& device,
229 const AudioConfig& config, AudioOutputFlags flags,
230 openOutputStream_cb _hidl_cb) {
231 AudioConfig suggestedConfig;
232 auto [result, streamOut] =
233 openOutputStreamImpl(ioHandle, device, config, flags, &suggestedConfig);
234 _hidl_cb(result, streamOut, suggestedConfig);
235 return Void();
236 }
237
openInputStream(int32_t ioHandle,const DeviceAddress & device,const AudioConfig & config,AudioInputFlags flags,AudioSource source,openInputStream_cb _hidl_cb)238 Return<void> Device::openInputStream(int32_t ioHandle, const DeviceAddress& device,
239 const AudioConfig& config, AudioInputFlags flags,
240 AudioSource source, openInputStream_cb _hidl_cb) {
241 AudioConfig suggestedConfig;
242 auto [result, streamIn] =
243 openInputStreamImpl(ioHandle, device, config, flags, source, &suggestedConfig);
244 _hidl_cb(result, streamIn, suggestedConfig);
245 return Void();
246 }
247
248 #elif MAJOR_VERSION >= 4
openOutputStream(int32_t ioHandle,const DeviceAddress & device,const AudioConfig & config,AudioOutputFlags flags,const SourceMetadata & sourceMetadata,openOutputStream_cb _hidl_cb)249 Return<void> Device::openOutputStream(int32_t ioHandle, const DeviceAddress& device,
250 const AudioConfig& config,
251 #if MAJOR_VERSION <= 6
252 AudioOutputFlags flags,
253 #else
254 const AudioOutputFlags& flags,
255 #endif
256 const SourceMetadata& sourceMetadata,
257 openOutputStream_cb _hidl_cb) {
258 #if MAJOR_VERSION <= 6
259 if (status_t status = CoreUtils::sourceMetadataToHal(sourceMetadata, nullptr);
260 status != NO_ERROR) {
261 #else
262 if (status_t status = CoreUtils::sourceMetadataToHalV7(sourceMetadata,
263 false /*ignoreNonVendorTags*/, nullptr);
264 status != NO_ERROR) {
265 #endif
266 _hidl_cb(analyzeStatus("sourceMetadataToHal", status), nullptr, AudioConfig{});
267 return Void();
268 }
269 AudioConfig suggestedConfig;
270 auto [result, streamOut] =
271 openOutputStreamImpl(ioHandle, device, config, flags, &suggestedConfig);
272 if (streamOut) {
273 streamOut->updateSourceMetadata(sourceMetadata);
274 }
275 _hidl_cb(result, streamOut, suggestedConfig);
276 return Void();
277 }
278
279 Return<void> Device::openInputStream(int32_t ioHandle, const DeviceAddress& device,
280 const AudioConfig& config,
281 #if MAJOR_VERSION <= 6
282 AudioInputFlags flags,
283 #else
284 const AudioInputFlags& flags,
285 #endif
286 const SinkMetadata& sinkMetadata,
287 openInputStream_cb _hidl_cb) {
288 if (sinkMetadata.tracks.size() == 0) {
289 // This should never happen, the framework must not create as stream
290 // if there is no client
291 ALOGE("openInputStream called without tracks connected");
292 _hidl_cb(Result::INVALID_ARGUMENTS, nullptr, AudioConfig{});
293 return Void();
294 }
295 #if MAJOR_VERSION <= 6
296 if (status_t status = CoreUtils::sinkMetadataToHal(sinkMetadata, nullptr); status != NO_ERROR) {
297 #else
298 if (status_t status = CoreUtils::sinkMetadataToHalV7(sinkMetadata,
299 false /*ignoreNonVendorTags*/, nullptr);
300 status != NO_ERROR) {
301 #endif
302 _hidl_cb(analyzeStatus("sinkMetadataToHal", status), nullptr, AudioConfig{});
303 return Void();
304 }
305 // Pick the first one as the main.
306 AudioSource source = sinkMetadata.tracks[0].source;
307 AudioConfig suggestedConfig;
308 auto [result, streamIn] =
309 openInputStreamImpl(ioHandle, device, config, flags, source, &suggestedConfig);
310 if (streamIn) {
311 streamIn->updateSinkMetadata(sinkMetadata);
312 }
313 _hidl_cb(result, streamIn, suggestedConfig);
314 return Void();
315 }
316 #endif /* MAJOR_VERSION */
317
318 Return<bool> Device::supportsAudioPatches() {
319 return version() >= AUDIO_DEVICE_API_VERSION_3_0;
320 }
321
322 Return<void> Device::createAudioPatch(const hidl_vec<AudioPortConfig>& sources,
323 const hidl_vec<AudioPortConfig>& sinks,
324 createAudioPatch_cb _hidl_cb) {
325 auto [retval, patch] = createOrUpdateAudioPatch(AudioPatchHandle{}, sources, sinks);
326 _hidl_cb(retval, patch);
327 return Void();
328 }
329
330 std::tuple<Result, AudioPatchHandle> Device::createOrUpdateAudioPatch(
331 AudioPatchHandle patch, const hidl_vec<AudioPortConfig>& sources,
332 const hidl_vec<AudioPortConfig>& sinks) {
333 Result retval(Result::NOT_SUPPORTED);
334 if (version() >= AUDIO_DEVICE_API_VERSION_3_0) {
335 audio_patch_handle_t halPatch = static_cast<audio_patch_handle_t>(patch);
336 std::unique_ptr<audio_port_config[]> halSources;
337 if (status_t status = HidlUtils::audioPortConfigsToHal(sources, &halSources);
338 status != NO_ERROR) {
339 return {analyzeStatus("audioPortConfigsToHal;sources", status), patch};
340 }
341 std::unique_ptr<audio_port_config[]> halSinks;
342 if (status_t status = HidlUtils::audioPortConfigsToHal(sinks, &halSinks);
343 status != NO_ERROR) {
344 return {analyzeStatus("audioPortConfigsToHal;sinks", status), patch};
345 }
346 retval = analyzeStatus("create_audio_patch",
347 mDevice->create_audio_patch(mDevice, sources.size(), &halSources[0],
348 sinks.size(), &halSinks[0], &halPatch));
349 if (retval == Result::OK) {
350 patch = static_cast<AudioPatchHandle>(halPatch);
351 }
352 }
353 return {retval, patch};
354 }
355
356 Return<Result> Device::releaseAudioPatch(int32_t patch) {
357 if (version() >= AUDIO_DEVICE_API_VERSION_3_0) {
358 return analyzeStatus(
359 "release_audio_patch",
360 mDevice->release_audio_patch(mDevice, static_cast<audio_patch_handle_t>(patch)));
361 }
362 return Result::NOT_SUPPORTED;
363 }
364
365 template <typename HalPort>
366 Return<void> Device::getAudioPortImpl(const AudioPort& port, getAudioPort_cb _hidl_cb,
367 int (*halGetter)(audio_hw_device_t*, HalPort*),
368 const char* halGetterName) {
369 HalPort halPort;
370 if (status_t status = HidlUtils::audioPortToHal(port, &halPort); status != NO_ERROR) {
371 _hidl_cb(analyzeStatus("audioPortToHal", status), port);
372 return Void();
373 }
374 Result retval = analyzeStatus(halGetterName, halGetter(mDevice, &halPort));
375 AudioPort resultPort = port;
376 if (retval == Result::OK) {
377 if (status_t status = HidlUtils::audioPortFromHal(halPort, &resultPort);
378 status != NO_ERROR) {
379 _hidl_cb(analyzeStatus("audioPortFromHal", status), port);
380 return Void();
381 }
382 }
383 _hidl_cb(retval, resultPort);
384 return Void();
385 }
386
387 #if MAJOR_VERSION <= 6
388 Return<void> Device::getAudioPort(const AudioPort& port, getAudioPort_cb _hidl_cb) {
389 return getAudioPortImpl(port, _hidl_cb, mDevice->get_audio_port, "get_audio_port");
390 }
391 #else
392 Return<void> Device::getAudioPort(const AudioPort& port, getAudioPort_cb _hidl_cb) {
393 if (version() >= AUDIO_DEVICE_API_VERSION_3_2) {
394 // get_audio_port_v7 is mandatory if legacy HAL support this API version.
395 return getAudioPortImpl(port, _hidl_cb, mDevice->get_audio_port_v7, "get_audio_port_v7");
396 } else {
397 return getAudioPortImpl(port, _hidl_cb, mDevice->get_audio_port, "get_audio_port");
398 }
399 }
400 #endif
401
402 Return<Result> Device::setAudioPortConfig(const AudioPortConfig& config) {
403 if (version() >= AUDIO_DEVICE_API_VERSION_3_0) {
404 struct audio_port_config halPortConfig;
405 if (status_t status = HidlUtils::audioPortConfigToHal(config, &halPortConfig);
406 status != NO_ERROR) {
407 return analyzeStatus("audioPortConfigToHal", status);
408 }
409 return analyzeStatus("set_audio_port_config",
410 mDevice->set_audio_port_config(mDevice, &halPortConfig));
411 }
412 return Result::NOT_SUPPORTED;
413 }
414
415 #if MAJOR_VERSION == 2
416 Return<AudioHwSync> Device::getHwAvSync() {
417 int halHwAvSync;
418 Result retval = getParam(AudioParameter::keyHwAvSync, &halHwAvSync);
419 return retval == Result::OK ? halHwAvSync : AUDIO_HW_SYNC_INVALID;
420 }
421 #elif MAJOR_VERSION >= 4
422 Return<void> Device::getHwAvSync(getHwAvSync_cb _hidl_cb) {
423 int halHwAvSync;
424 Result retval = getParam(AudioParameter::keyHwAvSync, &halHwAvSync);
425 _hidl_cb(retval, halHwAvSync);
426 return Void();
427 }
428 #endif
429
430 Return<Result> Device::setScreenState(bool turnedOn) {
431 return setParam(AudioParameter::keyScreenState, turnedOn);
432 }
433
434 #if MAJOR_VERSION == 2
435 Return<void> Device::getParameters(const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb) {
436 getParametersImpl({}, keys, _hidl_cb);
437 return Void();
438 }
439
440 Return<Result> Device::setParameters(const hidl_vec<ParameterValue>& parameters) {
441 return setParametersImpl({} /* context */, parameters);
442 }
443 #elif MAJOR_VERSION >= 4
444 Return<void> Device::getParameters(const hidl_vec<ParameterValue>& context,
445 const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb) {
446 getParametersImpl(context, keys, _hidl_cb);
447 return Void();
448 }
449 Return<Result> Device::setParameters(const hidl_vec<ParameterValue>& context,
450 const hidl_vec<ParameterValue>& parameters) {
451 return setParametersImpl(context, parameters);
452 }
453 #endif
454
455 #if MAJOR_VERSION == 2
456 Return<void> Device::debugDump(const hidl_handle& fd) {
457 return debug(fd, {});
458 }
459 #endif
460
461 Return<void> Device::debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) {
462 if (fd.getNativeHandle() != nullptr && fd->numFds == 1) {
463 const int fd0 = fd->data[0];
464 bool dumpMem = false;
465 bool unreachableMemory = false;
466 for (const auto& option : options) {
467 if (option == "-m") {
468 dumpMem = true;
469 } else if (option == "--unreachable") {
470 unreachableMemory = true;
471 }
472 }
473
474 if (dumpMem) {
475 dprintf(fd0, "\nDumping memory:\n");
476 std::string s = dumpMemoryAddresses(100 /* limit */);
477 write(fd0, s.c_str(), s.size());
478 }
479 if (unreachableMemory) {
480 dprintf(fd0, "\nDumping unreachable memory:\n");
481 // TODO - should limit be an argument parameter?
482 std::string s = GetUnreachableMemoryString(true /* contents */, 100 /* limit */);
483 write(fd0, s.c_str(), s.size());
484 }
485
486 analyzeStatus("dump", mDevice->dump(mDevice, fd0));
487 }
488 return Void();
489 }
490
491 #if MAJOR_VERSION >= 4
492 Return<void> Device::getMicrophones(getMicrophones_cb _hidl_cb) {
493 Result retval = Result::NOT_SUPPORTED;
494 size_t actual_mics = AUDIO_MICROPHONE_MAX_COUNT;
495 audio_microphone_characteristic_t mic_array[AUDIO_MICROPHONE_MAX_COUNT];
496
497 hidl_vec<MicrophoneInfo> microphones;
498 if (mDevice->get_microphones != NULL &&
499 mDevice->get_microphones(mDevice, &mic_array[0], &actual_mics) == 0) {
500 microphones.resize(actual_mics);
501 for (size_t i = 0; i < actual_mics; ++i) {
502 (void)CoreUtils::microphoneInfoFromHal(mic_array[i], µphones[i]);
503 }
504 retval = Result::OK;
505 }
506 _hidl_cb(retval, microphones);
507 return Void();
508 }
509
510 Return<Result> Device::setConnectedState(const DeviceAddress& address, bool connected) {
511 auto key = connected ? AudioParameter::keyDeviceConnect : AudioParameter::keyDeviceDisconnect;
512 return setParam(key, address);
513 }
514 #endif
515
516 Result Device::doClose() {
517 if (mIsClosed || mOpenedStreamsCount != 0) return Result::INVALID_STATE;
518 mIsClosed = true;
519 return analyzeStatus("close", audio_hw_device_close(mDevice));
520 }
521
522 #if MAJOR_VERSION >= 6
523 Return<Result> Device::close() {
524 return doClose();
525 }
526
527 Return<Result> Device::addDeviceEffect(AudioPortHandle device, uint64_t effectId) {
528 if (version() < AUDIO_DEVICE_API_VERSION_3_1 || mDevice->add_device_effect == nullptr) {
529 return Result::NOT_SUPPORTED;
530 }
531
532 effect_handle_t halEffect = EffectMap::getInstance().get(effectId);
533 if (halEffect != NULL) {
534 return analyzeStatus("add_device_effect",
535 mDevice->add_device_effect(
536 mDevice, static_cast<audio_port_handle_t>(device), halEffect));
537 } else {
538 ALOGW("%s Invalid effect ID passed from client: %" PRIu64 "", __func__, effectId);
539 return Result::INVALID_ARGUMENTS;
540 }
541 }
542
543 Return<Result> Device::removeDeviceEffect(AudioPortHandle device, uint64_t effectId) {
544 if (version() < AUDIO_DEVICE_API_VERSION_3_1 || mDevice->remove_device_effect == nullptr) {
545 return Result::NOT_SUPPORTED;
546 }
547
548 effect_handle_t halEffect = EffectMap::getInstance().get(effectId);
549 if (halEffect != NULL) {
550 return analyzeStatus("remove_device_effect",
551 mDevice->remove_device_effect(
552 mDevice, static_cast<audio_port_handle_t>(device), halEffect));
553 } else {
554 ALOGW("%s Invalid effect ID passed from client: %" PRIu64 "", __func__, effectId);
555 return Result::INVALID_ARGUMENTS;
556 }
557 }
558
559 Return<void> Device::updateAudioPatch(int32_t previousPatch,
560 const hidl_vec<AudioPortConfig>& sources,
561 const hidl_vec<AudioPortConfig>& sinks,
562 createAudioPatch_cb _hidl_cb) {
563 if (previousPatch != static_cast<int32_t>(AudioPatchHandle{})) {
564 auto [retval, patch] = createOrUpdateAudioPatch(previousPatch, sources, sinks);
565 _hidl_cb(retval, patch);
566 } else {
567 _hidl_cb(Result::INVALID_ARGUMENTS, previousPatch);
568 }
569 return Void();
570 }
571
572 #endif
573
574 } // namespace implementation
575 } // namespace CPP_VERSION
576 } // namespace audio
577 } // namespace hardware
578 } // namespace android
579