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