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 <hwbinder/IPCThreadState.h>
24 #include <media/AudioContainers.h>
25 #include <utils/Log.h>
26
27 #include PATH(android/hardware/audio/FILE_VERSION/IPrimaryDevice.h)
28 #include <HidlUtils.h>
29 #include <common/all-versions/VersionUtils.h>
30 #include <util/CoreUtils.h>
31
32 #include "DeviceHalHidl.h"
33 #include "EffectHalHidl.h"
34 #include "ParameterUtils.h"
35 #include "StreamHalHidl.h"
36
37 using ::android::hardware::audio::common::CPP_VERSION::implementation::HidlUtils;
38 using ::android::hardware::audio::common::utils::EnumBitfield;
39 using ::android::hardware::audio::CPP_VERSION::implementation::CoreUtils;
40 using ::android::hardware::hidl_string;
41 using ::android::hardware::hidl_vec;
42
43 namespace android {
44 namespace CPP_VERSION {
45
46 using namespace ::android::hardware::audio::common::CPP_VERSION;
47 using namespace ::android::hardware::audio::CPP_VERSION;
48
49 using EffectHalHidl = ::android::effect::CPP_VERSION::EffectHalHidl;
50
DeviceHalHidl(const sp<IDevice> & device)51 DeviceHalHidl::DeviceHalHidl(const sp<IDevice>& device)
52 : ConversionHelperHidl("Device"), mDevice(device),
53 mPrimaryDevice(IPrimaryDevice::castFrom(device)) {
54 }
55
~DeviceHalHidl()56 DeviceHalHidl::~DeviceHalHidl() {
57 if (mDevice != 0) {
58 #if MAJOR_VERSION <= 5
59 mDevice.clear();
60 hardware::IPCThreadState::self()->flushCommands();
61 #elif MAJOR_VERSION >= 6
62 mDevice->close();
63 #endif
64 }
65 }
66
getSupportedDevices(uint32_t *)67 status_t DeviceHalHidl::getSupportedDevices(uint32_t*) {
68 // Obsolete.
69 return INVALID_OPERATION;
70 }
71
initCheck()72 status_t DeviceHalHidl::initCheck() {
73 if (mDevice == 0) return NO_INIT;
74 return processReturn("initCheck", mDevice->initCheck());
75 }
76
setVoiceVolume(float volume)77 status_t DeviceHalHidl::setVoiceVolume(float volume) {
78 if (mDevice == 0) return NO_INIT;
79 if (mPrimaryDevice == 0) return INVALID_OPERATION;
80 return processReturn("setVoiceVolume", mPrimaryDevice->setVoiceVolume(volume));
81 }
82
setMasterVolume(float volume)83 status_t DeviceHalHidl::setMasterVolume(float volume) {
84 if (mDevice == 0) return NO_INIT;
85 return processReturn("setMasterVolume", mDevice->setMasterVolume(volume));
86 }
87
getMasterVolume(float * volume)88 status_t DeviceHalHidl::getMasterVolume(float *volume) {
89 if (mDevice == 0) return NO_INIT;
90 Result retval;
91 Return<void> ret = mDevice->getMasterVolume(
92 [&](Result r, float v) {
93 retval = r;
94 if (retval == Result::OK) {
95 *volume = v;
96 }
97 });
98 return processReturn("getMasterVolume", ret, retval);
99 }
100
setMode(audio_mode_t mode)101 status_t DeviceHalHidl::setMode(audio_mode_t mode) {
102 if (mDevice == 0) return NO_INIT;
103 if (mPrimaryDevice == 0) return INVALID_OPERATION;
104 return processReturn("setMode", mPrimaryDevice->setMode(AudioMode(mode)));
105 }
106
setMicMute(bool state)107 status_t DeviceHalHidl::setMicMute(bool state) {
108 if (mDevice == 0) return NO_INIT;
109 return processReturn("setMicMute", mDevice->setMicMute(state));
110 }
111
getMicMute(bool * state)112 status_t DeviceHalHidl::getMicMute(bool *state) {
113 if (mDevice == 0) return NO_INIT;
114 Result retval;
115 Return<void> ret = mDevice->getMicMute(
116 [&](Result r, bool mute) {
117 retval = r;
118 if (retval == Result::OK) {
119 *state = mute;
120 }
121 });
122 return processReturn("getMicMute", ret, retval);
123 }
124
setMasterMute(bool state)125 status_t DeviceHalHidl::setMasterMute(bool state) {
126 if (mDevice == 0) return NO_INIT;
127 return processReturn("setMasterMute", mDevice->setMasterMute(state));
128 }
129
getMasterMute(bool * state)130 status_t DeviceHalHidl::getMasterMute(bool *state) {
131 if (mDevice == 0) return NO_INIT;
132 Result retval;
133 Return<void> ret = mDevice->getMasterMute(
134 [&](Result r, bool mute) {
135 retval = r;
136 if (retval == Result::OK) {
137 *state = mute;
138 }
139 });
140 return processReturn("getMasterMute", ret, retval);
141 }
142
setParameters(const String8 & kvPairs)143 status_t DeviceHalHidl::setParameters(const String8& kvPairs) {
144 if (mDevice == 0) return NO_INIT;
145 hidl_vec<ParameterValue> hidlParams;
146 status_t status = parametersFromHal(kvPairs, &hidlParams);
147 if (status != OK) return status;
148 // TODO: change the API so that context and kvPairs are separated
149 return processReturn("setParameters",
150 utils::setParameters(mDevice, {} /* context */, hidlParams));
151 }
152
getParameters(const String8 & keys,String8 * values)153 status_t DeviceHalHidl::getParameters(const String8& keys, String8 *values) {
154 values->clear();
155 if (mDevice == 0) return NO_INIT;
156 hidl_vec<hidl_string> hidlKeys;
157 status_t status = keysFromHal(keys, &hidlKeys);
158 if (status != OK) return status;
159 Result retval;
160 Return<void> ret = utils::getParameters(mDevice,
161 {} /* context */,
162 hidlKeys,
163 [&](Result r, const hidl_vec<ParameterValue>& parameters) {
164 retval = r;
165 if (retval == Result::OK) {
166 parametersToHal(parameters, values);
167 }
168 });
169 return processReturn("getParameters", ret, retval);
170 }
171
getInputBufferSize(const struct audio_config * config,size_t * size)172 status_t DeviceHalHidl::getInputBufferSize(
173 const struct audio_config *config, size_t *size) {
174 if (mDevice == 0) return NO_INIT;
175 AudioConfig hidlConfig;
176 HidlUtils::audioConfigFromHal(*config, true /*isInput*/, &hidlConfig);
177 Result retval;
178 Return<void> ret = mDevice->getInputBufferSize(
179 hidlConfig,
180 [&](Result r, uint64_t bufferSize) {
181 retval = r;
182 if (retval == Result::OK) {
183 *size = static_cast<size_t>(bufferSize);
184 }
185 });
186 return processReturn("getInputBufferSize", ret, retval);
187 }
188
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)189 status_t DeviceHalHidl::openOutputStream(
190 audio_io_handle_t handle,
191 audio_devices_t deviceType,
192 audio_output_flags_t flags,
193 struct audio_config *config,
194 const char *address,
195 sp<StreamOutHalInterface> *outStream) {
196 if (mDevice == 0) return NO_INIT;
197 DeviceAddress hidlDevice;
198 if (status_t status = CoreUtils::deviceAddressFromHal(deviceType, address, &hidlDevice);
199 status != OK) {
200 return status;
201 }
202 AudioConfig hidlConfig;
203 if (status_t status = HidlUtils::audioConfigFromHal(*config, false /*isInput*/, &hidlConfig);
204 status != OK) {
205 return status;
206 }
207 CoreUtils::AudioOutputFlags hidlFlags;
208 if (status_t status = CoreUtils::audioOutputFlagsFromHal(flags, &hidlFlags); status != OK) {
209 return status;
210 }
211 Result retval = Result::NOT_INITIALIZED;
212 Return<void> ret = mDevice->openOutputStream(
213 handle, hidlDevice, hidlConfig, hidlFlags,
214 #if MAJOR_VERSION >= 4
215 {} /* metadata */,
216 #endif
217 [&](Result r, const sp<IStreamOut>& result, const AudioConfig& suggestedConfig) {
218 retval = r;
219 if (retval == Result::OK) {
220 *outStream = new StreamOutHalHidl(result);
221 }
222 HidlUtils::audioConfigToHal(suggestedConfig, config);
223 });
224 return processReturn("openOutputStream", ret, retval);
225 }
226
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)227 status_t DeviceHalHidl::openInputStream(
228 audio_io_handle_t handle,
229 audio_devices_t devices,
230 struct audio_config *config,
231 audio_input_flags_t flags,
232 const char *address,
233 audio_source_t source,
234 audio_devices_t outputDevice,
235 const char *outputDeviceAddress,
236 sp<StreamInHalInterface> *inStream) {
237 if (mDevice == 0) return NO_INIT;
238 DeviceAddress hidlDevice;
239 if (status_t status = CoreUtils::deviceAddressFromHal(devices, address, &hidlDevice);
240 status != OK) {
241 return status;
242 }
243 AudioConfig hidlConfig;
244 if (status_t status = HidlUtils::audioConfigFromHal(*config, true /*isInput*/, &hidlConfig);
245 status != OK) {
246 return status;
247 }
248 CoreUtils::AudioInputFlags hidlFlags;
249 #if MAJOR_VERSION <= 5
250 // Some flags were specific to framework and must not leak to the HAL.
251 flags = static_cast<audio_input_flags_t>(flags & ~AUDIO_INPUT_FLAG_DIRECT);
252 #endif
253 if (status_t status = CoreUtils::audioInputFlagsFromHal(flags, &hidlFlags); status != OK) {
254 return status;
255 }
256 Result retval = Result::NOT_INITIALIZED;
257 #if MAJOR_VERSION == 2
258 auto sinkMetadata = AudioSource(source);
259 #elif MAJOR_VERSION >= 4
260 // TODO: correctly propagate the tracks sources and volume
261 // for now, only send the main source at 1dbfs
262 AudioSource hidlSource;
263 if (status_t status = HidlUtils::audioSourceFromHal(source, &hidlSource); status != OK) {
264 return status;
265 }
266 SinkMetadata sinkMetadata = {{{ .source = std::move(hidlSource), .gain = 1 }}};
267 #endif
268 #if MAJOR_VERSION < 5
269 (void)outputDevice;
270 (void)outputDeviceAddress;
271 #else
272 #if MAJOR_VERSION >= 7
273 (void)HidlUtils::audioChannelMaskFromHal(
274 AUDIO_CHANNEL_NONE, true /*isInput*/, &sinkMetadata.tracks[0].channelMask);
275 #endif
276 if (outputDevice != AUDIO_DEVICE_NONE) {
277 DeviceAddress hidlOutputDevice;
278 if (status_t status = CoreUtils::deviceAddressFromHal(
279 outputDevice, outputDeviceAddress, &hidlOutputDevice); status != OK) {
280 return status;
281 }
282 sinkMetadata.tracks[0].destination.device(std::move(hidlOutputDevice));
283 }
284 #endif
285 Return<void> ret = mDevice->openInputStream(
286 handle, hidlDevice, hidlConfig, hidlFlags, sinkMetadata,
287 [&](Result r, const sp<IStreamIn>& result, const AudioConfig& suggestedConfig) {
288 retval = r;
289 if (retval == Result::OK) {
290 *inStream = new StreamInHalHidl(result);
291 }
292 HidlUtils::audioConfigToHal(suggestedConfig, config);
293 });
294 return processReturn("openInputStream", ret, retval);
295 }
296
supportsAudioPatches(bool * supportsPatches)297 status_t DeviceHalHidl::supportsAudioPatches(bool *supportsPatches) {
298 if (mDevice == 0) return NO_INIT;
299 return processReturn("supportsAudioPatches", mDevice->supportsAudioPatches(), supportsPatches);
300 }
301
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)302 status_t DeviceHalHidl::createAudioPatch(
303 unsigned int num_sources,
304 const struct audio_port_config *sources,
305 unsigned int num_sinks,
306 const struct audio_port_config *sinks,
307 audio_patch_handle_t *patch) {
308 if (mDevice == 0) return NO_INIT;
309 if (patch == nullptr) return BAD_VALUE;
310
311 #if MAJOR_VERSION < 6
312 if (*patch != AUDIO_PATCH_HANDLE_NONE) {
313 status_t status = releaseAudioPatch(*patch);
314 ALOGW_IF(status != NO_ERROR, "%s error %d releasing patch handle %d",
315 __func__, status, *patch);
316 *patch = AUDIO_PATCH_HANDLE_NONE;
317 }
318 #endif
319
320 hidl_vec<AudioPortConfig> hidlSources, hidlSinks;
321 HidlUtils::audioPortConfigsFromHal(num_sources, sources, &hidlSources);
322 HidlUtils::audioPortConfigsFromHal(num_sinks, sinks, &hidlSinks);
323 Result retval = Result::OK;
324 Return<void> ret;
325 std::string methodName = "createAudioPatch";
326 if (*patch == AUDIO_PATCH_HANDLE_NONE) { // always true for MAJOR_VERSION < 6
327 ret = mDevice->createAudioPatch(
328 hidlSources, hidlSinks,
329 [&](Result r, AudioPatchHandle hidlPatch) {
330 retval = r;
331 if (retval == Result::OK) {
332 *patch = static_cast<audio_patch_handle_t>(hidlPatch);
333 }
334 });
335 } else {
336 #if MAJOR_VERSION >= 6
337 ret = mDevice->updateAudioPatch(
338 *patch,
339 hidlSources, hidlSinks,
340 [&](Result r, AudioPatchHandle hidlPatch) {
341 retval = r;
342 if (retval == Result::OK) {
343 *patch = static_cast<audio_patch_handle_t>(hidlPatch);
344 }
345 });
346 methodName = "updateAudioPatch";
347 #endif
348 }
349 return processReturn(methodName.c_str(), ret, retval);
350 }
351
releaseAudioPatch(audio_patch_handle_t patch)352 status_t DeviceHalHidl::releaseAudioPatch(audio_patch_handle_t patch) {
353 if (mDevice == 0) return NO_INIT;
354 return processReturn("releaseAudioPatch", mDevice->releaseAudioPatch(patch));
355 }
356
357 template <typename HalPort>
getAudioPortImpl(HalPort * port)358 status_t DeviceHalHidl::getAudioPortImpl(HalPort *port) {
359 if (mDevice == 0) return NO_INIT;
360 AudioPort hidlPort;
361 HidlUtils::audioPortFromHal(*port, &hidlPort);
362 Result retval;
363 Return<void> ret = mDevice->getAudioPort(
364 hidlPort,
365 [&](Result r, const AudioPort& p) {
366 retval = r;
367 if (retval == Result::OK) {
368 HidlUtils::audioPortToHal(p, port);
369 }
370 });
371 return processReturn("getAudioPort", ret, retval);
372 }
373
getAudioPort(struct audio_port * port)374 status_t DeviceHalHidl::getAudioPort(struct audio_port *port) {
375 return getAudioPortImpl(port);
376 }
377
getAudioPort(struct audio_port_v7 * port)378 status_t DeviceHalHidl::getAudioPort(struct audio_port_v7 *port) {
379 #if MAJOR_VERSION >= 7
380 return getAudioPortImpl(port);
381 #else
382 struct audio_port audioPort = {};
383 status_t result = NO_ERROR;
384 if (!audio_populate_audio_port(port, &audioPort)) {
385 ALOGE("Failed to populate legacy audio port from audio_port_v7");
386 result = BAD_VALUE;
387 }
388 status_t status = getAudioPort(&audioPort);
389 if (status == NO_ERROR) {
390 audio_populate_audio_port_v7(&audioPort, port);
391 } else {
392 result = status;
393 }
394 return result;
395 #endif
396 }
397
setAudioPortConfig(const struct audio_port_config * config)398 status_t DeviceHalHidl::setAudioPortConfig(const struct audio_port_config *config) {
399 if (mDevice == 0) return NO_INIT;
400 AudioPortConfig hidlConfig;
401 HidlUtils::audioPortConfigFromHal(*config, &hidlConfig);
402 return processReturn("setAudioPortConfig", mDevice->setAudioPortConfig(hidlConfig));
403 }
404
405 #if MAJOR_VERSION == 2
getMicrophones(std::vector<media::MicrophoneInfo> * microphonesInfo __unused)406 status_t DeviceHalHidl::getMicrophones(
407 std::vector<media::MicrophoneInfo> *microphonesInfo __unused) {
408 if (mDevice == 0) return NO_INIT;
409 return INVALID_OPERATION;
410 }
411 #elif MAJOR_VERSION >= 4
getMicrophones(std::vector<media::MicrophoneInfo> * microphonesInfo)412 status_t DeviceHalHidl::getMicrophones(std::vector<media::MicrophoneInfo> *microphonesInfo) {
413 if (mDevice == 0) return NO_INIT;
414 Result retval;
415 Return<void> ret = mDevice->getMicrophones(
416 [&](Result r, hidl_vec<MicrophoneInfo> micArrayHal) {
417 retval = r;
418 for (size_t k = 0; k < micArrayHal.size(); k++) {
419 audio_microphone_characteristic_t dst;
420 //convert
421 (void)CoreUtils::microphoneInfoToHal(micArrayHal[k], &dst);
422 media::MicrophoneInfo microphone = media::MicrophoneInfo(dst);
423 microphonesInfo->push_back(microphone);
424 }
425 });
426 return processReturn("getMicrophones", ret, retval);
427 }
428 #endif
429
430 #if MAJOR_VERSION >= 6
addDeviceEffect(audio_port_handle_t device,sp<EffectHalInterface> effect)431 status_t DeviceHalHidl::addDeviceEffect(
432 audio_port_handle_t device, sp<EffectHalInterface> effect) {
433 if (mDevice == 0) return NO_INIT;
434 return processReturn("addDeviceEffect", mDevice->addDeviceEffect(
435 static_cast<AudioPortHandle>(device),
436 static_cast<EffectHalHidl*>(effect.get())->effectId()));
437 }
438 #else
addDeviceEffect(audio_port_handle_t device __unused,sp<EffectHalInterface> effect __unused)439 status_t DeviceHalHidl::addDeviceEffect(
440 audio_port_handle_t device __unused, sp<EffectHalInterface> effect __unused) {
441 return INVALID_OPERATION;
442 }
443 #endif
444
445 #if MAJOR_VERSION >= 6
removeDeviceEffect(audio_port_handle_t device,sp<EffectHalInterface> effect)446 status_t DeviceHalHidl::removeDeviceEffect(
447 audio_port_handle_t device, sp<EffectHalInterface> effect) {
448 if (mDevice == 0) return NO_INIT;
449 return processReturn("removeDeviceEffect", mDevice->removeDeviceEffect(
450 static_cast<AudioPortHandle>(device),
451 static_cast<EffectHalHidl*>(effect.get())->effectId()));
452 }
453 #else
removeDeviceEffect(audio_port_handle_t device __unused,sp<EffectHalInterface> effect __unused)454 status_t DeviceHalHidl::removeDeviceEffect(
455 audio_port_handle_t device __unused, sp<EffectHalInterface> effect __unused) {
456 return INVALID_OPERATION;
457 }
458 #endif
459
dump(int fd)460 status_t DeviceHalHidl::dump(int fd) {
461 if (mDevice == 0) return NO_INIT;
462 native_handle_t* hidlHandle = native_handle_create(1, 0);
463 hidlHandle->data[0] = fd;
464 Return<void> ret = mDevice->debug(hidlHandle, {} /* options */);
465 native_handle_delete(hidlHandle);
466 return processReturn("dump", ret);
467 }
468
469 } // namespace CPP_VERSION
470 } // namespace android
471