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 <android/hardware/audio/4.0/IPrimaryDevice.h>
23 #include <cutils/native_handle.h>
24 #include <hwbinder/IPCThreadState.h>
25 #include <utils/Log.h>
26
27 #include <common/all-versions/VersionUtils.h>
28
29 #include "DeviceHalHidl.h"
30 #include "HidlUtils.h"
31 #include "StreamHalHidl.h"
32 #include "VersionUtils.h"
33
34 using ::android::hardware::audio::common::V4_0::AudioConfig;
35 using ::android::hardware::audio::common::V4_0::AudioDevice;
36 using ::android::hardware::audio::common::V4_0::AudioInputFlag;
37 using ::android::hardware::audio::common::V4_0::AudioOutputFlag;
38 using ::android::hardware::audio::common::V4_0::AudioPatchHandle;
39 using ::android::hardware::audio::common::V4_0::AudioPort;
40 using ::android::hardware::audio::common::V4_0::AudioPortConfig;
41 using ::android::hardware::audio::common::V4_0::AudioMode;
42 using ::android::hardware::audio::common::V4_0::AudioSource;
43 using ::android::hardware::audio::common::V4_0::HidlUtils;
44 using ::android::hardware::audio::common::utils::mkEnumConverter;
45 using ::android::hardware::audio::V4_0::DeviceAddress;
46 using ::android::hardware::audio::V4_0::IPrimaryDevice;
47 using ::android::hardware::audio::V4_0::ParameterValue;
48 using ::android::hardware::audio::V4_0::Result;
49 using ::android::hardware::audio::V4_0::SinkMetadata;
50 using ::android::hardware::hidl_string;
51 using ::android::hardware::hidl_vec;
52
53 namespace android {
54 namespace V4_0 {
55
56 namespace {
57
deviceAddressFromHal(audio_devices_t device,const char * halAddress,DeviceAddress * address)58 status_t deviceAddressFromHal(
59 audio_devices_t device, const char* halAddress, DeviceAddress* address) {
60 address->device = AudioDevice(device);
61
62 if (halAddress == nullptr || strnlen(halAddress, AUDIO_DEVICE_MAX_ADDRESS_LEN) == 0) {
63 return OK;
64 }
65 const bool isInput = (device & AUDIO_DEVICE_BIT_IN) != 0;
66 if (isInput) device &= ~AUDIO_DEVICE_BIT_IN;
67 if ((!isInput && (device & AUDIO_DEVICE_OUT_ALL_A2DP) != 0)
68 || (isInput && (device & AUDIO_DEVICE_IN_BLUETOOTH_A2DP) != 0)) {
69 int status = sscanf(halAddress,
70 "%hhX:%hhX:%hhX:%hhX:%hhX:%hhX",
71 &address->address.mac[0], &address->address.mac[1], &address->address.mac[2],
72 &address->address.mac[3], &address->address.mac[4], &address->address.mac[5]);
73 return status == 6 ? OK : BAD_VALUE;
74 } else if ((!isInput && (device & AUDIO_DEVICE_OUT_IP) != 0)
75 || (isInput && (device & AUDIO_DEVICE_IN_IP) != 0)) {
76 int status = sscanf(halAddress,
77 "%hhu.%hhu.%hhu.%hhu",
78 &address->address.ipv4[0], &address->address.ipv4[1],
79 &address->address.ipv4[2], &address->address.ipv4[3]);
80 return status == 4 ? OK : BAD_VALUE;
81 } else if ((!isInput && (device & AUDIO_DEVICE_OUT_ALL_USB)) != 0
82 || (isInput && (device & AUDIO_DEVICE_IN_ALL_USB)) != 0) {
83 int status = sscanf(halAddress,
84 "card=%d;device=%d",
85 &address->address.alsa.card, &address->address.alsa.device);
86 return status == 2 ? OK : BAD_VALUE;
87 } else if ((!isInput && (device & AUDIO_DEVICE_OUT_BUS) != 0)
88 || (isInput && (device & AUDIO_DEVICE_IN_BUS) != 0)) {
89 if (halAddress != NULL) {
90 address->busAddress = halAddress;
91 return OK;
92 }
93 return BAD_VALUE;
94 } else if ((!isInput && (device & AUDIO_DEVICE_OUT_REMOTE_SUBMIX)) != 0
95 || (isInput && (device & AUDIO_DEVICE_IN_REMOTE_SUBMIX) != 0)) {
96 if (halAddress != NULL) {
97 address->rSubmixAddress = halAddress;
98 return OK;
99 }
100 return BAD_VALUE;
101 }
102 return OK;
103 }
104
105 } // namespace
106
DeviceHalHidl(const sp<IDevice> & device)107 DeviceHalHidl::DeviceHalHidl(const sp<IDevice>& device)
108 : ConversionHelperHidl("Device"), mDevice(device),
109 mPrimaryDevice(IPrimaryDevice::castFrom(device)) {
110 }
111
~DeviceHalHidl()112 DeviceHalHidl::~DeviceHalHidl() {
113 if (mDevice != 0) {
114 mDevice.clear();
115 hardware::IPCThreadState::self()->flushCommands();
116 }
117 }
118
getSupportedDevices(uint32_t *)119 status_t DeviceHalHidl::getSupportedDevices(uint32_t*) {
120 // Obsolete.
121 return INVALID_OPERATION;
122 }
123
initCheck()124 status_t DeviceHalHidl::initCheck() {
125 if (mDevice == 0) return NO_INIT;
126 return processReturn("initCheck", mDevice->initCheck());
127 }
128
setVoiceVolume(float volume)129 status_t DeviceHalHidl::setVoiceVolume(float volume) {
130 if (mDevice == 0) return NO_INIT;
131 if (mPrimaryDevice == 0) return INVALID_OPERATION;
132 return processReturn("setVoiceVolume", mPrimaryDevice->setVoiceVolume(volume));
133 }
134
setMasterVolume(float volume)135 status_t DeviceHalHidl::setMasterVolume(float volume) {
136 if (mDevice == 0) return NO_INIT;
137 if (mPrimaryDevice == 0) return INVALID_OPERATION;
138 return processReturn("setMasterVolume", mPrimaryDevice->setMasterVolume(volume));
139 }
140
getMasterVolume(float * volume)141 status_t DeviceHalHidl::getMasterVolume(float *volume) {
142 if (mDevice == 0) return NO_INIT;
143 if (mPrimaryDevice == 0) return INVALID_OPERATION;
144 Result retval;
145 Return<void> ret = mPrimaryDevice->getMasterVolume(
146 [&](Result r, float v) {
147 retval = r;
148 if (retval == Result::OK) {
149 *volume = v;
150 }
151 });
152 return processReturn("getMasterVolume", ret, retval);
153 }
154
setMode(audio_mode_t mode)155 status_t DeviceHalHidl::setMode(audio_mode_t mode) {
156 if (mDevice == 0) return NO_INIT;
157 if (mPrimaryDevice == 0) return INVALID_OPERATION;
158 return processReturn("setMode", mPrimaryDevice->setMode(AudioMode(mode)));
159 }
160
setMicMute(bool state)161 status_t DeviceHalHidl::setMicMute(bool state) {
162 if (mDevice == 0) return NO_INIT;
163 return processReturn("setMicMute", mDevice->setMicMute(state));
164 }
165
getMicMute(bool * state)166 status_t DeviceHalHidl::getMicMute(bool *state) {
167 if (mDevice == 0) return NO_INIT;
168 Result retval;
169 Return<void> ret = mDevice->getMicMute(
170 [&](Result r, bool mute) {
171 retval = r;
172 if (retval == Result::OK) {
173 *state = mute;
174 }
175 });
176 return processReturn("getMicMute", ret, retval);
177 }
178
setMasterMute(bool state)179 status_t DeviceHalHidl::setMasterMute(bool state) {
180 if (mDevice == 0) return NO_INIT;
181 return processReturn("setMasterMute", mDevice->setMasterMute(state));
182 }
183
getMasterMute(bool * state)184 status_t DeviceHalHidl::getMasterMute(bool *state) {
185 if (mDevice == 0) return NO_INIT;
186 Result retval;
187 Return<void> ret = mDevice->getMasterMute(
188 [&](Result r, bool mute) {
189 retval = r;
190 if (retval == Result::OK) {
191 *state = mute;
192 }
193 });
194 return processReturn("getMasterMute", ret, retval);
195 }
196
setParameters(const String8 & kvPairs)197 status_t DeviceHalHidl::setParameters(const String8& kvPairs) {
198 if (mDevice == 0) return NO_INIT;
199 hidl_vec<ParameterValue> hidlParams;
200 status_t status = parametersFromHal(kvPairs, &hidlParams);
201 if (status != OK) return status;
202 // TODO: change the API so that context and kvPairs are separated
203 return processReturn("setParameters",
204 utils::setParameters(mDevice, {} /* context */, hidlParams));
205 }
206
getParameters(const String8 & keys,String8 * values)207 status_t DeviceHalHidl::getParameters(const String8& keys, String8 *values) {
208 values->clear();
209 if (mDevice == 0) return NO_INIT;
210 hidl_vec<hidl_string> hidlKeys;
211 status_t status = keysFromHal(keys, &hidlKeys);
212 if (status != OK) return status;
213 Result retval;
214 Return<void> ret = utils::getParameters(mDevice,
215 {} /* context */,
216 hidlKeys,
217 [&](Result r, const hidl_vec<ParameterValue>& parameters) {
218 retval = r;
219 if (retval == Result::OK) {
220 parametersToHal(parameters, values);
221 }
222 });
223 return processReturn("getParameters", ret, retval);
224 }
225
getInputBufferSize(const struct audio_config * config,size_t * size)226 status_t DeviceHalHidl::getInputBufferSize(
227 const struct audio_config *config, size_t *size) {
228 if (mDevice == 0) return NO_INIT;
229 AudioConfig hidlConfig;
230 HidlUtils::audioConfigFromHal(*config, &hidlConfig);
231 Result retval;
232 Return<void> ret = mDevice->getInputBufferSize(
233 hidlConfig,
234 [&](Result r, uint64_t bufferSize) {
235 retval = r;
236 if (retval == Result::OK) {
237 *size = static_cast<size_t>(bufferSize);
238 }
239 });
240 return processReturn("getInputBufferSize", ret, retval);
241 }
242
openOutputStream(audio_io_handle_t handle,audio_devices_t devices,audio_output_flags_t flags,struct audio_config * config,const char * address,sp<StreamOutHalInterface> * outStream)243 status_t DeviceHalHidl::openOutputStream(
244 audio_io_handle_t handle,
245 audio_devices_t devices,
246 audio_output_flags_t flags,
247 struct audio_config *config,
248 const char *address,
249 sp<StreamOutHalInterface> *outStream) {
250 if (mDevice == 0) return NO_INIT;
251 DeviceAddress hidlDevice;
252 status_t status = deviceAddressFromHal(devices, address, &hidlDevice);
253 if (status != OK) return status;
254 AudioConfig hidlConfig;
255 HidlUtils::audioConfigFromHal(*config, &hidlConfig);
256 Result retval = Result::NOT_INITIALIZED;
257 Return<void> ret = mDevice->openOutputStream(
258 handle,
259 hidlDevice,
260 hidlConfig,
261 mkEnumConverter<AudioOutputFlag>(flags),
262 {} /* metadata */,
263 [&](Result r, const sp<IStreamOut>& result, 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,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 sp<StreamInHalInterface> *inStream) {
281 if (mDevice == 0) return NO_INIT;
282 DeviceAddress hidlDevice;
283 status_t status = deviceAddressFromHal(devices, address, &hidlDevice);
284 if (status != OK) return status;
285 AudioConfig hidlConfig;
286 HidlUtils::audioConfigFromHal(*config, &hidlConfig);
287 Result retval = Result::NOT_INITIALIZED;
288 // TODO: correctly propagate the tracks sources and volume
289 // for now, only send the main source at 1dbfs
290 SinkMetadata metadata = {{{AudioSource(source), 1}}};
291 Return<void> ret = mDevice->openInputStream(
292 handle,
293 hidlDevice,
294 hidlConfig,
295 flags,
296 metadata,
297 [&](Result r, const sp<IStreamIn>& result, const AudioConfig& suggestedConfig) {
298 retval = r;
299 if (retval == Result::OK) {
300 *inStream = new StreamInHalHidl(result);
301 }
302 HidlUtils::audioConfigToHal(suggestedConfig, config);
303 });
304 return processReturn("openInputStream", ret, retval);
305 }
306
supportsAudioPatches(bool * supportsPatches)307 status_t DeviceHalHidl::supportsAudioPatches(bool *supportsPatches) {
308 if (mDevice == 0) return NO_INIT;
309 return processReturn("supportsAudioPatches", mDevice->supportsAudioPatches(), supportsPatches);
310 }
311
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)312 status_t DeviceHalHidl::createAudioPatch(
313 unsigned int num_sources,
314 const struct audio_port_config *sources,
315 unsigned int num_sinks,
316 const struct audio_port_config *sinks,
317 audio_patch_handle_t *patch) {
318 if (mDevice == 0) return NO_INIT;
319 hidl_vec<AudioPortConfig> hidlSources, hidlSinks;
320 HidlUtils::audioPortConfigsFromHal(num_sources, sources, &hidlSources);
321 HidlUtils::audioPortConfigsFromHal(num_sinks, sinks, &hidlSinks);
322 Result retval;
323 Return<void> ret = mDevice->createAudioPatch(
324 hidlSources, hidlSinks,
325 [&](Result r, AudioPatchHandle hidlPatch) {
326 retval = r;
327 if (retval == Result::OK) {
328 *patch = static_cast<audio_patch_handle_t>(hidlPatch);
329 }
330 });
331 return processReturn("createAudioPatch", ret, retval);
332 }
333
releaseAudioPatch(audio_patch_handle_t patch)334 status_t DeviceHalHidl::releaseAudioPatch(audio_patch_handle_t patch) {
335 if (mDevice == 0) return NO_INIT;
336 return processReturn("releaseAudioPatch", mDevice->releaseAudioPatch(patch));
337 }
338
getAudioPort(struct audio_port * port)339 status_t DeviceHalHidl::getAudioPort(struct audio_port *port) {
340 if (mDevice == 0) return NO_INIT;
341 AudioPort hidlPort;
342 HidlUtils::audioPortFromHal(*port, &hidlPort);
343 Result retval;
344 Return<void> ret = mDevice->getAudioPort(
345 hidlPort,
346 [&](Result r, const AudioPort& p) {
347 retval = r;
348 if (retval == Result::OK) {
349 HidlUtils::audioPortToHal(p, port);
350 }
351 });
352 return processReturn("getAudioPort", ret, retval);
353 }
354
setAudioPortConfig(const struct audio_port_config * config)355 status_t DeviceHalHidl::setAudioPortConfig(const struct audio_port_config *config) {
356 if (mDevice == 0) return NO_INIT;
357 AudioPortConfig hidlConfig;
358 HidlUtils::audioPortConfigFromHal(*config, &hidlConfig);
359 return processReturn("setAudioPortConfig", mDevice->setAudioPortConfig(hidlConfig));
360 }
361
getMicrophones(std::vector<media::MicrophoneInfo> * microphonesInfo)362 status_t DeviceHalHidl::getMicrophones(std::vector<media::MicrophoneInfo> *microphonesInfo) {
363 if (mDevice == 0) return NO_INIT;
364 Result retval;
365 Return<void> ret = mDevice->getMicrophones(
366 [&](Result r, hidl_vec<MicrophoneInfo> micArrayHal) {
367 retval = r;
368 for (size_t k = 0; k < micArrayHal.size(); k++) {
369 audio_microphone_characteristic_t dst;
370 //convert
371 microphoneInfoToHal(micArrayHal[k], &dst);
372 media::MicrophoneInfo microphone = media::MicrophoneInfo(dst);
373 microphonesInfo->push_back(microphone);
374 }
375 });
376 return processReturn("getMicrophones", ret, retval);
377 }
378
dump(int fd)379 status_t DeviceHalHidl::dump(int fd) {
380 if (mDevice == 0) return NO_INIT;
381 native_handle_t* hidlHandle = native_handle_create(1, 0);
382 hidlHandle->data[0] = fd;
383 Return<void> ret = mDevice->debug(hidlHandle, {} /* options */);
384 native_handle_delete(hidlHandle);
385 return processReturn("dump", ret);
386 }
387
388 } // namespace V4_0
389 } // namespace android
390