mirror of
https://github.com/Evolution-X/hardware_interfaces
synced 2026-02-02 06:22:53 +00:00
We still not sure what causes crashes in Device::get|setParam*, but it seems that it is somehow caused by the fact that the parameters code is in a separate class with virtual methods, from which Device class inherits along with IDevice interface. The workaround is to substitute multiple inheritance with delegation in Device class. Hopefully this will either eliminate crashes or make the underlying reasons more clear. Some of the code got reformatted by clang-format as a presubmit requirement. Bug: 36225019 Test: make Change-Id: Id785c3565bbebd5acc26ca46472961698d9c6208
343 lines
11 KiB
C++
343 lines
11 KiB
C++
/*
|
|
* Copyright (C) 2016 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#define LOG_TAG "DeviceHAL"
|
|
//#define LOG_NDEBUG 0
|
|
|
|
#include <algorithm>
|
|
#include <memory.h>
|
|
#include <string.h>
|
|
|
|
#include <android/log.h>
|
|
|
|
#include "Conversions.h"
|
|
#include "Device.h"
|
|
#include "HidlUtils.h"
|
|
#include "ParametersUtil.h"
|
|
#include "StreamIn.h"
|
|
#include "StreamOut.h"
|
|
|
|
namespace android {
|
|
namespace hardware {
|
|
namespace audio {
|
|
namespace V2_0 {
|
|
namespace implementation {
|
|
|
|
namespace {
|
|
|
|
class ParametersUtilImpl : public ParametersUtil {
|
|
public:
|
|
ParametersUtilImpl(audio_hw_device_t* device) : mDevice{device} {}
|
|
|
|
char* halGetParameters(const char* keys) override {
|
|
return mDevice->get_parameters(mDevice, keys);
|
|
}
|
|
|
|
int halSetParameters(const char* keysAndValues) override {
|
|
return mDevice->set_parameters(mDevice, keysAndValues);
|
|
}
|
|
|
|
private:
|
|
audio_hw_device_t* mDevice;
|
|
};
|
|
|
|
} // namespace
|
|
|
|
Device::Device(audio_hw_device_t* device)
|
|
: mDevice{device}, mParameters{new ParametersUtilImpl(mDevice)} {}
|
|
|
|
Device::~Device() {
|
|
int status = audio_hw_device_close(mDevice);
|
|
ALOGW_IF(status, "Error closing audio hw device %p: %s", mDevice, strerror(-status));
|
|
mDevice = nullptr;
|
|
}
|
|
|
|
Result Device::analyzeStatus(const char* funcName, int status) {
|
|
if (status != 0) {
|
|
ALOGW("Device %p %s: %s", mDevice, funcName, strerror(-status));
|
|
}
|
|
switch (status) {
|
|
case 0: return Result::OK;
|
|
case -EINVAL: return Result::INVALID_ARGUMENTS;
|
|
case -ENODATA: return Result::INVALID_STATE;
|
|
case -ENODEV: return Result::NOT_INITIALIZED;
|
|
case -ENOSYS: return Result::NOT_SUPPORTED;
|
|
default: return Result::INVALID_STATE;
|
|
}
|
|
}
|
|
|
|
void Device::closeInputStream(audio_stream_in_t* stream) {
|
|
mDevice->close_input_stream(mDevice, stream);
|
|
}
|
|
|
|
void Device::closeOutputStream(audio_stream_out_t* stream) {
|
|
mDevice->close_output_stream(mDevice, stream);
|
|
}
|
|
|
|
Result Device::getParam(const char* name, bool* value) {
|
|
return mParameters->getParam(name, value);
|
|
}
|
|
|
|
Result Device::getParam(const char* name, int* value) {
|
|
return mParameters->getParam(name, value);
|
|
}
|
|
|
|
Result Device::getParam(const char* name, String8* value) {
|
|
return mParameters->getParam(name, value);
|
|
}
|
|
|
|
Result Device::setParam(const char* name, bool value) {
|
|
return mParameters->setParam(name, value);
|
|
}
|
|
|
|
Result Device::setParam(const char* name, int value) {
|
|
return mParameters->setParam(name, value);
|
|
}
|
|
|
|
Result Device::setParam(const char* name, const char* value) {
|
|
return mParameters->setParam(name, value);
|
|
}
|
|
|
|
// Methods from ::android::hardware::audio::V2_0::IDevice follow.
|
|
Return<Result> Device::initCheck() {
|
|
return analyzeStatus("init_check", mDevice->init_check(mDevice));
|
|
}
|
|
|
|
Return<Result> Device::setMasterVolume(float volume) {
|
|
Result retval(Result::NOT_SUPPORTED);
|
|
if (mDevice->set_master_volume != NULL) {
|
|
retval = analyzeStatus("set_master_volume", mDevice->set_master_volume(mDevice, volume));
|
|
}
|
|
return retval;
|
|
}
|
|
|
|
Return<void> Device::getMasterVolume(getMasterVolume_cb _hidl_cb) {
|
|
Result retval(Result::NOT_SUPPORTED);
|
|
float volume = 0;
|
|
if (mDevice->get_master_volume != NULL) {
|
|
retval = analyzeStatus("get_master_volume", mDevice->get_master_volume(mDevice, &volume));
|
|
}
|
|
_hidl_cb(retval, volume);
|
|
return Void();
|
|
}
|
|
|
|
Return<Result> Device::setMicMute(bool mute) {
|
|
return analyzeStatus("set_mic_mute", mDevice->set_mic_mute(mDevice, mute));
|
|
}
|
|
|
|
Return<void> Device::getMicMute(getMicMute_cb _hidl_cb) {
|
|
bool mute = false;
|
|
Result retval = analyzeStatus("get_mic_mute", mDevice->get_mic_mute(mDevice, &mute));
|
|
_hidl_cb(retval, mute);
|
|
return Void();
|
|
}
|
|
|
|
Return<Result> Device::setMasterMute(bool mute) {
|
|
Result retval(Result::NOT_SUPPORTED);
|
|
if (mDevice->set_master_mute != NULL) {
|
|
retval = analyzeStatus("set_master_mute", mDevice->set_master_mute(mDevice, mute));
|
|
}
|
|
return retval;
|
|
}
|
|
|
|
Return<void> Device::getMasterMute(getMasterMute_cb _hidl_cb) {
|
|
Result retval(Result::NOT_SUPPORTED);
|
|
bool mute = false;
|
|
if (mDevice->get_master_mute != NULL) {
|
|
retval = analyzeStatus("get_master_mute", mDevice->get_master_mute(mDevice, &mute));
|
|
}
|
|
_hidl_cb(retval, mute);
|
|
return Void();
|
|
}
|
|
|
|
Return<void> Device::getInputBufferSize(
|
|
const AudioConfig& config, getInputBufferSize_cb _hidl_cb) {
|
|
audio_config_t halConfig;
|
|
HidlUtils::audioConfigToHal(config, &halConfig);
|
|
size_t halBufferSize = mDevice->get_input_buffer_size(mDevice, &halConfig);
|
|
Result retval(Result::INVALID_ARGUMENTS);
|
|
uint64_t bufferSize = 0;
|
|
if (halBufferSize != 0) {
|
|
retval = Result::OK;
|
|
bufferSize = halBufferSize;
|
|
}
|
|
_hidl_cb(retval, bufferSize);
|
|
return Void();
|
|
}
|
|
|
|
Return<void> Device::openOutputStream(
|
|
int32_t ioHandle,
|
|
const DeviceAddress& device,
|
|
const AudioConfig& config,
|
|
AudioOutputFlag flags,
|
|
openOutputStream_cb _hidl_cb) {
|
|
audio_config_t halConfig;
|
|
HidlUtils::audioConfigToHal(config, &halConfig);
|
|
audio_stream_out_t *halStream;
|
|
ALOGV("open_output_stream handle: %d devices: %x flags: %#x "
|
|
"srate: %d format %#x channels %x address %s",
|
|
ioHandle,
|
|
static_cast<audio_devices_t>(device.device), static_cast<audio_output_flags_t>(flags),
|
|
halConfig.sample_rate, halConfig.format, halConfig.channel_mask,
|
|
deviceAddressToHal(device).c_str());
|
|
int status = mDevice->open_output_stream(
|
|
mDevice,
|
|
ioHandle,
|
|
static_cast<audio_devices_t>(device.device),
|
|
static_cast<audio_output_flags_t>(flags),
|
|
&halConfig,
|
|
&halStream,
|
|
deviceAddressToHal(device).c_str());
|
|
ALOGV("open_output_stream status %d stream %p", status, halStream);
|
|
sp<IStreamOut> streamOut;
|
|
if (status == OK) {
|
|
streamOut = new StreamOut(this, halStream);
|
|
}
|
|
AudioConfig suggestedConfig;
|
|
HidlUtils::audioConfigFromHal(halConfig, &suggestedConfig);
|
|
_hidl_cb(analyzeStatus("open_output_stream", status), streamOut, suggestedConfig);
|
|
return Void();
|
|
}
|
|
|
|
Return<void> Device::openInputStream(
|
|
int32_t ioHandle,
|
|
const DeviceAddress& device,
|
|
const AudioConfig& config,
|
|
AudioInputFlag flags,
|
|
AudioSource source,
|
|
openInputStream_cb _hidl_cb) {
|
|
audio_config_t halConfig;
|
|
HidlUtils::audioConfigToHal(config, &halConfig);
|
|
audio_stream_in_t *halStream;
|
|
ALOGV("open_input_stream handle: %d devices: %x flags: %#x "
|
|
"srate: %d format %#x channels %x address %s source %d",
|
|
ioHandle,
|
|
static_cast<audio_devices_t>(device.device), static_cast<audio_input_flags_t>(flags),
|
|
halConfig.sample_rate, halConfig.format, halConfig.channel_mask,
|
|
deviceAddressToHal(device).c_str(), static_cast<audio_source_t>(source));
|
|
int status = mDevice->open_input_stream(
|
|
mDevice,
|
|
ioHandle,
|
|
static_cast<audio_devices_t>(device.device),
|
|
&halConfig,
|
|
&halStream,
|
|
static_cast<audio_input_flags_t>(flags),
|
|
deviceAddressToHal(device).c_str(),
|
|
static_cast<audio_source_t>(source));
|
|
ALOGV("open_input_stream status %d stream %p", status, halStream);
|
|
sp<IStreamIn> streamIn;
|
|
if (status == OK) {
|
|
streamIn = new StreamIn(this, halStream);
|
|
}
|
|
AudioConfig suggestedConfig;
|
|
HidlUtils::audioConfigFromHal(halConfig, &suggestedConfig);
|
|
_hidl_cb(analyzeStatus("open_input_stream", status), streamIn, suggestedConfig);
|
|
return Void();
|
|
}
|
|
|
|
Return<bool> Device::supportsAudioPatches() {
|
|
return version() >= AUDIO_DEVICE_API_VERSION_3_0;
|
|
}
|
|
|
|
Return<void> Device::createAudioPatch(
|
|
const hidl_vec<AudioPortConfig>& sources,
|
|
const hidl_vec<AudioPortConfig>& sinks,
|
|
createAudioPatch_cb _hidl_cb) {
|
|
Result retval(Result::NOT_SUPPORTED);
|
|
AudioPatchHandle patch = 0;
|
|
if (version() >= AUDIO_DEVICE_API_VERSION_3_0) {
|
|
std::unique_ptr<audio_port_config[]> halSources(HidlUtils::audioPortConfigsToHal(sources));
|
|
std::unique_ptr<audio_port_config[]> halSinks(HidlUtils::audioPortConfigsToHal(sinks));
|
|
audio_patch_handle_t halPatch = AUDIO_PATCH_HANDLE_NONE;
|
|
retval = analyzeStatus(
|
|
"create_audio_patch",
|
|
mDevice->create_audio_patch(
|
|
mDevice,
|
|
sources.size(), &halSources[0],
|
|
sinks.size(), &halSinks[0],
|
|
&halPatch));
|
|
if (retval == Result::OK) {
|
|
patch = static_cast<AudioPatchHandle>(halPatch);
|
|
}
|
|
}
|
|
_hidl_cb(retval, patch);
|
|
return Void();
|
|
}
|
|
|
|
Return<Result> Device::releaseAudioPatch(int32_t patch) {
|
|
if (version() >= AUDIO_DEVICE_API_VERSION_3_0) {
|
|
return analyzeStatus(
|
|
"release_audio_patch",
|
|
mDevice->release_audio_patch(mDevice, static_cast<audio_patch_handle_t>(patch)));
|
|
}
|
|
return Result::NOT_SUPPORTED;
|
|
}
|
|
|
|
Return<void> Device::getAudioPort(const AudioPort& port, getAudioPort_cb _hidl_cb) {
|
|
audio_port halPort;
|
|
HidlUtils::audioPortToHal(port, &halPort);
|
|
Result retval = analyzeStatus("get_audio_port", mDevice->get_audio_port(mDevice, &halPort));
|
|
AudioPort resultPort = port;
|
|
if (retval == Result::OK) {
|
|
HidlUtils::audioPortFromHal(halPort, &resultPort);
|
|
}
|
|
_hidl_cb(retval, resultPort);
|
|
return Void();
|
|
}
|
|
|
|
Return<Result> Device::setAudioPortConfig(const AudioPortConfig& config) {
|
|
if (version() >= AUDIO_DEVICE_API_VERSION_3_0) {
|
|
struct audio_port_config halPortConfig;
|
|
HidlUtils::audioPortConfigToHal(config, &halPortConfig);
|
|
return analyzeStatus(
|
|
"set_audio_port_config", mDevice->set_audio_port_config(mDevice, &halPortConfig));
|
|
}
|
|
return Result::NOT_SUPPORTED;
|
|
}
|
|
|
|
Return<AudioHwSync> Device::getHwAvSync() {
|
|
int halHwAvSync;
|
|
Result retval =
|
|
mParameters->getParam(AudioParameter::keyHwAvSync, &halHwAvSync);
|
|
return retval == Result::OK ? halHwAvSync : AUDIO_HW_SYNC_INVALID;
|
|
}
|
|
|
|
Return<Result> Device::setScreenState(bool turnedOn) {
|
|
return mParameters->setParam(AudioParameter::keyScreenState, turnedOn);
|
|
}
|
|
|
|
Return<void> Device::getParameters(const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb) {
|
|
mParameters->getParametersImpl(keys, _hidl_cb);
|
|
return Void();
|
|
}
|
|
|
|
Return<Result> Device::setParameters(const hidl_vec<ParameterValue>& parameters) {
|
|
return mParameters->setParametersImpl(parameters);
|
|
}
|
|
|
|
Return<void> Device::debugDump(const hidl_handle& fd) {
|
|
if (fd.getNativeHandle() != nullptr && fd->numFds == 1) {
|
|
analyzeStatus("dump", mDevice->dump(mDevice, fd->data[0]));
|
|
}
|
|
return Void();
|
|
}
|
|
|
|
} // namespace implementation
|
|
} // namespace V2_0
|
|
} // namespace audio
|
|
} // namespace hardware
|
|
} // namespace android
|