blob: 8da1051aea7c2ee5b17718cf4c977f413308e98b [file] [log] [blame]
Kevin Rocardd4de2882018-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 Rocard2390b5d2018-02-28 14:36:53 -080022#include <android/hardware/audio/4.0/IPrimaryDevice.h>
Kevin Rocardd4de2882018-02-28 14:33:38 -080023#include <cutils/native_handle.h>
24#include <hwbinder/IPCThreadState.h>
25#include <utils/Log.h>
26
Kevin Rocard4a7484bd2018-02-23 19:11:06 -080027#include <common/all-versions/VersionUtils.h>
28
Kevin Rocardd4de2882018-02-28 14:33:38 -080029#include "DeviceHalHidl.h"
30#include "HidlUtils.h"
31#include "StreamHalHidl.h"
Kevin Rocard4a7484bd2018-02-23 19:11:06 -080032#include "VersionUtils.h"
Kevin Rocardd4de2882018-02-28 14:33:38 -080033
Kevin Rocard2390b5d2018-02-28 14:36:53 -080034using ::android::hardware::audio::common::V4_0::AudioConfig;
35using ::android::hardware::audio::common::V4_0::AudioDevice;
36using ::android::hardware::audio::common::V4_0::AudioInputFlag;
37using ::android::hardware::audio::common::V4_0::AudioOutputFlag;
38using ::android::hardware::audio::common::V4_0::AudioPatchHandle;
39using ::android::hardware::audio::common::V4_0::AudioPort;
40using ::android::hardware::audio::common::V4_0::AudioPortConfig;
41using ::android::hardware::audio::common::V4_0::AudioMode;
42using ::android::hardware::audio::common::V4_0::AudioSource;
43using ::android::hardware::audio::common::V4_0::HidlUtils;
Kevin Rocard4a7484bd2018-02-23 19:11:06 -080044using ::android::hardware::audio::common::utils::mkEnumConverter;
Kevin Rocard2390b5d2018-02-28 14:36:53 -080045using ::android::hardware::audio::V4_0::DeviceAddress;
46using ::android::hardware::audio::V4_0::IPrimaryDevice;
47using ::android::hardware::audio::V4_0::ParameterValue;
48using ::android::hardware::audio::V4_0::Result;
Kevin Rocard4a7484bd2018-02-23 19:11:06 -080049using ::android::hardware::audio::V4_0::SinkMetadata;
Kevin Rocardd4de2882018-02-28 14:33:38 -080050using ::android::hardware::hidl_string;
51using ::android::hardware::hidl_vec;
52
53namespace android {
Kevin Rocard2390b5d2018-02-28 14:36:53 -080054namespace V4_0 {
Kevin Rocardd4de2882018-02-28 14:33:38 -080055
56namespace {
57
58status_t deviceAddressFromHal(
59 audio_devices_t device, const char* halAddress, DeviceAddress* address) {
60 address->device = AudioDevice(device);
61
62 if (address == 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
107DeviceHalHidl::DeviceHalHidl(const sp<IDevice>& device)
108 : ConversionHelperHidl("Device"), mDevice(device),
109 mPrimaryDevice(IPrimaryDevice::castFrom(device)) {
110}
111
112DeviceHalHidl::~DeviceHalHidl() {
113 if (mDevice != 0) {
114 mDevice.clear();
115 hardware::IPCThreadState::self()->flushCommands();
116 }
117}
118
119status_t DeviceHalHidl::getSupportedDevices(uint32_t*) {
120 // Obsolete.
121 return INVALID_OPERATION;
122}
123
124status_t DeviceHalHidl::initCheck() {
125 if (mDevice == 0) return NO_INIT;
126 return processReturn("initCheck", mDevice->initCheck());
127}
128
129status_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
135status_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
141status_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
155status_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
161status_t DeviceHalHidl::setMicMute(bool state) {
162 if (mDevice == 0) return NO_INIT;
163 return processReturn("setMicMute", mDevice->setMicMute(state));
164}
165
166status_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
179status_t DeviceHalHidl::setMasterMute(bool state) {
180 if (mDevice == 0) return NO_INIT;
181 return processReturn("setMasterMute", mDevice->setMasterMute(state));
182}
183
184status_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
197status_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;
Kevin Rocard4a7484bd2018-02-23 19:11:06 -0800202 // TODO: change the API so that context and kvPairs are separated
203 return processReturn("setParameters",
204 utils::setParameters(mDevice, {} /* context */, hidlParams));
Kevin Rocardd4de2882018-02-28 14:33:38 -0800205}
206
207status_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;
Kevin Rocard4a7484bd2018-02-23 19:11:06 -0800214 Return<void> ret = utils::getParameters(mDevice,
215 {} /* context */,
Kevin Rocardd4de2882018-02-28 14:33:38 -0800216 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
226status_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
243status_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,
Kevin Rocard4a7484bd2018-02-23 19:11:06 -0800261 mkEnumConverter<AudioOutputFlag>(flags),
262 {} /* metadata */,
Kevin Rocardd4de2882018-02-28 14:33:38 -0800263 [&](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
273status_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;
Kevin Rocard4a7484bd2018-02-23 19:11:06 -0800288 // TODO: correctly propagate the tracks sources and volume
289 // for now, only send the main source at 1dbfs
290 SinkMetadata metadata = {{{AudioSource(source), 1}}};
Kevin Rocardd4de2882018-02-28 14:33:38 -0800291 Return<void> ret = mDevice->openInputStream(
292 handle,
293 hidlDevice,
294 hidlConfig,
Kevin Rocard4a7484bd2018-02-23 19:11:06 -0800295 flags,
296 metadata,
Kevin Rocardd4de2882018-02-28 14:33:38 -0800297 [&](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
307status_t DeviceHalHidl::supportsAudioPatches(bool *supportsPatches) {
308 if (mDevice == 0) return NO_INIT;
309 return processReturn("supportsAudioPatches", mDevice->supportsAudioPatches(), supportsPatches);
310}
311
312status_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
334status_t DeviceHalHidl::releaseAudioPatch(audio_patch_handle_t patch) {
335 if (mDevice == 0) return NO_INIT;
336 return processReturn("releaseAudioPatch", mDevice->releaseAudioPatch(patch));
337}
338
339status_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
355status_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
362status_t DeviceHalHidl::dump(int fd) {
363 if (mDevice == 0) return NO_INIT;
364 native_handle_t* hidlHandle = native_handle_create(1, 0);
365 hidlHandle->data[0] = fd;
Kevin Rocard4a7484bd2018-02-23 19:11:06 -0800366 Return<void> ret = mDevice->debug(hidlHandle, {} /* options */);
Kevin Rocardd4de2882018-02-28 14:33:38 -0800367 native_handle_delete(hidlHandle);
368 return processReturn("dump", ret);
369}
370
Kevin Rocard2390b5d2018-02-28 14:36:53 -0800371} // namespace V4_0
Kevin Rocardd4de2882018-02-28 14:33:38 -0800372} // namespace android