blob: ce806bfd0501adbaf96683996ca53052af4544fe [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
Kevin Rocard070e7512018-05-22 09:29:13 -070034using ::android::hardware::audio::common::CPP_VERSION::AudioConfig;
35using ::android::hardware::audio::common::CPP_VERSION::AudioDevice;
36using ::android::hardware::audio::common::CPP_VERSION::AudioInputFlag;
37using ::android::hardware::audio::common::CPP_VERSION::AudioOutputFlag;
38using ::android::hardware::audio::common::CPP_VERSION::AudioPatchHandle;
39using ::android::hardware::audio::common::CPP_VERSION::AudioPort;
40using ::android::hardware::audio::common::CPP_VERSION::AudioPortConfig;
41using ::android::hardware::audio::common::CPP_VERSION::AudioMode;
42using ::android::hardware::audio::common::CPP_VERSION::AudioSource;
43using ::android::hardware::audio::common::CPP_VERSION::HidlUtils;
Kevin Rocard7a9f05a2018-11-28 16:52:25 -080044using ::android::hardware::audio::common::utils::EnumBitfield;
Kevin Rocard070e7512018-05-22 09:29:13 -070045using ::android::hardware::audio::CPP_VERSION::DeviceAddress;
46using ::android::hardware::audio::CPP_VERSION::IPrimaryDevice;
47using ::android::hardware::audio::CPP_VERSION::ParameterValue;
48using ::android::hardware::audio::CPP_VERSION::Result;
Kevin Rocard4bcd67f2018-02-28 14:33:38 -080049using ::android::hardware::hidl_string;
50using ::android::hardware::hidl_vec;
51
Kevin Rocard070e7512018-05-22 09:29:13 -070052#if MAJOR_VERSION == 4
53using ::android::hardware::audio::CPP_VERSION::SinkMetadata;
54#endif
55
Kevin Rocard4bcd67f2018-02-28 14:33:38 -080056namespace android {
Kevin Rocard070e7512018-05-22 09:29:13 -070057namespace CPP_VERSION {
Kevin Rocard4bcd67f2018-02-28 14:33:38 -080058
59namespace {
60
61status_t deviceAddressFromHal(
62 audio_devices_t device, const char* halAddress, DeviceAddress* address) {
63 address->device = AudioDevice(device);
64
Kevin Rocard5915fa32018-03-29 10:32:44 -070065 if (halAddress == nullptr || strnlen(halAddress, AUDIO_DEVICE_MAX_ADDRESS_LEN) == 0) {
Kevin Rocard4bcd67f2018-02-28 14:33:38 -080066 return OK;
67 }
68 const bool isInput = (device & AUDIO_DEVICE_BIT_IN) != 0;
69 if (isInput) device &= ~AUDIO_DEVICE_BIT_IN;
70 if ((!isInput && (device & AUDIO_DEVICE_OUT_ALL_A2DP) != 0)
71 || (isInput && (device & AUDIO_DEVICE_IN_BLUETOOTH_A2DP) != 0)) {
72 int status = sscanf(halAddress,
73 "%hhX:%hhX:%hhX:%hhX:%hhX:%hhX",
74 &address->address.mac[0], &address->address.mac[1], &address->address.mac[2],
75 &address->address.mac[3], &address->address.mac[4], &address->address.mac[5]);
76 return status == 6 ? OK : BAD_VALUE;
77 } else if ((!isInput && (device & AUDIO_DEVICE_OUT_IP) != 0)
78 || (isInput && (device & AUDIO_DEVICE_IN_IP) != 0)) {
79 int status = sscanf(halAddress,
80 "%hhu.%hhu.%hhu.%hhu",
81 &address->address.ipv4[0], &address->address.ipv4[1],
82 &address->address.ipv4[2], &address->address.ipv4[3]);
83 return status == 4 ? OK : BAD_VALUE;
84 } else if ((!isInput && (device & AUDIO_DEVICE_OUT_ALL_USB)) != 0
85 || (isInput && (device & AUDIO_DEVICE_IN_ALL_USB)) != 0) {
86 int status = sscanf(halAddress,
87 "card=%d;device=%d",
88 &address->address.alsa.card, &address->address.alsa.device);
89 return status == 2 ? OK : BAD_VALUE;
90 } else if ((!isInput && (device & AUDIO_DEVICE_OUT_BUS) != 0)
91 || (isInput && (device & AUDIO_DEVICE_IN_BUS) != 0)) {
92 if (halAddress != NULL) {
93 address->busAddress = halAddress;
94 return OK;
95 }
96 return BAD_VALUE;
97 } else if ((!isInput && (device & AUDIO_DEVICE_OUT_REMOTE_SUBMIX)) != 0
98 || (isInput && (device & AUDIO_DEVICE_IN_REMOTE_SUBMIX) != 0)) {
99 if (halAddress != NULL) {
100 address->rSubmixAddress = halAddress;
101 return OK;
102 }
103 return BAD_VALUE;
104 }
105 return OK;
106}
107
108} // namespace
109
110DeviceHalHidl::DeviceHalHidl(const sp<IDevice>& device)
111 : ConversionHelperHidl("Device"), mDevice(device),
112 mPrimaryDevice(IPrimaryDevice::castFrom(device)) {
113}
114
115DeviceHalHidl::~DeviceHalHidl() {
116 if (mDevice != 0) {
117 mDevice.clear();
118 hardware::IPCThreadState::self()->flushCommands();
119 }
120}
121
122status_t DeviceHalHidl::getSupportedDevices(uint32_t*) {
123 // Obsolete.
124 return INVALID_OPERATION;
125}
126
127status_t DeviceHalHidl::initCheck() {
128 if (mDevice == 0) return NO_INIT;
129 return processReturn("initCheck", mDevice->initCheck());
130}
131
132status_t DeviceHalHidl::setVoiceVolume(float volume) {
133 if (mDevice == 0) return NO_INIT;
134 if (mPrimaryDevice == 0) return INVALID_OPERATION;
135 return processReturn("setVoiceVolume", mPrimaryDevice->setVoiceVolume(volume));
136}
137
138status_t DeviceHalHidl::setMasterVolume(float volume) {
139 if (mDevice == 0) return NO_INIT;
140 if (mPrimaryDevice == 0) return INVALID_OPERATION;
141 return processReturn("setMasterVolume", mPrimaryDevice->setMasterVolume(volume));
142}
143
144status_t DeviceHalHidl::getMasterVolume(float *volume) {
145 if (mDevice == 0) return NO_INIT;
146 if (mPrimaryDevice == 0) return INVALID_OPERATION;
147 Result retval;
148 Return<void> ret = mPrimaryDevice->getMasterVolume(
149 [&](Result r, float v) {
150 retval = r;
151 if (retval == Result::OK) {
152 *volume = v;
153 }
154 });
155 return processReturn("getMasterVolume", ret, retval);
156}
157
158status_t DeviceHalHidl::setMode(audio_mode_t mode) {
159 if (mDevice == 0) return NO_INIT;
160 if (mPrimaryDevice == 0) return INVALID_OPERATION;
161 return processReturn("setMode", mPrimaryDevice->setMode(AudioMode(mode)));
162}
163
164status_t DeviceHalHidl::setMicMute(bool state) {
165 if (mDevice == 0) return NO_INIT;
166 return processReturn("setMicMute", mDevice->setMicMute(state));
167}
168
169status_t DeviceHalHidl::getMicMute(bool *state) {
170 if (mDevice == 0) return NO_INIT;
171 Result retval;
172 Return<void> ret = mDevice->getMicMute(
173 [&](Result r, bool mute) {
174 retval = r;
175 if (retval == Result::OK) {
176 *state = mute;
177 }
178 });
179 return processReturn("getMicMute", ret, retval);
180}
181
182status_t DeviceHalHidl::setMasterMute(bool state) {
183 if (mDevice == 0) return NO_INIT;
184 return processReturn("setMasterMute", mDevice->setMasterMute(state));
185}
186
187status_t DeviceHalHidl::getMasterMute(bool *state) {
188 if (mDevice == 0) return NO_INIT;
189 Result retval;
190 Return<void> ret = mDevice->getMasterMute(
191 [&](Result r, bool mute) {
192 retval = r;
193 if (retval == Result::OK) {
194 *state = mute;
195 }
196 });
197 return processReturn("getMasterMute", ret, retval);
198}
199
200status_t DeviceHalHidl::setParameters(const String8& kvPairs) {
201 if (mDevice == 0) return NO_INIT;
202 hidl_vec<ParameterValue> hidlParams;
203 status_t status = parametersFromHal(kvPairs, &hidlParams);
204 if (status != OK) return status;
Kevin Rocardb9cfbf12018-02-23 19:11:06 -0800205 // TODO: change the API so that context and kvPairs are separated
206 return processReturn("setParameters",
207 utils::setParameters(mDevice, {} /* context */, hidlParams));
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800208}
209
210status_t DeviceHalHidl::getParameters(const String8& keys, String8 *values) {
211 values->clear();
212 if (mDevice == 0) return NO_INIT;
213 hidl_vec<hidl_string> hidlKeys;
214 status_t status = keysFromHal(keys, &hidlKeys);
215 if (status != OK) return status;
216 Result retval;
Kevin Rocardb9cfbf12018-02-23 19:11:06 -0800217 Return<void> ret = utils::getParameters(mDevice,
218 {} /* context */,
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800219 hidlKeys,
220 [&](Result r, const hidl_vec<ParameterValue>& parameters) {
221 retval = r;
222 if (retval == Result::OK) {
223 parametersToHal(parameters, values);
224 }
225 });
226 return processReturn("getParameters", ret, retval);
227}
228
229status_t DeviceHalHidl::getInputBufferSize(
230 const struct audio_config *config, size_t *size) {
231 if (mDevice == 0) return NO_INIT;
232 AudioConfig hidlConfig;
233 HidlUtils::audioConfigFromHal(*config, &hidlConfig);
234 Result retval;
235 Return<void> ret = mDevice->getInputBufferSize(
236 hidlConfig,
237 [&](Result r, uint64_t bufferSize) {
238 retval = r;
239 if (retval == Result::OK) {
240 *size = static_cast<size_t>(bufferSize);
241 }
242 });
243 return processReturn("getInputBufferSize", ret, retval);
244}
245
246status_t DeviceHalHidl::openOutputStream(
247 audio_io_handle_t handle,
248 audio_devices_t devices,
249 audio_output_flags_t flags,
250 struct audio_config *config,
251 const char *address,
252 sp<StreamOutHalInterface> *outStream) {
253 if (mDevice == 0) return NO_INIT;
254 DeviceAddress hidlDevice;
255 status_t status = deviceAddressFromHal(devices, address, &hidlDevice);
256 if (status != OK) return status;
257 AudioConfig hidlConfig;
258 HidlUtils::audioConfigFromHal(*config, &hidlConfig);
259 Result retval = Result::NOT_INITIALIZED;
260 Return<void> ret = mDevice->openOutputStream(
261 handle,
262 hidlDevice,
263 hidlConfig,
Kevin Rocard7a9f05a2018-11-28 16:52:25 -0800264 EnumBitfield<AudioOutputFlag>(flags),
Kevin Rocard070e7512018-05-22 09:29:13 -0700265#if MAJOR_VERSION == 4
Kevin Rocardb9cfbf12018-02-23 19:11:06 -0800266 {} /* metadata */,
Kevin Rocard070e7512018-05-22 09:29:13 -0700267#endif
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800268 [&](Result r, const sp<IStreamOut>& result, const AudioConfig& suggestedConfig) {
269 retval = r;
270 if (retval == Result::OK) {
271 *outStream = new StreamOutHalHidl(result);
272 }
273 HidlUtils::audioConfigToHal(suggestedConfig, config);
274 });
275 return processReturn("openOutputStream", ret, retval);
276}
277
278status_t DeviceHalHidl::openInputStream(
279 audio_io_handle_t handle,
280 audio_devices_t devices,
281 struct audio_config *config,
282 audio_input_flags_t flags,
283 const char *address,
284 audio_source_t source,
285 sp<StreamInHalInterface> *inStream) {
286 if (mDevice == 0) return NO_INIT;
287 DeviceAddress hidlDevice;
288 status_t status = deviceAddressFromHal(devices, address, &hidlDevice);
289 if (status != OK) return status;
290 AudioConfig hidlConfig;
291 HidlUtils::audioConfigFromHal(*config, &hidlConfig);
292 Result retval = Result::NOT_INITIALIZED;
Kevin Rocard070e7512018-05-22 09:29:13 -0700293#if MAJOR_VERSION == 2
294 auto sourceMetadata = AudioSource(source);
295#elif MAJOR_VERSION == 4
Kevin Rocardb9cfbf12018-02-23 19:11:06 -0800296 // TODO: correctly propagate the tracks sources and volume
297 // for now, only send the main source at 1dbfs
Kevin Rocarddf9b4202018-05-10 19:56:08 -0700298 SinkMetadata sourceMetadata = {{{AudioSource(source), 1}}};
Kevin Rocard070e7512018-05-22 09:29:13 -0700299#endif
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800300 Return<void> ret = mDevice->openInputStream(
301 handle,
302 hidlDevice,
303 hidlConfig,
Kevin Rocard7a9f05a2018-11-28 16:52:25 -0800304 EnumBitfield<AudioInputFlag>(flags),
Kevin Rocarddf9b4202018-05-10 19:56:08 -0700305 sourceMetadata,
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800306 [&](Result r, const sp<IStreamIn>& result, const AudioConfig& suggestedConfig) {
307 retval = r;
308 if (retval == Result::OK) {
309 *inStream = new StreamInHalHidl(result);
310 }
311 HidlUtils::audioConfigToHal(suggestedConfig, config);
312 });
313 return processReturn("openInputStream", ret, retval);
314}
315
316status_t DeviceHalHidl::supportsAudioPatches(bool *supportsPatches) {
317 if (mDevice == 0) return NO_INIT;
318 return processReturn("supportsAudioPatches", mDevice->supportsAudioPatches(), supportsPatches);
319}
320
321status_t DeviceHalHidl::createAudioPatch(
322 unsigned int num_sources,
323 const struct audio_port_config *sources,
324 unsigned int num_sinks,
325 const struct audio_port_config *sinks,
326 audio_patch_handle_t *patch) {
327 if (mDevice == 0) return NO_INIT;
328 hidl_vec<AudioPortConfig> hidlSources, hidlSinks;
329 HidlUtils::audioPortConfigsFromHal(num_sources, sources, &hidlSources);
330 HidlUtils::audioPortConfigsFromHal(num_sinks, sinks, &hidlSinks);
331 Result retval;
332 Return<void> ret = mDevice->createAudioPatch(
333 hidlSources, hidlSinks,
334 [&](Result r, AudioPatchHandle hidlPatch) {
335 retval = r;
336 if (retval == Result::OK) {
337 *patch = static_cast<audio_patch_handle_t>(hidlPatch);
338 }
339 });
340 return processReturn("createAudioPatch", ret, retval);
341}
342
343status_t DeviceHalHidl::releaseAudioPatch(audio_patch_handle_t patch) {
344 if (mDevice == 0) return NO_INIT;
345 return processReturn("releaseAudioPatch", mDevice->releaseAudioPatch(patch));
346}
347
348status_t DeviceHalHidl::getAudioPort(struct audio_port *port) {
349 if (mDevice == 0) return NO_INIT;
350 AudioPort hidlPort;
351 HidlUtils::audioPortFromHal(*port, &hidlPort);
352 Result retval;
353 Return<void> ret = mDevice->getAudioPort(
354 hidlPort,
355 [&](Result r, const AudioPort& p) {
356 retval = r;
357 if (retval == Result::OK) {
358 HidlUtils::audioPortToHal(p, port);
359 }
360 });
361 return processReturn("getAudioPort", ret, retval);
362}
363
364status_t DeviceHalHidl::setAudioPortConfig(const struct audio_port_config *config) {
365 if (mDevice == 0) return NO_INIT;
366 AudioPortConfig hidlConfig;
367 HidlUtils::audioPortConfigFromHal(*config, &hidlConfig);
368 return processReturn("setAudioPortConfig", mDevice->setAudioPortConfig(hidlConfig));
369}
370
Kevin Rocard070e7512018-05-22 09:29:13 -0700371#if MAJOR_VERSION == 2
372status_t DeviceHalHidl::getMicrophones(
373 std::vector<media::MicrophoneInfo> *microphonesInfo __unused) {
374 if (mDevice == 0) return NO_INIT;
375 return INVALID_OPERATION;
376}
377#elif MAJOR_VERSION == 4
jiabin9ff780e2018-03-19 18:19:52 -0700378status_t DeviceHalHidl::getMicrophones(std::vector<media::MicrophoneInfo> *microphonesInfo) {
379 if (mDevice == 0) return NO_INIT;
380 Result retval;
381 Return<void> ret = mDevice->getMicrophones(
382 [&](Result r, hidl_vec<MicrophoneInfo> micArrayHal) {
383 retval = r;
384 for (size_t k = 0; k < micArrayHal.size(); k++) {
385 audio_microphone_characteristic_t dst;
386 //convert
387 microphoneInfoToHal(micArrayHal[k], &dst);
388 media::MicrophoneInfo microphone = media::MicrophoneInfo(dst);
389 microphonesInfo->push_back(microphone);
390 }
391 });
392 return processReturn("getMicrophones", ret, retval);
393}
Kevin Rocard070e7512018-05-22 09:29:13 -0700394#endif
jiabin9ff780e2018-03-19 18:19:52 -0700395
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800396status_t DeviceHalHidl::dump(int fd) {
397 if (mDevice == 0) return NO_INIT;
398 native_handle_t* hidlHandle = native_handle_create(1, 0);
399 hidlHandle->data[0] = fd;
Kevin Rocardb9cfbf12018-02-23 19:11:06 -0800400 Return<void> ret = mDevice->debug(hidlHandle, {} /* options */);
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800401 native_handle_delete(hidlHandle);
402 return processReturn("dump", ret);
403}
404
Kevin Rocard070e7512018-05-22 09:29:13 -0700405} // namespace CPP_VERSION
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800406} // namespace android