blob: 1b648c9cad9b22205f7c8a095aaf893a187e27ec [file] [log] [blame]
Kevin Rocard4bcd67f2018-02-28 14:33:38 -08001/*
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
Kevin Rocard95213bf2018-11-08 17:16:57 -080022#include PATH(android/hardware/audio/FILE_VERSION/IPrimaryDevice.h)
Kevin Rocard4bcd67f2018-02-28 14:33:38 -080023#include <cutils/native_handle.h>
24#include <hwbinder/IPCThreadState.h>
25#include <utils/Log.h>
26
Kevin Rocardb9cfbf12018-02-23 19:11:06 -080027#include <common/all-versions/VersionUtils.h>
28
Kevin Rocard4bcd67f2018-02-28 14:33:38 -080029#include "DeviceHalHidl.h"
30#include "HidlUtils.h"
31#include "StreamHalHidl.h"
Kevin Rocardb9cfbf12018-02-23 19:11:06 -080032#include "VersionUtils.h"
Kevin Rocard4bcd67f2018-02-28 14:33:38 -080033
Mikhail Naganov9ccaa162018-12-12 10:27:29 -080034using ::android::hardware::audio::common::CPP_VERSION::implementation::HidlUtils;
Kevin Rocard7a9f05a2018-11-28 16:52:25 -080035using ::android::hardware::audio::common::utils::EnumBitfield;
Kevin Rocard4bcd67f2018-02-28 14:33:38 -080036using ::android::hardware::hidl_string;
37using ::android::hardware::hidl_vec;
38
39namespace android {
Kevin Rocard070e7512018-05-22 09:29:13 -070040namespace CPP_VERSION {
Kevin Rocard4bcd67f2018-02-28 14:33:38 -080041
Mikhail Naganov9ccaa162018-12-12 10:27:29 -080042using namespace ::android::hardware::audio::common::CPP_VERSION;
43using namespace ::android::hardware::audio::CPP_VERSION;
44
Kevin Rocard4bcd67f2018-02-28 14:33:38 -080045namespace {
46
47status_t deviceAddressFromHal(
48 audio_devices_t device, const char* halAddress, DeviceAddress* address) {
49 address->device = AudioDevice(device);
50
Kevin Rocard5915fa32018-03-29 10:32:44 -070051 if (halAddress == nullptr || strnlen(halAddress, AUDIO_DEVICE_MAX_ADDRESS_LEN) == 0) {
Kevin Rocard4bcd67f2018-02-28 14:33:38 -080052 return OK;
53 }
54 const bool isInput = (device & AUDIO_DEVICE_BIT_IN) != 0;
55 if (isInput) device &= ~AUDIO_DEVICE_BIT_IN;
56 if ((!isInput && (device & AUDIO_DEVICE_OUT_ALL_A2DP) != 0)
57 || (isInput && (device & AUDIO_DEVICE_IN_BLUETOOTH_A2DP) != 0)) {
58 int status = sscanf(halAddress,
59 "%hhX:%hhX:%hhX:%hhX:%hhX:%hhX",
60 &address->address.mac[0], &address->address.mac[1], &address->address.mac[2],
61 &address->address.mac[3], &address->address.mac[4], &address->address.mac[5]);
62 return status == 6 ? OK : BAD_VALUE;
63 } else if ((!isInput && (device & AUDIO_DEVICE_OUT_IP) != 0)
64 || (isInput && (device & AUDIO_DEVICE_IN_IP) != 0)) {
65 int status = sscanf(halAddress,
66 "%hhu.%hhu.%hhu.%hhu",
67 &address->address.ipv4[0], &address->address.ipv4[1],
68 &address->address.ipv4[2], &address->address.ipv4[3]);
69 return status == 4 ? OK : BAD_VALUE;
70 } else if ((!isInput && (device & AUDIO_DEVICE_OUT_ALL_USB)) != 0
71 || (isInput && (device & AUDIO_DEVICE_IN_ALL_USB)) != 0) {
72 int status = sscanf(halAddress,
73 "card=%d;device=%d",
74 &address->address.alsa.card, &address->address.alsa.device);
75 return status == 2 ? OK : BAD_VALUE;
76 } else if ((!isInput && (device & AUDIO_DEVICE_OUT_BUS) != 0)
77 || (isInput && (device & AUDIO_DEVICE_IN_BUS) != 0)) {
78 if (halAddress != NULL) {
79 address->busAddress = halAddress;
80 return OK;
81 }
82 return BAD_VALUE;
83 } else if ((!isInput && (device & AUDIO_DEVICE_OUT_REMOTE_SUBMIX)) != 0
84 || (isInput && (device & AUDIO_DEVICE_IN_REMOTE_SUBMIX) != 0)) {
85 if (halAddress != NULL) {
86 address->rSubmixAddress = halAddress;
87 return OK;
88 }
89 return BAD_VALUE;
90 }
91 return OK;
92}
93
94} // namespace
95
96DeviceHalHidl::DeviceHalHidl(const sp<IDevice>& device)
97 : ConversionHelperHidl("Device"), mDevice(device),
98 mPrimaryDevice(IPrimaryDevice::castFrom(device)) {
99}
100
101DeviceHalHidl::~DeviceHalHidl() {
102 if (mDevice != 0) {
Mikhail Naganov5a20d9e2019-11-20 14:20:01 -0800103#if MAJOR_VERSION <= 5
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800104 mDevice.clear();
105 hardware::IPCThreadState::self()->flushCommands();
Mikhail Naganov5a20d9e2019-11-20 14:20:01 -0800106#elif MAJOR_VERSION >= 6
107 mDevice->close();
108#endif
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800109 }
110}
111
112status_t DeviceHalHidl::getSupportedDevices(uint32_t*) {
113 // Obsolete.
114 return INVALID_OPERATION;
115}
116
117status_t DeviceHalHidl::initCheck() {
118 if (mDevice == 0) return NO_INIT;
119 return processReturn("initCheck", mDevice->initCheck());
120}
121
122status_t DeviceHalHidl::setVoiceVolume(float volume) {
123 if (mDevice == 0) return NO_INIT;
124 if (mPrimaryDevice == 0) return INVALID_OPERATION;
125 return processReturn("setVoiceVolume", mPrimaryDevice->setVoiceVolume(volume));
126}
127
128status_t DeviceHalHidl::setMasterVolume(float volume) {
129 if (mDevice == 0) return NO_INIT;
Mikhail Naganovae1f6622019-02-21 15:20:05 -0800130 return processReturn("setMasterVolume", mDevice->setMasterVolume(volume));
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800131}
132
133status_t DeviceHalHidl::getMasterVolume(float *volume) {
134 if (mDevice == 0) return NO_INIT;
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800135 Result retval;
Mikhail Naganovae1f6622019-02-21 15:20:05 -0800136 Return<void> ret = mDevice->getMasterVolume(
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800137 [&](Result r, float v) {
138 retval = r;
139 if (retval == Result::OK) {
140 *volume = v;
141 }
142 });
143 return processReturn("getMasterVolume", ret, retval);
144}
145
146status_t DeviceHalHidl::setMode(audio_mode_t mode) {
147 if (mDevice == 0) return NO_INIT;
148 if (mPrimaryDevice == 0) return INVALID_OPERATION;
149 return processReturn("setMode", mPrimaryDevice->setMode(AudioMode(mode)));
150}
151
152status_t DeviceHalHidl::setMicMute(bool state) {
153 if (mDevice == 0) return NO_INIT;
154 return processReturn("setMicMute", mDevice->setMicMute(state));
155}
156
157status_t DeviceHalHidl::getMicMute(bool *state) {
158 if (mDevice == 0) return NO_INIT;
159 Result retval;
160 Return<void> ret = mDevice->getMicMute(
161 [&](Result r, bool mute) {
162 retval = r;
163 if (retval == Result::OK) {
164 *state = mute;
165 }
166 });
167 return processReturn("getMicMute", ret, retval);
168}
169
170status_t DeviceHalHidl::setMasterMute(bool state) {
171 if (mDevice == 0) return NO_INIT;
172 return processReturn("setMasterMute", mDevice->setMasterMute(state));
173}
174
175status_t DeviceHalHidl::getMasterMute(bool *state) {
176 if (mDevice == 0) return NO_INIT;
177 Result retval;
178 Return<void> ret = mDevice->getMasterMute(
179 [&](Result r, bool mute) {
180 retval = r;
181 if (retval == Result::OK) {
182 *state = mute;
183 }
184 });
185 return processReturn("getMasterMute", ret, retval);
186}
187
188status_t DeviceHalHidl::setParameters(const String8& kvPairs) {
189 if (mDevice == 0) return NO_INIT;
190 hidl_vec<ParameterValue> hidlParams;
191 status_t status = parametersFromHal(kvPairs, &hidlParams);
192 if (status != OK) return status;
Kevin Rocardb9cfbf12018-02-23 19:11:06 -0800193 // TODO: change the API so that context and kvPairs are separated
194 return processReturn("setParameters",
195 utils::setParameters(mDevice, {} /* context */, hidlParams));
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800196}
197
198status_t DeviceHalHidl::getParameters(const String8& keys, String8 *values) {
199 values->clear();
200 if (mDevice == 0) return NO_INIT;
201 hidl_vec<hidl_string> hidlKeys;
202 status_t status = keysFromHal(keys, &hidlKeys);
203 if (status != OK) return status;
204 Result retval;
Kevin Rocardb9cfbf12018-02-23 19:11:06 -0800205 Return<void> ret = utils::getParameters(mDevice,
206 {} /* context */,
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800207 hidlKeys,
208 [&](Result r, const hidl_vec<ParameterValue>& parameters) {
209 retval = r;
210 if (retval == Result::OK) {
211 parametersToHal(parameters, values);
212 }
213 });
214 return processReturn("getParameters", ret, retval);
215}
216
217status_t DeviceHalHidl::getInputBufferSize(
218 const struct audio_config *config, size_t *size) {
219 if (mDevice == 0) return NO_INIT;
220 AudioConfig hidlConfig;
221 HidlUtils::audioConfigFromHal(*config, &hidlConfig);
222 Result retval;
223 Return<void> ret = mDevice->getInputBufferSize(
224 hidlConfig,
225 [&](Result r, uint64_t bufferSize) {
226 retval = r;
227 if (retval == Result::OK) {
228 *size = static_cast<size_t>(bufferSize);
229 }
230 });
231 return processReturn("getInputBufferSize", ret, retval);
232}
233
234status_t DeviceHalHidl::openOutputStream(
235 audio_io_handle_t handle,
236 audio_devices_t devices,
237 audio_output_flags_t flags,
238 struct audio_config *config,
239 const char *address,
240 sp<StreamOutHalInterface> *outStream) {
241 if (mDevice == 0) return NO_INIT;
242 DeviceAddress hidlDevice;
243 status_t status = deviceAddressFromHal(devices, address, &hidlDevice);
244 if (status != OK) return status;
245 AudioConfig hidlConfig;
246 HidlUtils::audioConfigFromHal(*config, &hidlConfig);
247 Result retval = Result::NOT_INITIALIZED;
248 Return<void> ret = mDevice->openOutputStream(
249 handle,
250 hidlDevice,
251 hidlConfig,
Kevin Rocard7a9f05a2018-11-28 16:52:25 -0800252 EnumBitfield<AudioOutputFlag>(flags),
Kevin Rocard3d48dce2018-11-08 17:16:57 -0800253#if MAJOR_VERSION >= 4
Kevin Rocardb9cfbf12018-02-23 19:11:06 -0800254 {} /* metadata */,
Kevin Rocard070e7512018-05-22 09:29:13 -0700255#endif
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800256 [&](Result r, const sp<IStreamOut>& result, const AudioConfig& suggestedConfig) {
257 retval = r;
258 if (retval == Result::OK) {
259 *outStream = new StreamOutHalHidl(result);
260 }
261 HidlUtils::audioConfigToHal(suggestedConfig, config);
262 });
263 return processReturn("openOutputStream", ret, retval);
264}
265
266status_t DeviceHalHidl::openInputStream(
267 audio_io_handle_t handle,
268 audio_devices_t devices,
269 struct audio_config *config,
270 audio_input_flags_t flags,
271 const char *address,
272 audio_source_t source,
Mikhail Naganovb4e037e2019-01-14 15:56:33 -0800273 audio_devices_t outputDevice,
274 const char *outputDeviceAddress,
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800275 sp<StreamInHalInterface> *inStream) {
276 if (mDevice == 0) return NO_INIT;
277 DeviceAddress hidlDevice;
278 status_t status = deviceAddressFromHal(devices, address, &hidlDevice);
279 if (status != OK) return status;
280 AudioConfig hidlConfig;
281 HidlUtils::audioConfigFromHal(*config, &hidlConfig);
282 Result retval = Result::NOT_INITIALIZED;
Kevin Rocard070e7512018-05-22 09:29:13 -0700283#if MAJOR_VERSION == 2
Mikhail Naganovd9499eb2018-12-17 16:23:22 -0800284 auto sinkMetadata = AudioSource(source);
Kevin Rocard3d48dce2018-11-08 17:16:57 -0800285#elif MAJOR_VERSION >= 4
Kevin Rocardb9cfbf12018-02-23 19:11:06 -0800286 // TODO: correctly propagate the tracks sources and volume
287 // for now, only send the main source at 1dbfs
Mikhail Naganovd9499eb2018-12-17 16:23:22 -0800288 SinkMetadata sinkMetadata = {{{ .source = AudioSource(source), .gain = 1 }}};
Kevin Rocard070e7512018-05-22 09:29:13 -0700289#endif
Mikhail Naganovb4e037e2019-01-14 15:56:33 -0800290#if MAJOR_VERSION < 5
291 (void)outputDevice;
292 (void)outputDeviceAddress;
293#else
294 if (outputDevice != AUDIO_DEVICE_NONE) {
295 DeviceAddress hidlOutputDevice;
296 status = deviceAddressFromHal(outputDevice, outputDeviceAddress, &hidlOutputDevice);
297 if (status != OK) return status;
298 sinkMetadata.tracks[0].destination.device(std::move(hidlOutputDevice));
299 }
300#endif
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800301 Return<void> ret = mDevice->openInputStream(
302 handle,
303 hidlDevice,
304 hidlConfig,
Kevin Rocard7a9f05a2018-11-28 16:52:25 -0800305 EnumBitfield<AudioInputFlag>(flags),
Mikhail Naganovd9499eb2018-12-17 16:23:22 -0800306 sinkMetadata,
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800307 [&](Result r, const sp<IStreamIn>& result, const AudioConfig& suggestedConfig) {
308 retval = r;
309 if (retval == Result::OK) {
310 *inStream = new StreamInHalHidl(result);
311 }
312 HidlUtils::audioConfigToHal(suggestedConfig, config);
313 });
314 return processReturn("openInputStream", ret, retval);
315}
316
317status_t DeviceHalHidl::supportsAudioPatches(bool *supportsPatches) {
318 if (mDevice == 0) return NO_INIT;
319 return processReturn("supportsAudioPatches", mDevice->supportsAudioPatches(), supportsPatches);
320}
321
322status_t DeviceHalHidl::createAudioPatch(
323 unsigned int num_sources,
324 const struct audio_port_config *sources,
325 unsigned int num_sinks,
326 const struct audio_port_config *sinks,
327 audio_patch_handle_t *patch) {
328 if (mDevice == 0) return NO_INIT;
329 hidl_vec<AudioPortConfig> hidlSources, hidlSinks;
330 HidlUtils::audioPortConfigsFromHal(num_sources, sources, &hidlSources);
331 HidlUtils::audioPortConfigsFromHal(num_sinks, sinks, &hidlSinks);
332 Result retval;
333 Return<void> ret = mDevice->createAudioPatch(
334 hidlSources, hidlSinks,
335 [&](Result r, AudioPatchHandle hidlPatch) {
336 retval = r;
337 if (retval == Result::OK) {
338 *patch = static_cast<audio_patch_handle_t>(hidlPatch);
339 }
340 });
341 return processReturn("createAudioPatch", ret, retval);
342}
343
344status_t DeviceHalHidl::releaseAudioPatch(audio_patch_handle_t patch) {
345 if (mDevice == 0) return NO_INIT;
346 return processReturn("releaseAudioPatch", mDevice->releaseAudioPatch(patch));
347}
348
349status_t DeviceHalHidl::getAudioPort(struct audio_port *port) {
350 if (mDevice == 0) return NO_INIT;
351 AudioPort hidlPort;
352 HidlUtils::audioPortFromHal(*port, &hidlPort);
353 Result retval;
354 Return<void> ret = mDevice->getAudioPort(
355 hidlPort,
356 [&](Result r, const AudioPort& p) {
357 retval = r;
358 if (retval == Result::OK) {
359 HidlUtils::audioPortToHal(p, port);
360 }
361 });
362 return processReturn("getAudioPort", ret, retval);
363}
364
365status_t DeviceHalHidl::setAudioPortConfig(const struct audio_port_config *config) {
366 if (mDevice == 0) return NO_INIT;
367 AudioPortConfig hidlConfig;
368 HidlUtils::audioPortConfigFromHal(*config, &hidlConfig);
369 return processReturn("setAudioPortConfig", mDevice->setAudioPortConfig(hidlConfig));
370}
371
Kevin Rocard070e7512018-05-22 09:29:13 -0700372#if MAJOR_VERSION == 2
373status_t DeviceHalHidl::getMicrophones(
374 std::vector<media::MicrophoneInfo> *microphonesInfo __unused) {
375 if (mDevice == 0) return NO_INIT;
376 return INVALID_OPERATION;
377}
Kevin Rocard3d48dce2018-11-08 17:16:57 -0800378#elif MAJOR_VERSION >= 4
jiabin9ff780e2018-03-19 18:19:52 -0700379status_t DeviceHalHidl::getMicrophones(std::vector<media::MicrophoneInfo> *microphonesInfo) {
380 if (mDevice == 0) return NO_INIT;
381 Result retval;
382 Return<void> ret = mDevice->getMicrophones(
383 [&](Result r, hidl_vec<MicrophoneInfo> micArrayHal) {
384 retval = r;
385 for (size_t k = 0; k < micArrayHal.size(); k++) {
386 audio_microphone_characteristic_t dst;
387 //convert
388 microphoneInfoToHal(micArrayHal[k], &dst);
389 media::MicrophoneInfo microphone = media::MicrophoneInfo(dst);
390 microphonesInfo->push_back(microphone);
391 }
392 });
393 return processReturn("getMicrophones", ret, retval);
394}
Kevin Rocard070e7512018-05-22 09:29:13 -0700395#endif
jiabin9ff780e2018-03-19 18:19:52 -0700396
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800397status_t DeviceHalHidl::dump(int fd) {
398 if (mDevice == 0) return NO_INIT;
399 native_handle_t* hidlHandle = native_handle_create(1, 0);
400 hidlHandle->data[0] = fd;
Kevin Rocardb9cfbf12018-02-23 19:11:06 -0800401 Return<void> ret = mDevice->debug(hidlHandle, {} /* options */);
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800402 native_handle_delete(hidlHandle);
403 return processReturn("dump", ret);
404}
405
Kevin Rocard070e7512018-05-22 09:29:13 -0700406} // namespace CPP_VERSION
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800407} // namespace android