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