blob: a1e869f53867a412490f4ca94a946e4f69007a8c [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) {
103 mDevice.clear();
104 hardware::IPCThreadState::self()->flushCommands();
105 }
106}
107
108status_t DeviceHalHidl::getSupportedDevices(uint32_t*) {
109 // Obsolete.
110 return INVALID_OPERATION;
111}
112
113status_t DeviceHalHidl::initCheck() {
114 if (mDevice == 0) return NO_INIT;
115 return processReturn("initCheck", mDevice->initCheck());
116}
117
118status_t DeviceHalHidl::setVoiceVolume(float volume) {
119 if (mDevice == 0) return NO_INIT;
120 if (mPrimaryDevice == 0) return INVALID_OPERATION;
121 return processReturn("setVoiceVolume", mPrimaryDevice->setVoiceVolume(volume));
122}
123
124status_t DeviceHalHidl::setMasterVolume(float volume) {
125 if (mDevice == 0) return NO_INIT;
126 if (mPrimaryDevice == 0) return INVALID_OPERATION;
127 return processReturn("setMasterVolume", mPrimaryDevice->setMasterVolume(volume));
128}
129
130status_t DeviceHalHidl::getMasterVolume(float *volume) {
131 if (mDevice == 0) return NO_INIT;
132 if (mPrimaryDevice == 0) return INVALID_OPERATION;
133 Result retval;
134 Return<void> ret = mPrimaryDevice->getMasterVolume(
135 [&](Result r, float v) {
136 retval = r;
137 if (retval == Result::OK) {
138 *volume = v;
139 }
140 });
141 return processReturn("getMasterVolume", ret, retval);
142}
143
144status_t DeviceHalHidl::setMode(audio_mode_t mode) {
145 if (mDevice == 0) return NO_INIT;
146 if (mPrimaryDevice == 0) return INVALID_OPERATION;
147 return processReturn("setMode", mPrimaryDevice->setMode(AudioMode(mode)));
148}
149
150status_t DeviceHalHidl::setMicMute(bool state) {
151 if (mDevice == 0) return NO_INIT;
152 return processReturn("setMicMute", mDevice->setMicMute(state));
153}
154
155status_t DeviceHalHidl::getMicMute(bool *state) {
156 if (mDevice == 0) return NO_INIT;
157 Result retval;
158 Return<void> ret = mDevice->getMicMute(
159 [&](Result r, bool mute) {
160 retval = r;
161 if (retval == Result::OK) {
162 *state = mute;
163 }
164 });
165 return processReturn("getMicMute", ret, retval);
166}
167
168status_t DeviceHalHidl::setMasterMute(bool state) {
169 if (mDevice == 0) return NO_INIT;
170 return processReturn("setMasterMute", mDevice->setMasterMute(state));
171}
172
173status_t DeviceHalHidl::getMasterMute(bool *state) {
174 if (mDevice == 0) return NO_INIT;
175 Result retval;
176 Return<void> ret = mDevice->getMasterMute(
177 [&](Result r, bool mute) {
178 retval = r;
179 if (retval == Result::OK) {
180 *state = mute;
181 }
182 });
183 return processReturn("getMasterMute", ret, retval);
184}
185
186status_t DeviceHalHidl::setParameters(const String8& kvPairs) {
187 if (mDevice == 0) return NO_INIT;
188 hidl_vec<ParameterValue> hidlParams;
189 status_t status = parametersFromHal(kvPairs, &hidlParams);
190 if (status != OK) return status;
Kevin Rocardb9cfbf12018-02-23 19:11:06 -0800191 // TODO: change the API so that context and kvPairs are separated
192 return processReturn("setParameters",
193 utils::setParameters(mDevice, {} /* context */, hidlParams));
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800194}
195
196status_t DeviceHalHidl::getParameters(const String8& keys, String8 *values) {
197 values->clear();
198 if (mDevice == 0) return NO_INIT;
199 hidl_vec<hidl_string> hidlKeys;
200 status_t status = keysFromHal(keys, &hidlKeys);
201 if (status != OK) return status;
202 Result retval;
Kevin Rocardb9cfbf12018-02-23 19:11:06 -0800203 Return<void> ret = utils::getParameters(mDevice,
204 {} /* context */,
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800205 hidlKeys,
206 [&](Result r, const hidl_vec<ParameterValue>& parameters) {
207 retval = r;
208 if (retval == Result::OK) {
209 parametersToHal(parameters, values);
210 }
211 });
212 return processReturn("getParameters", ret, retval);
213}
214
215status_t DeviceHalHidl::getInputBufferSize(
216 const struct audio_config *config, size_t *size) {
217 if (mDevice == 0) return NO_INIT;
218 AudioConfig hidlConfig;
219 HidlUtils::audioConfigFromHal(*config, &hidlConfig);
220 Result retval;
221 Return<void> ret = mDevice->getInputBufferSize(
222 hidlConfig,
223 [&](Result r, uint64_t bufferSize) {
224 retval = r;
225 if (retval == Result::OK) {
226 *size = static_cast<size_t>(bufferSize);
227 }
228 });
229 return processReturn("getInputBufferSize", ret, retval);
230}
231
232status_t DeviceHalHidl::openOutputStream(
233 audio_io_handle_t handle,
234 audio_devices_t devices,
235 audio_output_flags_t flags,
236 struct audio_config *config,
237 const char *address,
238 sp<StreamOutHalInterface> *outStream) {
239 if (mDevice == 0) return NO_INIT;
240 DeviceAddress hidlDevice;
241 status_t status = deviceAddressFromHal(devices, address, &hidlDevice);
242 if (status != OK) return status;
243 AudioConfig hidlConfig;
244 HidlUtils::audioConfigFromHal(*config, &hidlConfig);
245 Result retval = Result::NOT_INITIALIZED;
246 Return<void> ret = mDevice->openOutputStream(
247 handle,
248 hidlDevice,
249 hidlConfig,
Kevin Rocard7a9f05a2018-11-28 16:52:25 -0800250 EnumBitfield<AudioOutputFlag>(flags),
Kevin Rocard3d48dce2018-11-08 17:16:57 -0800251#if MAJOR_VERSION >= 4
Kevin Rocardb9cfbf12018-02-23 19:11:06 -0800252 {} /* metadata */,
Kevin Rocard070e7512018-05-22 09:29:13 -0700253#endif
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800254 [&](Result r, const sp<IStreamOut>& result, const AudioConfig& suggestedConfig) {
255 retval = r;
256 if (retval == Result::OK) {
257 *outStream = new StreamOutHalHidl(result);
258 }
259 HidlUtils::audioConfigToHal(suggestedConfig, config);
260 });
261 return processReturn("openOutputStream", ret, retval);
262}
263
264status_t DeviceHalHidl::openInputStream(
265 audio_io_handle_t handle,
266 audio_devices_t devices,
267 struct audio_config *config,
268 audio_input_flags_t flags,
269 const char *address,
270 audio_source_t source,
Mikhail Naganovb4e037e2019-01-14 15:56:33 -0800271 audio_devices_t outputDevice,
272 const char *outputDeviceAddress,
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800273 sp<StreamInHalInterface> *inStream) {
274 if (mDevice == 0) return NO_INIT;
275 DeviceAddress hidlDevice;
276 status_t status = deviceAddressFromHal(devices, address, &hidlDevice);
277 if (status != OK) return status;
278 AudioConfig hidlConfig;
279 HidlUtils::audioConfigFromHal(*config, &hidlConfig);
280 Result retval = Result::NOT_INITIALIZED;
Kevin Rocard070e7512018-05-22 09:29:13 -0700281#if MAJOR_VERSION == 2
Mikhail Naganovd9499eb2018-12-17 16:23:22 -0800282 auto sinkMetadata = AudioSource(source);
Kevin Rocard3d48dce2018-11-08 17:16:57 -0800283#elif MAJOR_VERSION >= 4
Kevin Rocardb9cfbf12018-02-23 19:11:06 -0800284 // TODO: correctly propagate the tracks sources and volume
285 // for now, only send the main source at 1dbfs
Mikhail Naganovd9499eb2018-12-17 16:23:22 -0800286 SinkMetadata sinkMetadata = {{{ .source = AudioSource(source), .gain = 1 }}};
Kevin Rocard070e7512018-05-22 09:29:13 -0700287#endif
Mikhail Naganovb4e037e2019-01-14 15:56:33 -0800288#if MAJOR_VERSION < 5
289 (void)outputDevice;
290 (void)outputDeviceAddress;
291#else
292 if (outputDevice != AUDIO_DEVICE_NONE) {
293 DeviceAddress hidlOutputDevice;
294 status = deviceAddressFromHal(outputDevice, outputDeviceAddress, &hidlOutputDevice);
295 if (status != OK) return status;
296 sinkMetadata.tracks[0].destination.device(std::move(hidlOutputDevice));
297 }
298#endif
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800299 Return<void> ret = mDevice->openInputStream(
300 handle,
301 hidlDevice,
302 hidlConfig,
Kevin Rocard7a9f05a2018-11-28 16:52:25 -0800303 EnumBitfield<AudioInputFlag>(flags),
Mikhail Naganovd9499eb2018-12-17 16:23:22 -0800304 sinkMetadata,
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800305 [&](Result r, const sp<IStreamIn>& result, const AudioConfig& suggestedConfig) {
306 retval = r;
307 if (retval == Result::OK) {
308 *inStream = new StreamInHalHidl(result);
309 }
310 HidlUtils::audioConfigToHal(suggestedConfig, config);
311 });
312 return processReturn("openInputStream", ret, retval);
313}
314
315status_t DeviceHalHidl::supportsAudioPatches(bool *supportsPatches) {
316 if (mDevice == 0) return NO_INIT;
317 return processReturn("supportsAudioPatches", mDevice->supportsAudioPatches(), supportsPatches);
318}
319
320status_t DeviceHalHidl::createAudioPatch(
321 unsigned int num_sources,
322 const struct audio_port_config *sources,
323 unsigned int num_sinks,
324 const struct audio_port_config *sinks,
325 audio_patch_handle_t *patch) {
326 if (mDevice == 0) return NO_INIT;
327 hidl_vec<AudioPortConfig> hidlSources, hidlSinks;
328 HidlUtils::audioPortConfigsFromHal(num_sources, sources, &hidlSources);
329 HidlUtils::audioPortConfigsFromHal(num_sinks, sinks, &hidlSinks);
330 Result retval;
331 Return<void> ret = mDevice->createAudioPatch(
332 hidlSources, hidlSinks,
333 [&](Result r, AudioPatchHandle hidlPatch) {
334 retval = r;
335 if (retval == Result::OK) {
336 *patch = static_cast<audio_patch_handle_t>(hidlPatch);
337 }
338 });
339 return processReturn("createAudioPatch", ret, retval);
340}
341
342status_t DeviceHalHidl::releaseAudioPatch(audio_patch_handle_t patch) {
343 if (mDevice == 0) return NO_INIT;
344 return processReturn("releaseAudioPatch", mDevice->releaseAudioPatch(patch));
345}
346
347status_t DeviceHalHidl::getAudioPort(struct audio_port *port) {
348 if (mDevice == 0) return NO_INIT;
349 AudioPort hidlPort;
350 HidlUtils::audioPortFromHal(*port, &hidlPort);
351 Result retval;
352 Return<void> ret = mDevice->getAudioPort(
353 hidlPort,
354 [&](Result r, const AudioPort& p) {
355 retval = r;
356 if (retval == Result::OK) {
357 HidlUtils::audioPortToHal(p, port);
358 }
359 });
360 return processReturn("getAudioPort", ret, retval);
361}
362
363status_t DeviceHalHidl::setAudioPortConfig(const struct audio_port_config *config) {
364 if (mDevice == 0) return NO_INIT;
365 AudioPortConfig hidlConfig;
366 HidlUtils::audioPortConfigFromHal(*config, &hidlConfig);
367 return processReturn("setAudioPortConfig", mDevice->setAudioPortConfig(hidlConfig));
368}
369
Kevin Rocard070e7512018-05-22 09:29:13 -0700370#if MAJOR_VERSION == 2
371status_t DeviceHalHidl::getMicrophones(
372 std::vector<media::MicrophoneInfo> *microphonesInfo __unused) {
373 if (mDevice == 0) return NO_INIT;
374 return INVALID_OPERATION;
375}
Kevin Rocard3d48dce2018-11-08 17:16:57 -0800376#elif MAJOR_VERSION >= 4
jiabin9ff780e2018-03-19 18:19:52 -0700377status_t DeviceHalHidl::getMicrophones(std::vector<media::MicrophoneInfo> *microphonesInfo) {
378 if (mDevice == 0) return NO_INIT;
379 Result retval;
380 Return<void> ret = mDevice->getMicrophones(
381 [&](Result r, hidl_vec<MicrophoneInfo> micArrayHal) {
382 retval = r;
383 for (size_t k = 0; k < micArrayHal.size(); k++) {
384 audio_microphone_characteristic_t dst;
385 //convert
386 microphoneInfoToHal(micArrayHal[k], &dst);
387 media::MicrophoneInfo microphone = media::MicrophoneInfo(dst);
388 microphonesInfo->push_back(microphone);
389 }
390 });
391 return processReturn("getMicrophones", ret, retval);
392}
Kevin Rocard070e7512018-05-22 09:29:13 -0700393#endif
jiabin9ff780e2018-03-19 18:19:52 -0700394
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800395status_t DeviceHalHidl::dump(int fd) {
396 if (mDevice == 0) return NO_INIT;
397 native_handle_t* hidlHandle = native_handle_create(1, 0);
398 hidlHandle->data[0] = fd;
Kevin Rocardb9cfbf12018-02-23 19:11:06 -0800399 Return<void> ret = mDevice->debug(hidlHandle, {} /* options */);
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800400 native_handle_delete(hidlHandle);
401 return processReturn("dump", ret);
402}
403
Kevin Rocard070e7512018-05-22 09:29:13 -0700404} // namespace CPP_VERSION
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800405} // namespace android