blob: 8886f7c3116f697b5125cc5c407ca40e8386a5d8 [file] [log] [blame]
/*
* Copyright (C) 2018 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.
*/
#include <log/log.h>
#include <system/audio.h>
#include PATH(APM_XSD_ENUMS_H_FILENAME)
#include "primary_device.h"
#include "stream_in.h"
#include "stream_out.h"
#include "util.h"
#include "debug.h"
namespace xsd {
using namespace ::android::audio::policy::configuration::CPP_VERSION;
}
namespace android {
namespace hardware {
namespace audio {
namespace CPP_VERSION {
namespace implementation {
constexpr size_t kInBufferDurationMs = 15;
constexpr size_t kOutBufferDurationMs = 22;
using ::android::hardware::Void;
Device::Device() {}
Return<Result> Device::initCheck() {
return Result::OK;
}
Return<Result> Device::setMasterVolume(float volume) {
if (isnan(volume) || volume < 0 || volume > 1.0) {
return FAILURE(Result::INVALID_ARGUMENTS);
}
mMasterVolume = volume;
updateOutputStreamVolume(mMasterMute ? 0.0f : volume);
return Result::OK;
}
Return<void> Device::getMasterVolume(getMasterVolume_cb _hidl_cb) {
_hidl_cb(Result::OK, mMasterVolume);
return Void();
}
Return<Result> Device::setMicMute(bool mute) {
mMicMute = mute;
updateInputStreamMicMute(mute);
return Result::OK;
}
Return<void> Device::getMicMute(getMicMute_cb _hidl_cb) {
_hidl_cb(Result::OK, mMicMute);
return Void();
}
Return<Result> Device::setMasterMute(bool mute) {
mMasterMute = mute;
updateOutputStreamVolume(mute ? 0.0f : mMasterVolume);
return Result::OK;
}
Return<void> Device::getMasterMute(getMasterMute_cb _hidl_cb) {
_hidl_cb(Result::OK, mMasterMute);
return Void();
}
Return<void> Device::getInputBufferSize(const AudioConfig& config, getInputBufferSize_cb _hidl_cb) {
AudioConfig suggestedConfig;
if (util::checkAudioConfig(false, kInBufferDurationMs, config, suggestedConfig)) {
const size_t sz =
suggestedConfig.frameCount
* util::countChannels(suggestedConfig.base.channelMask)
* util::getBytesPerSample(suggestedConfig.base.format);
_hidl_cb(Result::OK, sz);
} else {
_hidl_cb(FAILURE(Result::INVALID_ARGUMENTS), 0);
}
return Void();
}
Return<void> Device::openOutputStream(int32_t ioHandle,
const DeviceAddress& device,
const AudioConfig& config,
const hidl_vec<AudioInOutFlag>& flags,
const SourceMetadata& sourceMetadata,
openOutputStream_cb _hidl_cb) {
auto [result, stream, cfg] = openOutputStreamImpl(ioHandle, device,
config, flags, sourceMetadata);
_hidl_cb(result, stream, cfg);
return Void();
}
Return<void> Device::openInputStream(int32_t ioHandle,
const DeviceAddress& device,
const AudioConfig& config,
const hidl_vec<AudioInOutFlag>& flags,
const SinkMetadata& sinkMetadata,
openInputStream_cb _hidl_cb) {
auto [result, stream, cfg] = openInputStreamImpl(ioHandle, device,
config, flags, sinkMetadata);
_hidl_cb(result, stream, cfg);
return Void();
}
Return<bool> Device::supportsAudioPatches() {
return true;
}
Return<void> Device::createAudioPatch(const hidl_vec<AudioPortConfig>& sources,
const hidl_vec<AudioPortConfig>& sinks,
createAudioPatch_cb _hidl_cb) {
if (sources.size() == 1 && sinks.size() == 1) {
AudioPatch patch;
if (!util::checkAudioPortConfig(sources[0]) || !util::checkAudioPortConfig(sinks[0])) {
_hidl_cb(FAILURE(Result::INVALID_ARGUMENTS), 0);
return Void();
}
patch.source = sources[0];
patch.sink = sinks[0];
AudioPatchHandle handle;
while (true) {
handle = mNextAudioPatchHandle;
mNextAudioPatchHandle = std::max(handle + 1, 0);
if (mAudioPatches.insert({handle, patch}).second) {
break;
}
}
_hidl_cb(Result::OK, handle);
} else {
_hidl_cb(FAILURE(Result::NOT_SUPPORTED), 0);
}
return Void();
}
Return<void> Device::updateAudioPatch(AudioPatchHandle previousPatchHandle,
const hidl_vec<AudioPortConfig>& sources,
const hidl_vec<AudioPortConfig>& sinks,
updateAudioPatch_cb _hidl_cb) {
const auto i = mAudioPatches.find(previousPatchHandle);
if (i == mAudioPatches.end()) {
_hidl_cb(FAILURE(Result::INVALID_ARGUMENTS), previousPatchHandle);
} else {
if (sources.size() == 1 && sinks.size() == 1) {
AudioPatch patch;
patch.source = sources[0];
patch.sink = sinks[0];
i->second = patch;
_hidl_cb(Result::OK, previousPatchHandle);
} else {
_hidl_cb(Result::NOT_SUPPORTED, previousPatchHandle);
}
}
return Void();
}
Return<Result> Device::releaseAudioPatch(AudioPatchHandle patchHandle) {
return (mAudioPatches.erase(patchHandle) == 1) ? Result::OK : FAILURE(Result::INVALID_ARGUMENTS);
}
Return<void> Device::getAudioPort(const AudioPort& port, getAudioPort_cb _hidl_cb) {
_hidl_cb(FAILURE(Result::NOT_SUPPORTED), port);
return Void();
}
Return<Result> Device::setAudioPortConfig(const AudioPortConfig& config) {
(void)config;
return FAILURE(Result::NOT_SUPPORTED);
}
Return<Result> Device::setScreenState(bool turnedOn) {
(void)turnedOn;
return Result::OK;
}
Return<void> Device::getHwAvSync(getHwAvSync_cb _hidl_cb) {
_hidl_cb(FAILURE(Result::NOT_SUPPORTED), {});
return Void();
}
Return<void> Device::getParameters(const hidl_vec<ParameterValue>& context,
const hidl_vec<hidl_string>& keys,
getParameters_cb _hidl_cb) {
(void)context;
if (keys.size() == 0) {
_hidl_cb(Result::OK, {});
} else {
_hidl_cb(FAILURE(Result::NOT_SUPPORTED), {});
}
return Void();
}
Return<Result> Device::setParameters(const hidl_vec<ParameterValue>& context,
const hidl_vec<ParameterValue>& parameters) {
(void)context;
(void)parameters;
return Result::OK;
}
Return<void> Device::getMicrophones(getMicrophones_cb _hidl_cb) {
_hidl_cb(Result::OK, {util::getMicrophoneInfo()});
return Void();
}
Return<Result> Device::setConnectedState(const DeviceAddress& dev_addr, bool connected) {
(void)dev_addr;
(void)connected;
return FAILURE(Result::NOT_SUPPORTED);
}
Return<Result> Device::close() {
std::lock_guard<std::mutex> guard(mMutex);
return (mInputStreams.empty() && mOutputStreams.empty())
? Result::OK : FAILURE(Result::INVALID_STATE);
}
Return<Result> Device::addDeviceEffect(AudioPortHandle device, uint64_t effectId) {
(void)device;
(void)effectId;
return FAILURE(Result::NOT_SUPPORTED);
}
Return<Result> Device::removeDeviceEffect(AudioPortHandle device, uint64_t effectId) {
(void)device;
(void)effectId;
return FAILURE(Result::NOT_SUPPORTED);
}
void Device::unrefDevice(StreamIn *sin) {
std::lock_guard<std::mutex> guard(mMutex);
LOG_ALWAYS_FATAL_IF(mInputStreams.erase(sin) < 1);
}
void Device::unrefDevice(StreamOut *sout) {
std::lock_guard<std::mutex> guard(mMutex);
LOG_ALWAYS_FATAL_IF(mOutputStreams.erase(sout) < 1);
}
void Device::updateOutputStreamVolume(float masterVolume) const {
std::lock_guard<std::mutex> guard(mMutex);
for (StreamOut *stream : mOutputStreams) {
stream->setMasterVolume(masterVolume);
}
}
void Device::updateInputStreamMicMute(bool micMute) const {
std::lock_guard<std::mutex> guard(mMutex);
for (StreamIn *stream : mInputStreams) {
stream->setMicMute(micMute);
}
}
std::tuple<Result, sp<IStreamOut>, AudioConfig> Device::openOutputStreamImpl(
int32_t ioHandle, const DeviceAddress& device,
const AudioConfig& config, const hidl_vec<AudioInOutFlag>& flags,
const SourceMetadata& sourceMetadata) {
if (!StreamOut::validateDeviceAddress(device)
|| !util::checkAudioConfig(config)
|| !StreamOut::validateFlags(flags)
|| !StreamOut::validateSourceMetadata(sourceMetadata)) {
return {FAILURE(Result::INVALID_ARGUMENTS), {}, {}};
}
AudioConfig suggestedConfig;
if (util::checkAudioConfig(true, kOutBufferDurationMs, config, suggestedConfig)) {
auto stream = std::make_unique<StreamOut>(
this, ioHandle, device, suggestedConfig, flags, sourceMetadata);
stream->setMasterVolume(mMasterMute ? 0.0f : mMasterVolume);
{
std::lock_guard<std::mutex> guard(mMutex);
LOG_ALWAYS_FATAL_IF(!mOutputStreams.insert(stream.get()).second);
}
return {Result::OK, stream.release(), suggestedConfig};
}
return {FAILURE(Result::INVALID_ARGUMENTS), {}, suggestedConfig};
}
std::tuple<Result, sp<IStreamIn>, AudioConfig> Device::openInputStreamImpl(
int32_t ioHandle, const DeviceAddress& device,
const AudioConfig& config, const hidl_vec<AudioInOutFlag>& flags,
const SinkMetadata& sinkMetadata) {
if (!StreamIn::validateDeviceAddress(device)
|| !util::checkAudioConfig(config)
|| !StreamIn::validateFlags(flags)
|| !StreamIn::validateSinkMetadata(sinkMetadata)) {
return {FAILURE(Result::INVALID_ARGUMENTS), {}, {}};
}
AudioConfig suggestedConfig;
if (util::checkAudioConfig(false, kInBufferDurationMs, config, suggestedConfig)) {
auto stream = std::make_unique<StreamIn>(
this, ioHandle, device, suggestedConfig, flags, sinkMetadata);
stream->setMicMute(mMicMute);
{
std::lock_guard<std::mutex> guard(mMutex);
LOG_ALWAYS_FATAL_IF(!mInputStreams.insert(stream.get()).second);
}
return {Result::OK, stream.release(), suggestedConfig};
}
return {FAILURE(Result::INVALID_ARGUMENTS), {}, suggestedConfig};
}
#if MAJOR_VERSION == 7 && MINOR_VERSION == 1
Return<void> Device::openOutputStream_7_1(int32_t ioHandle, const DeviceAddress& device,
const AudioConfig& config, const hidl_vec<AudioInOutFlag>& flags,
const SourceMetadata& sourceMetadata, openOutputStream_7_1_cb _hidl_cb) {
auto [result, stream, cfg] = openOutputStreamImpl(ioHandle, device,
config, flags, sourceMetadata);
_hidl_cb(result, stream, cfg);
return Void();
}
Return<Result> Device::setConnectedState_7_1(const AudioPort& devicePort,
bool connected) {
(void)devicePort;
(void)connected;
return FAILURE(Result::NOT_SUPPORTED);
}
#endif
// ==================
PrimaryDevice::PrimaryDevice() : mDevice(sp<Device>::make()) {
}
Return<Result> PrimaryDevice::initCheck() {
return mDevice->initCheck();
}
Return<Result> PrimaryDevice::setMasterVolume(float volume) {
return mDevice->setMasterVolume(volume);
}
Return<void> PrimaryDevice::getMasterVolume(getMasterVolume_cb _hidl_cb) {
return mDevice->getMasterVolume(_hidl_cb);
}
Return<Result> PrimaryDevice::setMicMute(bool mute) {
return mDevice->setMicMute(mute);
}
Return<void> PrimaryDevice::getMicMute(getMicMute_cb _hidl_cb) {
return mDevice->getMicMute(_hidl_cb);
}
Return<Result> PrimaryDevice::setMasterMute(bool mute) {
return mDevice->setMasterMute(mute);
}
Return<void> PrimaryDevice::getMasterMute(getMasterMute_cb _hidl_cb) {
return mDevice->getMasterMute(_hidl_cb);
}
Return<void> PrimaryDevice::getInputBufferSize(const AudioConfig& config,
getInputBufferSize_cb _hidl_cb) {
return mDevice->getInputBufferSize(config, _hidl_cb);
}
Return<void> PrimaryDevice::openOutputStream(int32_t ioHandle,
const DeviceAddress& device,
const AudioConfig& config,
const hidl_vec<AudioInOutFlag>& flags,
const SourceMetadata& sourceMetadata,
openOutputStream_cb _hidl_cb) {
return mDevice->openOutputStream(ioHandle, device, config, flags, sourceMetadata, _hidl_cb);
}
Return<void> PrimaryDevice::openInputStream(int32_t ioHandle,
const DeviceAddress& device,
const AudioConfig& config,
const hidl_vec<AudioInOutFlag>& flags,
const SinkMetadata& sinkMetadata,
openInputStream_cb _hidl_cb) {
return mDevice->openInputStream(ioHandle, device, config, flags, sinkMetadata, _hidl_cb);
}
Return<bool> PrimaryDevice::supportsAudioPatches() {
return mDevice->supportsAudioPatches();
}
Return<void> PrimaryDevice::createAudioPatch(const hidl_vec<AudioPortConfig>& sources,
const hidl_vec<AudioPortConfig>& sinks,
createAudioPatch_cb _hidl_cb) {
return mDevice->createAudioPatch(sources, sinks, _hidl_cb);
}
Return<void> PrimaryDevice::updateAudioPatch(int32_t previousPatch,
const hidl_vec<AudioPortConfig>& sources,
const hidl_vec<AudioPortConfig>& sinks,
updateAudioPatch_cb _hidl_cb) {
return mDevice->updateAudioPatch(previousPatch, sources, sinks, _hidl_cb);
}
Return<Result> PrimaryDevice::releaseAudioPatch(int32_t patch) {
return mDevice->releaseAudioPatch(patch);
}
Return<void> PrimaryDevice::getAudioPort(const AudioPort& port, getAudioPort_cb _hidl_cb) {
return mDevice->getAudioPort(port, _hidl_cb);
}
Return<Result> PrimaryDevice::setAudioPortConfig(const AudioPortConfig& config) {
return mDevice->setAudioPortConfig(config);
}
Return<Result> PrimaryDevice::setScreenState(bool turnedOn) {
return mDevice->setScreenState(turnedOn);
}
Return<void> PrimaryDevice::getHwAvSync(getHwAvSync_cb _hidl_cb) {
return mDevice->getHwAvSync(_hidl_cb);
}
Return<void> PrimaryDevice::getParameters(const hidl_vec<ParameterValue>& context,
const hidl_vec<hidl_string>& keys,
getParameters_cb _hidl_cb) {
return mDevice->getParameters(context, keys, _hidl_cb);
}
Return<Result> PrimaryDevice::setParameters(const hidl_vec<ParameterValue>& context,
const hidl_vec<ParameterValue>& parameters) {
return mDevice->setParameters(context, parameters);
}
Return<void> PrimaryDevice::getMicrophones(getMicrophones_cb _hidl_cb) {
return mDevice->getMicrophones(_hidl_cb);
}
Return<Result> PrimaryDevice::setConnectedState(const DeviceAddress& dev_addr, bool connected) {
return mDevice->setConnectedState(dev_addr, connected);
}
Return<Result> PrimaryDevice::close() {
return mDevice->close();
}
Return<Result> PrimaryDevice::addDeviceEffect(AudioPortHandle device, uint64_t effectId) {
return mDevice->addDeviceEffect(device, effectId);
}
Return<Result> PrimaryDevice::removeDeviceEffect(AudioPortHandle device, uint64_t effectId) {
return mDevice->removeDeviceEffect(device, effectId);
}
Return<Result> PrimaryDevice::setVoiceVolume(float volume) {
return (volume >= 0 && volume <= 1.0) ? Result::OK : FAILURE(Result::INVALID_ARGUMENTS);
}
Return<Result> PrimaryDevice::setMode(AudioMode mode) {
switch (mode) {
case AudioMode::NORMAL:
case AudioMode::RINGTONE:
case AudioMode::IN_CALL:
case AudioMode::IN_COMMUNICATION:
return Result::OK;
default:
return FAILURE(Result::INVALID_ARGUMENTS);
}
}
Return<Result> PrimaryDevice::setBtScoHeadsetDebugName(const hidl_string& name) {
(void)name;
return FAILURE(Result::NOT_SUPPORTED);
}
Return<void> PrimaryDevice::getBtScoNrecEnabled(getBtScoNrecEnabled_cb _hidl_cb) {
_hidl_cb(FAILURE(Result::NOT_SUPPORTED), false);
return Void();
}
Return<Result> PrimaryDevice::setBtScoNrecEnabled(bool enabled) {
(void)enabled;
return FAILURE(Result::NOT_SUPPORTED);
}
Return<void> PrimaryDevice::getBtScoWidebandEnabled(getBtScoWidebandEnabled_cb _hidl_cb) {
_hidl_cb(FAILURE(Result::NOT_SUPPORTED), false);
return Void();
}
Return<Result> PrimaryDevice::setBtScoWidebandEnabled(bool enabled) {
(void)enabled;
return FAILURE(Result::NOT_SUPPORTED);
}
Return<void> PrimaryDevice::getTtyMode(getTtyMode_cb _hidl_cb) {
_hidl_cb(FAILURE(Result::NOT_SUPPORTED), TtyMode::OFF);
return Void();
}
Return<Result> PrimaryDevice::setTtyMode(IPrimaryDevice::TtyMode mode) {
(void)mode;
return FAILURE(Result::NOT_SUPPORTED);
}
Return<void> PrimaryDevice::getHacEnabled(getHacEnabled_cb _hidl_cb) {
_hidl_cb(FAILURE(Result::NOT_SUPPORTED), false);
return Void();
}
Return<Result> PrimaryDevice::setHacEnabled(bool enabled) {
(void)enabled;
return FAILURE(Result::NOT_SUPPORTED);
}
Return<void> PrimaryDevice::getBtHfpEnabled(getBtHfpEnabled_cb _hidl_cb) {
_hidl_cb(FAILURE(Result::NOT_SUPPORTED), false);
return Void();
}
Return<Result> PrimaryDevice::setBtHfpEnabled(bool enabled) {
(void)enabled;
return FAILURE(Result::NOT_SUPPORTED);
}
Return<Result> PrimaryDevice::setBtHfpSampleRate(uint32_t sampleRateHz) {
(void)sampleRateHz;
return FAILURE(Result::NOT_SUPPORTED);
}
Return<Result> PrimaryDevice::setBtHfpVolume(float volume) {
(void)volume;
return FAILURE(Result::NOT_SUPPORTED);
}
Return<Result> PrimaryDevice::updateRotation(IPrimaryDevice::Rotation rotation) {
(void)rotation;
return FAILURE(Result::NOT_SUPPORTED);
}
} // namespace implementation
} // namespace CPP_VERSION
} // namespace audio
} // namespace hardware
} // namespace android