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