blob: cd3ac1f3447c55dc088219dddf5b028d084a0681 [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
326 if (*patch != AUDIO_PATCH_HANDLE_NONE) {
327 status_t status = releaseAudioPatch(*patch);
328 ALOGW_IF(status != NO_ERROR, "%s error %d releasing patch handle %d",
329 __func__, status, *patch);
330 }
331
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800332 hidl_vec<AudioPortConfig> hidlSources, hidlSinks;
333 HidlUtils::audioPortConfigsFromHal(num_sources, sources, &hidlSources);
334 HidlUtils::audioPortConfigsFromHal(num_sinks, sinks, &hidlSinks);
335 Result retval;
336 Return<void> ret = mDevice->createAudioPatch(
337 hidlSources, hidlSinks,
338 [&](Result r, AudioPatchHandle hidlPatch) {
339 retval = r;
340 if (retval == Result::OK) {
341 *patch = static_cast<audio_patch_handle_t>(hidlPatch);
342 }
343 });
344 return processReturn("createAudioPatch", ret, retval);
345}
346
347status_t DeviceHalHidl::releaseAudioPatch(audio_patch_handle_t patch) {
348 if (mDevice == 0) return NO_INIT;
349 return processReturn("releaseAudioPatch", mDevice->releaseAudioPatch(patch));
350}
351
352status_t DeviceHalHidl::getAudioPort(struct audio_port *port) {
353 if (mDevice == 0) return NO_INIT;
354 AudioPort hidlPort;
355 HidlUtils::audioPortFromHal(*port, &hidlPort);
356 Result retval;
357 Return<void> ret = mDevice->getAudioPort(
358 hidlPort,
359 [&](Result r, const AudioPort& p) {
360 retval = r;
361 if (retval == Result::OK) {
362 HidlUtils::audioPortToHal(p, port);
363 }
364 });
365 return processReturn("getAudioPort", ret, retval);
366}
367
368status_t DeviceHalHidl::setAudioPortConfig(const struct audio_port_config *config) {
369 if (mDevice == 0) return NO_INIT;
370 AudioPortConfig hidlConfig;
371 HidlUtils::audioPortConfigFromHal(*config, &hidlConfig);
372 return processReturn("setAudioPortConfig", mDevice->setAudioPortConfig(hidlConfig));
373}
374
Kevin Rocard070e7512018-05-22 09:29:13 -0700375#if MAJOR_VERSION == 2
376status_t DeviceHalHidl::getMicrophones(
377 std::vector<media::MicrophoneInfo> *microphonesInfo __unused) {
378 if (mDevice == 0) return NO_INIT;
379 return INVALID_OPERATION;
380}
Kevin Rocard3d48dce2018-11-08 17:16:57 -0800381#elif MAJOR_VERSION >= 4
jiabin9ff780e2018-03-19 18:19:52 -0700382status_t DeviceHalHidl::getMicrophones(std::vector<media::MicrophoneInfo> *microphonesInfo) {
383 if (mDevice == 0) return NO_INIT;
384 Result retval;
385 Return<void> ret = mDevice->getMicrophones(
386 [&](Result r, hidl_vec<MicrophoneInfo> micArrayHal) {
387 retval = r;
388 for (size_t k = 0; k < micArrayHal.size(); k++) {
389 audio_microphone_characteristic_t dst;
390 //convert
391 microphoneInfoToHal(micArrayHal[k], &dst);
392 media::MicrophoneInfo microphone = media::MicrophoneInfo(dst);
393 microphonesInfo->push_back(microphone);
394 }
395 });
396 return processReturn("getMicrophones", ret, retval);
397}
Kevin Rocard070e7512018-05-22 09:29:13 -0700398#endif
jiabin9ff780e2018-03-19 18:19:52 -0700399
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800400status_t DeviceHalHidl::dump(int fd) {
401 if (mDevice == 0) return NO_INIT;
402 native_handle_t* hidlHandle = native_handle_create(1, 0);
403 hidlHandle->data[0] = fd;
Kevin Rocardb9cfbf12018-02-23 19:11:06 -0800404 Return<void> ret = mDevice->debug(hidlHandle, {} /* options */);
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800405 native_handle_delete(hidlHandle);
406 return processReturn("dump", ret);
407}
408
Kevin Rocard070e7512018-05-22 09:29:13 -0700409} // namespace CPP_VERSION
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800410} // namespace android