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