• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 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 #include <stdio.h>
18 
19 #define LOG_TAG "DeviceHalHidl"
20 //#define LOG_NDEBUG 0
21 
22 #include <cutils/native_handle.h>
23 #include <cutils/properties.h>
24 #include <hwbinder/IPCThreadState.h>
25 #include <media/AudioContainers.h>
26 #include <mediautils/TimeCheck.h>
27 #include <utils/Log.h>
28 
29 #include PATH(android/hardware/audio/FILE_VERSION/IPrimaryDevice.h)
30 #include <HidlUtils.h>
31 #include <common/all-versions/VersionUtils.h>
32 #include <util/CoreUtils.h>
33 
34 #include "DeviceHalHidl.h"
35 #include "ParameterUtils.h"
36 #include "StreamHalHidl.h"
37 
38 using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::implementation::HidlUtils;
39 using ::android::hardware::audio::common::utils::EnumBitfield;
40 using ::android::hardware::audio::CORE_TYPES_CPP_VERSION::implementation::CoreUtils;
41 using ::android::hardware::hidl_string;
42 using ::android::hardware::hidl_vec;
43 
44 namespace android {
45 
46 using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
47 using namespace ::android::hardware::audio::CORE_TYPES_CPP_VERSION;
48 
49 #define TIME_CHECK() auto timeCheck = \
50         mediautils::makeTimeCheckStatsForClassMethod(getClassName(), __func__)
51 
DeviceHalHidl(const sp<::android::hardware::audio::CPP_VERSION::IDevice> & device)52 DeviceHalHidl::DeviceHalHidl(const sp<::android::hardware::audio::CPP_VERSION::IDevice>& device)
53         : CoreConversionHelperHidl("DeviceHalHidl"), mDevice(device) {
54 }
55 
DeviceHalHidl(const sp<::android::hardware::audio::CPP_VERSION::IPrimaryDevice> & device)56 DeviceHalHidl::DeviceHalHidl(
57         const sp<::android::hardware::audio::CPP_VERSION::IPrimaryDevice>& device)
58         : CoreConversionHelperHidl("DeviceHalHidl"),
59 #if MAJOR_VERSION <= 6 || (MAJOR_VERSION == 7 && MINOR_VERSION == 0)
60           mDevice(device),
61 #endif
62           mPrimaryDevice(device) {
63 #if MAJOR_VERSION == 7 && MINOR_VERSION == 1
64     auto getDeviceRet = mPrimaryDevice->getDevice();
65     if (getDeviceRet.isOk()) {
66         mDevice = getDeviceRet;
67     } else {
68         ALOGE("Call to IPrimaryDevice.getDevice has failed: %s",
69                 getDeviceRet.description().c_str());
70     }
71 #endif
72 }
73 
~DeviceHalHidl()74 DeviceHalHidl::~DeviceHalHidl() {
75     if (mDevice != 0) {
76 #if MAJOR_VERSION <= 5
77         mDevice.clear();
78         hardware::IPCThreadState::self()->flushCommands();
79 #elif MAJOR_VERSION >= 6
80         mDevice->close();
81 #endif
82     }
83 }
84 
getSupportedDevices(uint32_t *)85 status_t DeviceHalHidl::getSupportedDevices(uint32_t*) {
86     // Obsolete.
87     return INVALID_OPERATION;
88 }
89 
initCheck()90 status_t DeviceHalHidl::initCheck() {
91     TIME_CHECK();
92     if (mDevice == 0) return NO_INIT;
93     return processReturn("initCheck", mDevice->initCheck());
94 }
95 
setVoiceVolume(float volume)96 status_t DeviceHalHidl::setVoiceVolume(float volume) {
97     TIME_CHECK();
98     if (mDevice == 0) return NO_INIT;
99     if (mPrimaryDevice == 0) return INVALID_OPERATION;
100     return processReturn("setVoiceVolume", mPrimaryDevice->setVoiceVolume(volume));
101 }
102 
setMasterVolume(float volume)103 status_t DeviceHalHidl::setMasterVolume(float volume) {
104     TIME_CHECK();
105     if (mDevice == 0) return NO_INIT;
106     return processReturn("setMasterVolume", mDevice->setMasterVolume(volume));
107 }
108 
getMasterVolume(float * volume)109 status_t DeviceHalHidl::getMasterVolume(float *volume) {
110     TIME_CHECK();
111     if (mDevice == 0) return NO_INIT;
112     Result retval;
113     Return<void> ret = mDevice->getMasterVolume(
114             [&](Result r, float v) {
115                 retval = r;
116                 if (retval == Result::OK) {
117                     *volume = v;
118                 }
119             });
120     return processReturn("getMasterVolume", ret, retval);
121 }
122 
setMode(audio_mode_t mode)123 status_t DeviceHalHidl::setMode(audio_mode_t mode) {
124     TIME_CHECK();
125     if (mDevice == 0) return NO_INIT;
126     if (mPrimaryDevice == 0) return INVALID_OPERATION;
127     return processReturn("setMode", mPrimaryDevice->setMode(AudioMode(mode)));
128 }
129 
setMicMute(bool state)130 status_t DeviceHalHidl::setMicMute(bool state) {
131     TIME_CHECK();
132     if (mDevice == 0) return NO_INIT;
133     return processReturn("setMicMute", mDevice->setMicMute(state));
134 }
135 
getMicMute(bool * state)136 status_t DeviceHalHidl::getMicMute(bool *state) {
137     TIME_CHECK();
138     if (mDevice == 0) return NO_INIT;
139     Result retval;
140     Return<void> ret = mDevice->getMicMute(
141             [&](Result r, bool mute) {
142                 retval = r;
143                 if (retval == Result::OK) {
144                     *state = mute;
145                 }
146             });
147     return processReturn("getMicMute", ret, retval);
148 }
149 
setMasterMute(bool state)150 status_t DeviceHalHidl::setMasterMute(bool state) {
151     TIME_CHECK();
152     if (mDevice == 0) return NO_INIT;
153     return processReturn("setMasterMute", mDevice->setMasterMute(state));
154 }
155 
getMasterMute(bool * state)156 status_t DeviceHalHidl::getMasterMute(bool *state) {
157     TIME_CHECK();
158     if (mDevice == 0) return NO_INIT;
159     Result retval;
160     Return<void> ret = mDevice->getMasterMute(
161             [&](Result r, bool mute) {
162                 retval = r;
163                 if (retval == Result::OK) {
164                     *state = mute;
165                 }
166             });
167     return processReturn("getMasterMute", ret, retval);
168 }
169 
setParameters(const String8 & kvPairs)170 status_t DeviceHalHidl::setParameters(const String8& kvPairs) {
171     TIME_CHECK();
172     if (mDevice == 0) return NO_INIT;
173     hidl_vec<ParameterValue> hidlParams;
174     status_t status = parametersFromHal(kvPairs, &hidlParams);
175     if (status != OK) return status;
176     // TODO: change the API so that context and kvPairs are separated
177     return processReturn("setParameters",
178                          utils::setParameters(mDevice, {} /* context */, hidlParams));
179 }
180 
getParameters(const String8 & keys,String8 * values)181 status_t DeviceHalHidl::getParameters(const String8& keys, String8 *values) {
182     TIME_CHECK();
183     values->clear();
184     if (mDevice == 0) return NO_INIT;
185     hidl_vec<hidl_string> hidlKeys;
186     status_t status = keysFromHal(keys, &hidlKeys);
187     if (status != OK) return status;
188     Result retval;
189     Return<void> ret = utils::getParameters(mDevice,
190             {} /* context */,
191             hidlKeys,
192             [&](Result r, const hidl_vec<ParameterValue>& parameters) {
193                 retval = r;
194                 if (retval == Result::OK) {
195                     parametersToHal(parameters, values);
196                 }
197             });
198     return processReturn("getParameters", ret, retval);
199 }
200 
getInputBufferSize(const struct audio_config * config,size_t * size)201 status_t DeviceHalHidl::getInputBufferSize(
202         const struct audio_config *config, size_t *size) {
203     TIME_CHECK();
204     if (mDevice == 0) return NO_INIT;
205     AudioConfig hidlConfig;
206     HidlUtils::audioConfigFromHal(*config, true /*isInput*/, &hidlConfig);
207     Result retval;
208     Return<void> ret = mDevice->getInputBufferSize(
209             hidlConfig,
210             [&](Result r, uint64_t bufferSize) {
211                 retval = r;
212                 if (retval == Result::OK) {
213                     *size = static_cast<size_t>(bufferSize);
214                 }
215             });
216     return processReturn("getInputBufferSize", ret, retval);
217 }
218 
openOutputStream(audio_io_handle_t handle,audio_devices_t deviceType,audio_output_flags_t flags,struct audio_config * config,const char * address,sp<StreamOutHalInterface> * outStream)219 status_t DeviceHalHidl::openOutputStream(
220         audio_io_handle_t handle,
221         audio_devices_t deviceType,
222         audio_output_flags_t flags,
223         struct audio_config *config,
224         const char *address,
225         sp<StreamOutHalInterface> *outStream) {
226     TIME_CHECK();
227     if (mDevice == 0) return NO_INIT;
228     DeviceAddress hidlDevice;
229     if (status_t status = CoreUtils::deviceAddressFromHal(deviceType, address, &hidlDevice);
230             status != OK) {
231         return status;
232     }
233     AudioConfig hidlConfig;
234     if (status_t status = HidlUtils::audioConfigFromHal(*config, false /*isInput*/, &hidlConfig);
235             status != OK) {
236         return status;
237     }
238 
239 #if !(MAJOR_VERSION == 7 && MINOR_VERSION == 1)
240     //TODO: b/193496180 use spatializer flag at audio HAL when available
241     if ((flags & AUDIO_OUTPUT_FLAG_SPATIALIZER) != 0) {
242         flags = (audio_output_flags_t)(flags & ~AUDIO_OUTPUT_FLAG_SPATIALIZER);
243         flags = (audio_output_flags_t)
244                 (flags | AUDIO_OUTPUT_FLAG_FAST | AUDIO_OUTPUT_FLAG_DEEP_BUFFER);
245     }
246 #endif
247 
248     CoreUtils::AudioOutputFlags hidlFlags;
249     if (status_t status = CoreUtils::audioOutputFlagsFromHal(flags, &hidlFlags); status != OK) {
250         return status;
251     }
252     Result retval = Result::NOT_INITIALIZED;
253 #if MAJOR_VERSION == 7 && MINOR_VERSION == 1
254     Return<void> ret = mDevice->openOutputStream_7_1(
255 #else
256     Return<void> ret = mDevice->openOutputStream(
257 #endif
258             handle, hidlDevice, hidlConfig, hidlFlags,
259 #if MAJOR_VERSION >= 4
260             {} /* metadata */,
261 #endif
262             [&](Result r, const sp<::android::hardware::audio::CPP_VERSION::IStreamOut>& result,
263                     const AudioConfig& suggestedConfig) {
264                 retval = r;
265                 if (retval == Result::OK) {
266                     *outStream = new StreamOutHalHidl(result);
267                 }
268                 HidlUtils::audioConfigToHal(suggestedConfig, config);
269             });
270     return processReturn("openOutputStream", ret, retval);
271 }
272 
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)273 status_t DeviceHalHidl::openInputStream(
274         audio_io_handle_t handle,
275         audio_devices_t devices,
276         struct audio_config *config,
277         audio_input_flags_t flags,
278         const char *address,
279         audio_source_t source,
280         audio_devices_t outputDevice,
281         const char *outputDeviceAddress,
282         sp<StreamInHalInterface> *inStream) {
283     TIME_CHECK();
284     if (mDevice == 0) return NO_INIT;
285     DeviceAddress hidlDevice;
286     if (status_t status = CoreUtils::deviceAddressFromHal(devices, address, &hidlDevice);
287             status != OK) {
288         return status;
289     }
290     AudioConfig hidlConfig;
291     if (status_t status = HidlUtils::audioConfigFromHal(*config, true /*isInput*/, &hidlConfig);
292             status != OK) {
293         return status;
294     }
295     CoreUtils::AudioInputFlags hidlFlags;
296 #if MAJOR_VERSION <= 5
297     // Some flags were specific to framework and must not leak to the HAL.
298     flags = static_cast<audio_input_flags_t>(flags & ~AUDIO_INPUT_FLAG_DIRECT);
299 #endif
300     if (status_t status = CoreUtils::audioInputFlagsFromHal(flags, &hidlFlags); status != OK) {
301         return status;
302     }
303     Result retval = Result::NOT_INITIALIZED;
304 #if MAJOR_VERSION == 2
305     auto sinkMetadata = AudioSource(source);
306 #elif MAJOR_VERSION >= 4
307     // TODO: correctly propagate the tracks sources and volume
308     //       for now, only send the main source at 1dbfs
309     AudioSource hidlSource;
310     if (status_t status = HidlUtils::audioSourceFromHal(source, &hidlSource); status != OK) {
311         return status;
312     }
313     SinkMetadata sinkMetadata = {{{ .source = std::move(hidlSource), .gain = 1 }}};
314 #endif
315 #if MAJOR_VERSION < 5
316     (void)outputDevice;
317     (void)outputDeviceAddress;
318 #else
319 #if MAJOR_VERSION >= 7
320     (void)HidlUtils::audioChannelMaskFromHal(
321             AUDIO_CHANNEL_NONE, true /*isInput*/, &sinkMetadata.tracks[0].channelMask);
322 #endif
323     if (outputDevice != AUDIO_DEVICE_NONE) {
324         DeviceAddress hidlOutputDevice;
325         if (status_t status = CoreUtils::deviceAddressFromHal(
326                         outputDevice, outputDeviceAddress, &hidlOutputDevice); status != OK) {
327             return status;
328         }
329         sinkMetadata.tracks[0].destination.device(std::move(hidlOutputDevice));
330     }
331 #endif
332     Return<void> ret = mDevice->openInputStream(
333             handle, hidlDevice, hidlConfig, hidlFlags, sinkMetadata,
334             [&](Result r,
335                 const sp<::android::hardware::audio::CORE_TYPES_CPP_VERSION::IStreamIn>& result,
336                     const AudioConfig& suggestedConfig) {
337                 retval = r;
338                 if (retval == Result::OK) {
339                     *inStream = new StreamInHalHidl(result);
340                 }
341                 HidlUtils::audioConfigToHal(suggestedConfig, config);
342             });
343     return processReturn("openInputStream", ret, retval);
344 }
345 
supportsAudioPatches(bool * supportsPatches)346 status_t DeviceHalHidl::supportsAudioPatches(bool *supportsPatches) {
347     TIME_CHECK();
348     if (mDevice == 0) return NO_INIT;
349     return processReturn("supportsAudioPatches", mDevice->supportsAudioPatches(), supportsPatches);
350 }
351 
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)352 status_t DeviceHalHidl::createAudioPatch(
353         unsigned int num_sources,
354         const struct audio_port_config *sources,
355         unsigned int num_sinks,
356         const struct audio_port_config *sinks,
357         audio_patch_handle_t *patch) {
358     TIME_CHECK();
359     if (mDevice == 0) return NO_INIT;
360     if (patch == nullptr) return BAD_VALUE;
361 
362 #if MAJOR_VERSION < 6
363     if (*patch != AUDIO_PATCH_HANDLE_NONE) {
364         status_t status = releaseAudioPatch(*patch);
365         ALOGW_IF(status != NO_ERROR, "%s error %d releasing patch handle %d",
366             __func__, status, *patch);
367         *patch = AUDIO_PATCH_HANDLE_NONE;
368     }
369 #endif
370 
371     hidl_vec<AudioPortConfig> hidlSources, hidlSinks;
372     HidlUtils::audioPortConfigsFromHal(num_sources, sources, &hidlSources);
373     HidlUtils::audioPortConfigsFromHal(num_sinks, sinks, &hidlSinks);
374     Result retval = Result::OK;
375     Return<void> ret;
376     std::string methodName = "createAudioPatch";
377     if (*patch == AUDIO_PATCH_HANDLE_NONE) {  // always true for MAJOR_VERSION < 6
378         ret = mDevice->createAudioPatch(
379                 hidlSources, hidlSinks,
380                 [&](Result r, AudioPatchHandle hidlPatch) {
381                     retval = r;
382                     if (retval == Result::OK) {
383                         *patch = static_cast<audio_patch_handle_t>(hidlPatch);
384                     }
385                 });
386     } else {
387 #if MAJOR_VERSION >= 6
388         ret = mDevice->updateAudioPatch(
389                 *patch,
390                 hidlSources, hidlSinks,
391                 [&](Result r, AudioPatchHandle hidlPatch) {
392                     retval = r;
393                     if (retval == Result::OK) {
394                         *patch = static_cast<audio_patch_handle_t>(hidlPatch);
395                     }
396                 });
397         methodName = "updateAudioPatch";
398 #endif
399     }
400     return processReturn(methodName.c_str(), ret, retval);
401 }
402 
releaseAudioPatch(audio_patch_handle_t patch)403 status_t DeviceHalHidl::releaseAudioPatch(audio_patch_handle_t patch) {
404     TIME_CHECK();
405     if (mDevice == 0) return NO_INIT;
406     return processReturn("releaseAudioPatch", mDevice->releaseAudioPatch(patch));
407 }
408 
409 template <typename HalPort>
getAudioPortImpl(HalPort * port)410 status_t DeviceHalHidl::getAudioPortImpl(HalPort *port) {
411     if (mDevice == 0) return NO_INIT;
412     AudioPort hidlPort;
413     HidlUtils::audioPortFromHal(*port, &hidlPort);
414     Result retval;
415     Return<void> ret = mDevice->getAudioPort(
416             hidlPort,
417             [&](Result r, const AudioPort& p) {
418                 retval = r;
419                 if (retval == Result::OK) {
420                     HidlUtils::audioPortToHal(p, port);
421                 }
422             });
423     return processReturn("getAudioPort", ret, retval);
424 }
425 
getAudioPort(struct audio_port * port)426 status_t DeviceHalHidl::getAudioPort(struct audio_port *port) {
427     TIME_CHECK();
428     return getAudioPortImpl(port);
429 }
430 
getAudioPort(struct audio_port_v7 * port)431 status_t DeviceHalHidl::getAudioPort(struct audio_port_v7 *port) {
432     TIME_CHECK();
433 #if MAJOR_VERSION >= 7
434     return getAudioPortImpl(port);
435 #else
436     struct audio_port audioPort = {};
437     status_t result = NO_ERROR;
438     if (!audio_populate_audio_port(port, &audioPort)) {
439         ALOGE("Failed to populate legacy audio port from audio_port_v7");
440         result = BAD_VALUE;
441     }
442     status_t status = getAudioPort(&audioPort);
443     if (status == NO_ERROR) {
444         audio_populate_audio_port_v7(&audioPort, port);
445     } else {
446         result = status;
447     }
448     return result;
449 #endif
450 }
451 
setAudioPortConfig(const struct audio_port_config * config)452 status_t DeviceHalHidl::setAudioPortConfig(const struct audio_port_config *config) {
453     TIME_CHECK();
454     if (mDevice == 0) return NO_INIT;
455     AudioPortConfig hidlConfig;
456     HidlUtils::audioPortConfigFromHal(*config, &hidlConfig);
457     return processReturn("setAudioPortConfig", mDevice->setAudioPortConfig(hidlConfig));
458 }
459 
460 #if MAJOR_VERSION == 2
getMicrophones(std::vector<media::MicrophoneInfo> * microphonesInfo __unused)461 status_t DeviceHalHidl::getMicrophones(
462         std::vector<media::MicrophoneInfo> *microphonesInfo __unused) {
463     if (mDevice == 0) return NO_INIT;
464     return INVALID_OPERATION;
465 }
466 #elif MAJOR_VERSION >= 4
getMicrophones(std::vector<media::MicrophoneInfo> * microphonesInfo)467 status_t DeviceHalHidl::getMicrophones(std::vector<media::MicrophoneInfo> *microphonesInfo) {
468     TIME_CHECK();
469     if (mDevice == 0) return NO_INIT;
470     Result retval;
471     Return<void> ret = mDevice->getMicrophones(
472             [&](Result r, hidl_vec<MicrophoneInfo> micArrayHal) {
473         retval = r;
474         for (size_t k = 0; k < micArrayHal.size(); k++) {
475             audio_microphone_characteristic_t dst;
476             //convert
477             (void)CoreUtils::microphoneInfoToHal(micArrayHal[k], &dst);
478             media::MicrophoneInfo microphone = media::MicrophoneInfo(dst);
479             microphonesInfo->push_back(microphone);
480         }
481     });
482     return processReturn("getMicrophones", ret, retval);
483 }
484 #endif
485 
486 #if MAJOR_VERSION >= 6
addDeviceEffect(audio_port_handle_t device,sp<EffectHalInterface> effect)487 status_t DeviceHalHidl::addDeviceEffect(
488         audio_port_handle_t device, sp<EffectHalInterface> effect) {
489     TIME_CHECK();
490     if (mDevice == 0) return NO_INIT;
491     return processReturn("addDeviceEffect", mDevice->addDeviceEffect(
492             static_cast<AudioPortHandle>(device), effect->effectId()));
493 }
494 #else
addDeviceEffect(audio_port_handle_t device __unused,sp<EffectHalInterface> effect __unused)495 status_t DeviceHalHidl::addDeviceEffect(
496         audio_port_handle_t device __unused, sp<EffectHalInterface> effect __unused) {
497     return INVALID_OPERATION;
498 }
499 #endif
500 
501 #if MAJOR_VERSION >= 6
removeDeviceEffect(audio_port_handle_t device,sp<EffectHalInterface> effect)502 status_t DeviceHalHidl::removeDeviceEffect(
503         audio_port_handle_t device, sp<EffectHalInterface> effect) {
504     TIME_CHECK();
505     if (mDevice == 0) return NO_INIT;
506     return processReturn("removeDeviceEffect", mDevice->removeDeviceEffect(
507             static_cast<AudioPortHandle>(device), effect->effectId()));
508 }
509 #else
removeDeviceEffect(audio_port_handle_t device __unused,sp<EffectHalInterface> effect __unused)510 status_t DeviceHalHidl::removeDeviceEffect(
511         audio_port_handle_t device __unused, sp<EffectHalInterface> effect __unused) {
512     return INVALID_OPERATION;
513 }
514 #endif
515 
setConnectedState(const struct audio_port_v7 * port,bool connected)516 status_t DeviceHalHidl::setConnectedState(const struct audio_port_v7 *port, bool connected) {
517     TIME_CHECK();
518     if (mDevice == 0) return NO_INIT;
519 #if MAJOR_VERSION == 7 && MINOR_VERSION == 1
520     if (supportsSetConnectedState7_1) {
521         AudioPort hidlPort;
522         if (status_t result = HidlUtils::audioPortFromHal(*port, &hidlPort); result != NO_ERROR) {
523             return result;
524         }
525         Return<Result> ret = mDevice->setConnectedState_7_1(hidlPort, connected);
526         if (!ret.isOk() || ret != Result::NOT_SUPPORTED) {
527             return processReturn("setConnectedState_7_1", ret);
528         } else if (ret == Result::OK) {
529             return NO_ERROR;
530         }
531         supportsSetConnectedState7_1 = false;
532     }
533 #endif
534     DeviceAddress hidlAddress;
535     if (status_t result = CoreUtils::deviceAddressFromHal(
536                     port->ext.device.type, port->ext.device.address, &hidlAddress);
537             result != NO_ERROR) {
538         return result;
539     }
540     return processReturn("setConnectedState", mDevice->setConnectedState(hidlAddress, connected));
541 }
542 
getHwAvSync()543 error::Result<audio_hw_sync_t> DeviceHalHidl::getHwAvSync() {
544     TIME_CHECK();
545     if (mDevice == 0) return NO_INIT;
546     audio_hw_sync_t value;
547     Result result;
548     Return<void> ret = mDevice->getHwAvSync([&value, &result](Result r, audio_hw_sync_t v) {
549         value = v;
550         result = r;
551     });
552     RETURN_IF_ERROR(processReturn("getHwAvSync", ret, result));
553     return value;
554 }
555 
dump(int fd,const Vector<String16> & args)556 status_t DeviceHalHidl::dump(int fd, const Vector<String16>& args) {
557     TIME_CHECK();
558     if (mDevice == 0) return NO_INIT;
559     native_handle_t* hidlHandle = native_handle_create(1, 0);
560     hidlHandle->data[0] = fd;
561     hidl_vec<hidl_string> hidlArgs;
562     argsFromHal(args, &hidlArgs);
563     Return<void> ret = mDevice->debug(hidlHandle, hidlArgs);
564     native_handle_delete(hidlHandle);
565 
566     // TODO(b/111997867, b/177271958)  Workaround - remove when fixed.
567     // A Binder transmitted fd may not close immediately due to a race condition b/111997867
568     // when the remote binder thread removes the last refcount to the fd blocks in the
569     // kernel for binder activity. We send a Binder ping() command to unblock the thread
570     // and complete the fd close / release.
571     //
572     // See DeviceHalHidl::dump(), EffectHalHidl::dump(), StreamHalHidl::dump(),
573     //     EffectsFactoryHalHidl::dumpEffects().
574 
575     (void)mDevice->ping(); // synchronous Binder call
576 
577     return processReturn("dump", ret);
578 }
579 
580 } // namespace android
581