blob: 342ceb635f8689402af222a9e882e4f912964a1c [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>
jiabindaf49952019-11-22 14:10:57 -080025#include <media/AudioContainers.h>
Kevin Rocard4bcd67f2018-02-28 14:33:38 -080026#include <utils/Log.h>
27
Kevin Rocardb9cfbf12018-02-23 19:11:06 -080028#include <common/all-versions/VersionUtils.h>
29
Kevin Rocard4bcd67f2018-02-28 14:33:38 -080030#include "DeviceHalHidl.h"
31#include "HidlUtils.h"
32#include "StreamHalHidl.h"
Kevin Rocardb9cfbf12018-02-23 19:11:06 -080033#include "VersionUtils.h"
Kevin Rocard4bcd67f2018-02-28 14:33:38 -080034
Mikhail Naganov9ccaa162018-12-12 10:27:29 -080035using ::android::hardware::audio::common::CPP_VERSION::implementation::HidlUtils;
Kevin Rocard7a9f05a2018-11-28 16:52:25 -080036using ::android::hardware::audio::common::utils::EnumBitfield;
Kevin Rocard4bcd67f2018-02-28 14:33:38 -080037using ::android::hardware::hidl_string;
38using ::android::hardware::hidl_vec;
39
40namespace android {
Kevin Rocard070e7512018-05-22 09:29:13 -070041namespace CPP_VERSION {
Kevin Rocard4bcd67f2018-02-28 14:33:38 -080042
Mikhail Naganov9ccaa162018-12-12 10:27:29 -080043using namespace ::android::hardware::audio::common::CPP_VERSION;
44using namespace ::android::hardware::audio::CPP_VERSION;
45
Kevin Rocard4bcd67f2018-02-28 14:33:38 -080046namespace {
47
48status_t deviceAddressFromHal(
49 audio_devices_t device, const char* halAddress, DeviceAddress* address) {
50 address->device = AudioDevice(device);
51
Kevin Rocard5915fa32018-03-29 10:32:44 -070052 if (halAddress == nullptr || strnlen(halAddress, AUDIO_DEVICE_MAX_ADDRESS_LEN) == 0) {
Kevin Rocard4bcd67f2018-02-28 14:33:38 -080053 return OK;
54 }
jiabindaf49952019-11-22 14:10:57 -080055 if (getAudioDeviceOutAllA2dpSet().count(device) > 0
56 || device == AUDIO_DEVICE_IN_BLUETOOTH_A2DP) {
Kevin Rocard4bcd67f2018-02-28 14:33:38 -080057 int status = sscanf(halAddress,
58 "%hhX:%hhX:%hhX:%hhX:%hhX:%hhX",
59 &address->address.mac[0], &address->address.mac[1], &address->address.mac[2],
60 &address->address.mac[3], &address->address.mac[4], &address->address.mac[5]);
61 return status == 6 ? OK : BAD_VALUE;
jiabindaf49952019-11-22 14:10:57 -080062 } else if (device == AUDIO_DEVICE_OUT_IP || device == AUDIO_DEVICE_IN_IP) {
Kevin Rocard4bcd67f2018-02-28 14:33:38 -080063 int status = sscanf(halAddress,
64 "%hhu.%hhu.%hhu.%hhu",
65 &address->address.ipv4[0], &address->address.ipv4[1],
66 &address->address.ipv4[2], &address->address.ipv4[3]);
67 return status == 4 ? OK : BAD_VALUE;
jiabindaf49952019-11-22 14:10:57 -080068 } else if (getAudioDeviceOutAllUsbSet().count(device) > 0
69 || getAudioDeviceInAllUsbSet().count(device) > 0) {
Kevin Rocard4bcd67f2018-02-28 14:33:38 -080070 int status = sscanf(halAddress,
71 "card=%d;device=%d",
72 &address->address.alsa.card, &address->address.alsa.device);
73 return status == 2 ? OK : BAD_VALUE;
jiabindaf49952019-11-22 14:10:57 -080074 } else if (device == AUDIO_DEVICE_OUT_BUS || device == AUDIO_DEVICE_IN_BUS) {
75 address->busAddress = halAddress;
76 return OK;
77 } else if (device == AUDIO_DEVICE_OUT_REMOTE_SUBMIX
78 || device == AUDIO_DEVICE_IN_REMOTE_SUBMIX) {
79 address->rSubmixAddress = halAddress;
80 return OK;
Kevin Rocard4bcd67f2018-02-28 14:33:38 -080081 }
82 return OK;
83}
84
85} // namespace
86
87DeviceHalHidl::DeviceHalHidl(const sp<IDevice>& device)
88 : ConversionHelperHidl("Device"), mDevice(device),
89 mPrimaryDevice(IPrimaryDevice::castFrom(device)) {
90}
91
92DeviceHalHidl::~DeviceHalHidl() {
93 if (mDevice != 0) {
Mikhail Naganov3355e442019-11-20 14:20:01 -080094#if MAJOR_VERSION <= 5
Kevin Rocard4bcd67f2018-02-28 14:33:38 -080095 mDevice.clear();
96 hardware::IPCThreadState::self()->flushCommands();
Mikhail Naganov3355e442019-11-20 14:20:01 -080097#elif MAJOR_VERSION >= 6
98 mDevice->close();
99#endif
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800100 }
101}
102
103status_t DeviceHalHidl::getSupportedDevices(uint32_t*) {
104 // Obsolete.
105 return INVALID_OPERATION;
106}
107
108status_t DeviceHalHidl::initCheck() {
109 if (mDevice == 0) return NO_INIT;
110 return processReturn("initCheck", mDevice->initCheck());
111}
112
113status_t DeviceHalHidl::setVoiceVolume(float volume) {
114 if (mDevice == 0) return NO_INIT;
115 if (mPrimaryDevice == 0) return INVALID_OPERATION;
116 return processReturn("setVoiceVolume", mPrimaryDevice->setVoiceVolume(volume));
117}
118
119status_t DeviceHalHidl::setMasterVolume(float volume) {
120 if (mDevice == 0) return NO_INIT;
Mikhail Naganovae1f6622019-02-21 15:20:05 -0800121 return processReturn("setMasterVolume", mDevice->setMasterVolume(volume));
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800122}
123
124status_t DeviceHalHidl::getMasterVolume(float *volume) {
125 if (mDevice == 0) return NO_INIT;
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800126 Result retval;
Mikhail Naganovae1f6622019-02-21 15:20:05 -0800127 Return<void> ret = mDevice->getMasterVolume(
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800128 [&](Result r, float v) {
129 retval = r;
130 if (retval == Result::OK) {
131 *volume = v;
132 }
133 });
134 return processReturn("getMasterVolume", ret, retval);
135}
136
137status_t DeviceHalHidl::setMode(audio_mode_t mode) {
138 if (mDevice == 0) return NO_INIT;
139 if (mPrimaryDevice == 0) return INVALID_OPERATION;
140 return processReturn("setMode", mPrimaryDevice->setMode(AudioMode(mode)));
141}
142
143status_t DeviceHalHidl::setMicMute(bool state) {
144 if (mDevice == 0) return NO_INIT;
145 return processReturn("setMicMute", mDevice->setMicMute(state));
146}
147
148status_t DeviceHalHidl::getMicMute(bool *state) {
149 if (mDevice == 0) return NO_INIT;
150 Result retval;
151 Return<void> ret = mDevice->getMicMute(
152 [&](Result r, bool mute) {
153 retval = r;
154 if (retval == Result::OK) {
155 *state = mute;
156 }
157 });
158 return processReturn("getMicMute", ret, retval);
159}
160
161status_t DeviceHalHidl::setMasterMute(bool state) {
162 if (mDevice == 0) return NO_INIT;
163 return processReturn("setMasterMute", mDevice->setMasterMute(state));
164}
165
166status_t DeviceHalHidl::getMasterMute(bool *state) {
167 if (mDevice == 0) return NO_INIT;
168 Result retval;
169 Return<void> ret = mDevice->getMasterMute(
170 [&](Result r, bool mute) {
171 retval = r;
172 if (retval == Result::OK) {
173 *state = mute;
174 }
175 });
176 return processReturn("getMasterMute", ret, retval);
177}
178
179status_t DeviceHalHidl::setParameters(const String8& kvPairs) {
180 if (mDevice == 0) return NO_INIT;
181 hidl_vec<ParameterValue> hidlParams;
182 status_t status = parametersFromHal(kvPairs, &hidlParams);
183 if (status != OK) return status;
Kevin Rocardb9cfbf12018-02-23 19:11:06 -0800184 // TODO: change the API so that context and kvPairs are separated
185 return processReturn("setParameters",
186 utils::setParameters(mDevice, {} /* context */, hidlParams));
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800187}
188
189status_t DeviceHalHidl::getParameters(const String8& keys, String8 *values) {
190 values->clear();
191 if (mDevice == 0) return NO_INIT;
192 hidl_vec<hidl_string> hidlKeys;
193 status_t status = keysFromHal(keys, &hidlKeys);
194 if (status != OK) return status;
195 Result retval;
Kevin Rocardb9cfbf12018-02-23 19:11:06 -0800196 Return<void> ret = utils::getParameters(mDevice,
197 {} /* context */,
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800198 hidlKeys,
199 [&](Result r, const hidl_vec<ParameterValue>& parameters) {
200 retval = r;
201 if (retval == Result::OK) {
202 parametersToHal(parameters, values);
203 }
204 });
205 return processReturn("getParameters", ret, retval);
206}
207
208status_t DeviceHalHidl::getInputBufferSize(
209 const struct audio_config *config, size_t *size) {
210 if (mDevice == 0) return NO_INIT;
211 AudioConfig hidlConfig;
212 HidlUtils::audioConfigFromHal(*config, &hidlConfig);
213 Result retval;
214 Return<void> ret = mDevice->getInputBufferSize(
215 hidlConfig,
216 [&](Result r, uint64_t bufferSize) {
217 retval = r;
218 if (retval == Result::OK) {
219 *size = static_cast<size_t>(bufferSize);
220 }
221 });
222 return processReturn("getInputBufferSize", ret, retval);
223}
224
225status_t DeviceHalHidl::openOutputStream(
226 audio_io_handle_t handle,
jiabin43810402019-10-24 14:58:31 -0700227 audio_devices_t deviceType,
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800228 audio_output_flags_t flags,
229 struct audio_config *config,
230 const char *address,
231 sp<StreamOutHalInterface> *outStream) {
232 if (mDevice == 0) return NO_INIT;
233 DeviceAddress hidlDevice;
jiabin43810402019-10-24 14:58:31 -0700234 status_t status = deviceAddressFromHal(deviceType, address, &hidlDevice);
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800235 if (status != OK) return status;
236 AudioConfig hidlConfig;
237 HidlUtils::audioConfigFromHal(*config, &hidlConfig);
238 Result retval = Result::NOT_INITIALIZED;
239 Return<void> ret = mDevice->openOutputStream(
240 handle,
241 hidlDevice,
242 hidlConfig,
Kevin Rocard7a9f05a2018-11-28 16:52:25 -0800243 EnumBitfield<AudioOutputFlag>(flags),
Kevin Rocard3d48dce2018-11-08 17:16:57 -0800244#if MAJOR_VERSION >= 4
Kevin Rocardb9cfbf12018-02-23 19:11:06 -0800245 {} /* metadata */,
Kevin Rocard070e7512018-05-22 09:29:13 -0700246#endif
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800247 [&](Result r, const sp<IStreamOut>& result, const AudioConfig& suggestedConfig) {
248 retval = r;
249 if (retval == Result::OK) {
250 *outStream = new StreamOutHalHidl(result);
251 }
252 HidlUtils::audioConfigToHal(suggestedConfig, config);
253 });
254 return processReturn("openOutputStream", ret, retval);
255}
256
257status_t DeviceHalHidl::openInputStream(
258 audio_io_handle_t handle,
259 audio_devices_t devices,
260 struct audio_config *config,
261 audio_input_flags_t flags,
262 const char *address,
263 audio_source_t source,
Mikhail Naganovb4e037e2019-01-14 15:56:33 -0800264 audio_devices_t outputDevice,
265 const char *outputDeviceAddress,
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800266 sp<StreamInHalInterface> *inStream) {
267 if (mDevice == 0) return NO_INIT;
268 DeviceAddress hidlDevice;
269 status_t status = deviceAddressFromHal(devices, address, &hidlDevice);
270 if (status != OK) return status;
271 AudioConfig hidlConfig;
272 HidlUtils::audioConfigFromHal(*config, &hidlConfig);
273 Result retval = Result::NOT_INITIALIZED;
Kevin Rocard070e7512018-05-22 09:29:13 -0700274#if MAJOR_VERSION == 2
Mikhail Naganovd9499eb2018-12-17 16:23:22 -0800275 auto sinkMetadata = AudioSource(source);
Kevin Rocard3d48dce2018-11-08 17:16:57 -0800276#elif MAJOR_VERSION >= 4
Kevin Rocardb9cfbf12018-02-23 19:11:06 -0800277 // TODO: correctly propagate the tracks sources and volume
278 // for now, only send the main source at 1dbfs
Mikhail Naganovd9499eb2018-12-17 16:23:22 -0800279 SinkMetadata sinkMetadata = {{{ .source = AudioSource(source), .gain = 1 }}};
Kevin Rocard070e7512018-05-22 09:29:13 -0700280#endif
Mikhail Naganovb4e037e2019-01-14 15:56:33 -0800281#if MAJOR_VERSION < 5
282 (void)outputDevice;
283 (void)outputDeviceAddress;
284#else
285 if (outputDevice != AUDIO_DEVICE_NONE) {
286 DeviceAddress hidlOutputDevice;
287 status = deviceAddressFromHal(outputDevice, outputDeviceAddress, &hidlOutputDevice);
288 if (status != OK) return status;
289 sinkMetadata.tracks[0].destination.device(std::move(hidlOutputDevice));
290 }
291#endif
Mikhail Naganovbad15102019-12-10 16:44:19 -0800292#if MAJOR_VERSION <= 5
293 // Some flags were specific to framework and must not leak to the HAL.
294 flags = static_cast<audio_input_flags_t>(flags & ~AUDIO_INPUT_FLAG_DIRECT);
295#endif
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800296 Return<void> ret = mDevice->openInputStream(
297 handle,
298 hidlDevice,
299 hidlConfig,
Kevin Rocard7a9f05a2018-11-28 16:52:25 -0800300 EnumBitfield<AudioInputFlag>(flags),
Mikhail Naganovd9499eb2018-12-17 16:23:22 -0800301 sinkMetadata,
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800302 [&](Result r, const sp<IStreamIn>& result, const AudioConfig& suggestedConfig) {
303 retval = r;
304 if (retval == Result::OK) {
305 *inStream = new StreamInHalHidl(result);
306 }
307 HidlUtils::audioConfigToHal(suggestedConfig, config);
308 });
309 return processReturn("openInputStream", ret, retval);
310}
311
312status_t DeviceHalHidl::supportsAudioPatches(bool *supportsPatches) {
313 if (mDevice == 0) return NO_INIT;
314 return processReturn("supportsAudioPatches", mDevice->supportsAudioPatches(), supportsPatches);
315}
316
317status_t DeviceHalHidl::createAudioPatch(
318 unsigned int num_sources,
319 const struct audio_port_config *sources,
320 unsigned int num_sinks,
321 const struct audio_port_config *sinks,
322 audio_patch_handle_t *patch) {
323 if (mDevice == 0) return NO_INIT;
Eric Laurent8711cfd2019-06-10 18:06:33 -0700324 if (patch == nullptr) return BAD_VALUE;
325
Mikhail Naganov73bdf572019-12-11 12:34:15 -0800326#if MAJOR_VERSION < 6
Eric Laurent8711cfd2019-06-10 18:06:33 -0700327 if (*patch != AUDIO_PATCH_HANDLE_NONE) {
328 status_t status = releaseAudioPatch(*patch);
329 ALOGW_IF(status != NO_ERROR, "%s error %d releasing patch handle %d",
330 __func__, status, *patch);
Mikhail Naganov73bdf572019-12-11 12:34:15 -0800331 *patch = AUDIO_PATCH_HANDLE_NONE;
Eric Laurent8711cfd2019-06-10 18:06:33 -0700332 }
Mikhail Naganov73bdf572019-12-11 12:34:15 -0800333#endif
Eric Laurent8711cfd2019-06-10 18:06:33 -0700334
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800335 hidl_vec<AudioPortConfig> hidlSources, hidlSinks;
336 HidlUtils::audioPortConfigsFromHal(num_sources, sources, &hidlSources);
337 HidlUtils::audioPortConfigsFromHal(num_sinks, sinks, &hidlSinks);
Mikhail Naganov73bdf572019-12-11 12:34:15 -0800338 Result retval = Result::OK;
339 Return<void> ret;
340 std::string methodName = "createAudioPatch";
341 if (*patch == AUDIO_PATCH_HANDLE_NONE) { // always true for MAJOR_VERSION < 6
342 ret = mDevice->createAudioPatch(
343 hidlSources, hidlSinks,
344 [&](Result r, AudioPatchHandle hidlPatch) {
345 retval = r;
346 if (retval == Result::OK) {
347 *patch = static_cast<audio_patch_handle_t>(hidlPatch);
348 }
349 });
350 } else {
351#if MAJOR_VERSION >= 6
352 ret = mDevice->updateAudioPatch(
353 *patch,
354 hidlSources, hidlSinks,
355 [&](Result r, AudioPatchHandle hidlPatch) {
356 retval = r;
357 if (retval == Result::OK) {
358 *patch = static_cast<audio_patch_handle_t>(hidlPatch);
359 }
360 });
361 methodName = "updateAudioPatch";
362#endif
363 }
364 return processReturn(methodName.c_str(), ret, retval);
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800365}
366
367status_t DeviceHalHidl::releaseAudioPatch(audio_patch_handle_t patch) {
368 if (mDevice == 0) return NO_INIT;
369 return processReturn("releaseAudioPatch", mDevice->releaseAudioPatch(patch));
370}
371
372status_t DeviceHalHidl::getAudioPort(struct audio_port *port) {
373 if (mDevice == 0) return NO_INIT;
374 AudioPort hidlPort;
375 HidlUtils::audioPortFromHal(*port, &hidlPort);
376 Result retval;
377 Return<void> ret = mDevice->getAudioPort(
378 hidlPort,
379 [&](Result r, const AudioPort& p) {
380 retval = r;
381 if (retval == Result::OK) {
382 HidlUtils::audioPortToHal(p, port);
383 }
384 });
385 return processReturn("getAudioPort", ret, retval);
386}
387
388status_t DeviceHalHidl::setAudioPortConfig(const struct audio_port_config *config) {
389 if (mDevice == 0) return NO_INIT;
390 AudioPortConfig hidlConfig;
391 HidlUtils::audioPortConfigFromHal(*config, &hidlConfig);
392 return processReturn("setAudioPortConfig", mDevice->setAudioPortConfig(hidlConfig));
393}
394
Kevin Rocard070e7512018-05-22 09:29:13 -0700395#if MAJOR_VERSION == 2
396status_t DeviceHalHidl::getMicrophones(
397 std::vector<media::MicrophoneInfo> *microphonesInfo __unused) {
398 if (mDevice == 0) return NO_INIT;
399 return INVALID_OPERATION;
400}
Kevin Rocard3d48dce2018-11-08 17:16:57 -0800401#elif MAJOR_VERSION >= 4
jiabin9ff780e2018-03-19 18:19:52 -0700402status_t DeviceHalHidl::getMicrophones(std::vector<media::MicrophoneInfo> *microphonesInfo) {
403 if (mDevice == 0) return NO_INIT;
404 Result retval;
405 Return<void> ret = mDevice->getMicrophones(
406 [&](Result r, hidl_vec<MicrophoneInfo> micArrayHal) {
407 retval = r;
408 for (size_t k = 0; k < micArrayHal.size(); k++) {
409 audio_microphone_characteristic_t dst;
410 //convert
411 microphoneInfoToHal(micArrayHal[k], &dst);
412 media::MicrophoneInfo microphone = media::MicrophoneInfo(dst);
413 microphonesInfo->push_back(microphone);
414 }
415 });
416 return processReturn("getMicrophones", ret, retval);
417}
Kevin Rocard070e7512018-05-22 09:29:13 -0700418#endif
jiabin9ff780e2018-03-19 18:19:52 -0700419
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800420status_t DeviceHalHidl::dump(int fd) {
421 if (mDevice == 0) return NO_INIT;
422 native_handle_t* hidlHandle = native_handle_create(1, 0);
423 hidlHandle->data[0] = fd;
Kevin Rocardb9cfbf12018-02-23 19:11:06 -0800424 Return<void> ret = mDevice->debug(hidlHandle, {} /* options */);
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800425 native_handle_delete(hidlHandle);
426 return processReturn("dump", ret);
427}
428
Kevin Rocard070e7512018-05-22 09:29:13 -0700429} // namespace CPP_VERSION
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800430} // namespace android