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