blob: 5cd9782528017c7569ee18b4c7c541f0a2af445c [file] [log] [blame]
/*
* 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 "AAudio"
//#define LOG_NDEBUG 0
#include <utils/Log.h>
#include <cassert>
#include <aaudio/AAudioDefinitions.h>
#include "AudioEndpointParcelable.h"
#include "AudioEndpoint.h"
#include "AAudioServiceMessage.h"
using namespace android;
using namespace aaudio;
AudioEndpoint::AudioEndpoint()
: mOutputFreeRunning(false)
, mDataReadCounter(0)
, mDataWriteCounter(0)
{
}
AudioEndpoint::~AudioEndpoint()
{
}
static void AudioEndpoint_validateQueueDescriptor(const char *type,
const RingBufferDescriptor *descriptor) {
assert(descriptor->capacityInFrames > 0);
assert(descriptor->bytesPerFrame > 1);
assert(descriptor->dataAddress != nullptr);
ALOGD("AudioEndpoint_validateQueueDescriptor %s, dataAddress at %p ====================",
type,
descriptor->dataAddress);
ALOGD("AudioEndpoint_validateQueueDescriptor readCounter at %p, writeCounter at %p",
descriptor->readCounterAddress,
descriptor->writeCounterAddress);
// Try to READ from the data area.
uint8_t value = descriptor->dataAddress[0];
ALOGD("AudioEndpoint_validateQueueDescriptor() dataAddress[0] = %d, then try to write",
(int) value);
// Try to WRITE to the data area.
descriptor->dataAddress[0] = value;
ALOGD("AudioEndpoint_validateQueueDescriptor() wrote successfully");
if (descriptor->readCounterAddress) {
fifo_counter_t counter = *descriptor->readCounterAddress;
ALOGD("AudioEndpoint_validateQueueDescriptor() *readCounterAddress = %d, now write",
(int) counter);
*descriptor->readCounterAddress = counter;
ALOGD("AudioEndpoint_validateQueueDescriptor() wrote readCounterAddress successfully");
}
if (descriptor->writeCounterAddress) {
fifo_counter_t counter = *descriptor->writeCounterAddress;
ALOGD("AudioEndpoint_validateQueueDescriptor() *writeCounterAddress = %d, now write",
(int) counter);
*descriptor->writeCounterAddress = counter;
ALOGD("AudioEndpoint_validateQueueDescriptor() wrote writeCounterAddress successfully");
}
}
void AudioEndpoint_validateDescriptor(const EndpointDescriptor *pEndpointDescriptor) {
AudioEndpoint_validateQueueDescriptor("msg", &pEndpointDescriptor->upMessageQueueDescriptor);
AudioEndpoint_validateQueueDescriptor("data", &pEndpointDescriptor->downDataQueueDescriptor);
}
aaudio_result_t AudioEndpoint::configure(const EndpointDescriptor *pEndpointDescriptor)
{
aaudio_result_t result = AAUDIO_OK;
AudioEndpoint_validateDescriptor(pEndpointDescriptor); // FIXME remove after debugging
const RingBufferDescriptor *descriptor = &pEndpointDescriptor->upMessageQueueDescriptor;
assert(descriptor->bytesPerFrame == sizeof(AAudioServiceMessage));
assert(descriptor->readCounterAddress != nullptr);
assert(descriptor->writeCounterAddress != nullptr);
mUpCommandQueue = new FifoBuffer(
descriptor->bytesPerFrame,
descriptor->capacityInFrames,
descriptor->readCounterAddress,
descriptor->writeCounterAddress,
descriptor->dataAddress
);
/* TODO mDownCommandQueue
if (descriptor->capacityInFrames > 0) {
descriptor = &pEndpointDescriptor->downMessageQueueDescriptor;
mDownCommandQueue = new FifoBuffer(
descriptor->capacityInFrames,
descriptor->bytesPerFrame,
descriptor->readCounterAddress,
descriptor->writeCounterAddress,
descriptor->dataAddress
);
}
*/
descriptor = &pEndpointDescriptor->downDataQueueDescriptor;
assert(descriptor->capacityInFrames > 0);
assert(descriptor->bytesPerFrame > 1);
assert(descriptor->bytesPerFrame < 4 * 16); // FIXME just for initial debugging
assert(descriptor->framesPerBurst > 0);
assert(descriptor->framesPerBurst < 8 * 1024); // FIXME just for initial debugging
assert(descriptor->dataAddress != nullptr);
ALOGD("AudioEndpoint::configure() data framesPerBurst = %d", descriptor->framesPerBurst);
ALOGD("AudioEndpoint::configure() data readCounterAddress = %p", descriptor->readCounterAddress);
mOutputFreeRunning = descriptor->readCounterAddress == nullptr;
ALOGD("AudioEndpoint::configure() mOutputFreeRunning = %d", mOutputFreeRunning ? 1 : 0);
int64_t *readCounterAddress = (descriptor->readCounterAddress == nullptr)
? &mDataReadCounter
: descriptor->readCounterAddress;
int64_t *writeCounterAddress = (descriptor->writeCounterAddress == nullptr)
? &mDataWriteCounter
: descriptor->writeCounterAddress;
mDownDataQueue = new FifoBuffer(
descriptor->bytesPerFrame,
descriptor->capacityInFrames,
readCounterAddress,
writeCounterAddress,
descriptor->dataAddress
);
uint32_t threshold = descriptor->capacityInFrames / 2;
mDownDataQueue->setThreshold(threshold);
return result;
}
aaudio_result_t AudioEndpoint::readUpCommand(AAudioServiceMessage *commandPtr)
{
return mUpCommandQueue->read(commandPtr, 1);
}
aaudio_result_t AudioEndpoint::writeDataNow(const void *buffer, int32_t numFrames)
{
return mDownDataQueue->write(buffer, numFrames);
}
void AudioEndpoint::setDownDataReadCounter(fifo_counter_t framesRead)
{
mDownDataQueue->setReadCounter(framesRead);
}
fifo_counter_t AudioEndpoint::getDownDataReadCounter()
{
return mDownDataQueue->getReadCounter();
}
void AudioEndpoint::setDownDataWriteCounter(fifo_counter_t framesRead)
{
mDownDataQueue->setWriteCounter(framesRead);
}
fifo_counter_t AudioEndpoint::getDownDataWriteCounter()
{
return mDownDataQueue->getWriteCounter();
}
aaudio_size_frames_t AudioEndpoint::setBufferSizeInFrames(aaudio_size_frames_t requestedFrames,
aaudio_size_frames_t *actualFrames)
{
if (requestedFrames < ENDPOINT_DATA_QUEUE_SIZE_MIN) {
requestedFrames = ENDPOINT_DATA_QUEUE_SIZE_MIN;
}
mDownDataQueue->setThreshold(requestedFrames);
*actualFrames = mDownDataQueue->getThreshold();
return AAUDIO_OK;
}
int32_t AudioEndpoint::getBufferSizeInFrames() const
{
return mDownDataQueue->getThreshold();
}
int32_t AudioEndpoint::getBufferCapacityInFrames() const
{
return (int32_t)mDownDataQueue->getBufferCapacityInFrames();
}
int32_t AudioEndpoint::getFullFramesAvailable()
{
return mDownDataQueue->getFifoControllerBase()->getFullFramesAvailable();
}