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