#include <aaudio/AAudio.h>
#include <aaudio/AAudioTesting.h>
-#include <AAudioExampleUtils.h>
+
+#include "AAudioExampleUtils.h"
// TODO use this as a base class within AAudio
class AAudioParameters {
* Print stream parameters in comparison with requested values.
* @param stream
*/
- void compareWithStream(AAudioStream *stream) {
+ void compareWithStream(AAudioStream *stream) const {
printf(" DeviceId: requested = %d, actual = %d\n",
getDeviceId(), AAudioStream_getDeviceId(stream));
int64_t startTime;
ALOGD("AudioStreamInternal()::requestStart()");
if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) {
+ ALOGE("AudioStreamInternal::requestStart() mServiceStreamHandle invalid");
return AAUDIO_ERROR_INVALID_STATE;
}
if (isActive()) {
+ ALOGE("AudioStreamInternal::requestStart() already active");
return AAUDIO_ERROR_INVALID_STATE;
}
aaudio_stream_state_t originalState = getState();
aaudio_result_t AudioStreamInternal::registerThread() {
if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) {
+ ALOGE("AudioStreamInternal::registerThread() mServiceStreamHandle invalid");
return AAUDIO_ERROR_INVALID_STATE;
}
return mServiceInterface.registerAudioThread(mServiceStreamHandle,
aaudio_result_t AudioStreamInternal::unregisterThread() {
if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) {
+ ALOGE("AudioStreamInternal::unregisterThread() mServiceStreamHandle invalid");
return AAUDIO_ERROR_INVALID_STATE;
}
return mServiceInterface.unregisterAudioThread(mServiceStreamHandle, gettid());
aaudio_result_t result = AAUDIO_OK;
switch (message->event.event) {
case AAUDIO_SERVICE_EVENT_STARTED:
- ALOGD("AudioStreamInternal::onEventFromServergot() AAUDIO_SERVICE_EVENT_STARTED");
+ ALOGD("AudioStreamInternal::onEventFromServer() got AAUDIO_SERVICE_EVENT_STARTED");
if (getState() == AAUDIO_STREAM_STATE_STARTING) {
setState(AAUDIO_STREAM_STATE_STARTED);
}
break;
case AAUDIO_SERVICE_EVENT_PAUSED:
- ALOGD("AudioStreamInternal::onEventFromServergot() AAUDIO_SERVICE_EVENT_PAUSED");
+ ALOGD("AudioStreamInternal::onEventFromServer() got AAUDIO_SERVICE_EVENT_PAUSED");
if (getState() == AAUDIO_STREAM_STATE_PAUSING) {
setState(AAUDIO_STREAM_STATE_PAUSED);
}
break;
case AAUDIO_SERVICE_EVENT_STOPPED:
- ALOGD("AudioStreamInternal::onEventFromServergot() AAUDIO_SERVICE_EVENT_STOPPED");
+ ALOGD("AudioStreamInternal::onEventFromServer() got AAUDIO_SERVICE_EVENT_STOPPED");
if (getState() == AAUDIO_STREAM_STATE_STOPPING) {
setState(AAUDIO_STREAM_STATE_STOPPED);
}
AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
ALOGD("AAudioStream_requestStart(%p) called --------------", stream);
aaudio_result_t result = audioStream->requestStart();
- ALOGD("AAudioStream_requestStart(%p) returned ------------", stream);
+ ALOGD("AAudioStream_requestStart(%p) returned %d ---------", stream, result);
return result;
}
void* threadArg)
{
if (mHasThread) {
+ ALOGE("AudioStream::createThread() - mHasThread already true");
return AAUDIO_ERROR_INVALID_STATE;
}
if (threadProc == nullptr) {
aaudio_result_t AudioStream::joinThread(void** returnArg, int64_t timeoutNanoseconds)
{
if (!mHasThread) {
+ ALOGE("AudioStream::joinThread() - but has no thread");
return AAUDIO_ERROR_INVALID_STATE;
}
#if 0
std::lock_guard<std::mutex> lock(mStreamMutex);
if (mAudioTrack.get() == nullptr) {
+ ALOGE("AudioStreamTrack::requestStart() no AudioTrack");
return AAUDIO_ERROR_INVALID_STATE;
}
// Get current position so we can detect when the track is playing.
std::lock_guard<std::mutex> lock(mStreamMutex);
if (mAudioTrack.get() == nullptr) {
+ ALOGE("AudioStreamTrack::requestPause() no AudioTrack");
return AAUDIO_ERROR_INVALID_STATE;
} else if (getState() != AAUDIO_STREAM_STATE_STARTING
&& getState() != AAUDIO_STREAM_STATE_STARTED) {
std::lock_guard<std::mutex> lock(mStreamMutex);
if (mAudioTrack.get() == nullptr) {
+ ALOGE("AudioStreamTrack::requestFlush() no AudioTrack");
return AAUDIO_ERROR_INVALID_STATE;
} else if (getState() != AAUDIO_STREAM_STATE_PAUSED) {
+ ALOGE("AudioStreamTrack::requestFlush() not paused");
return AAUDIO_ERROR_INVALID_STATE;
}
setState(AAUDIO_STREAM_STATE_FLUSHING);
std::lock_guard<std::mutex> lock(mStreamMutex);
if (mAudioTrack.get() == nullptr) {
+ ALOGE("AudioStreamTrack::requestStop() no AudioTrack");
return AAUDIO_ERROR_INVALID_STATE;
}
onStop();
}
result << " Registered Streams:" << "\n";
+ result << AAudioServiceStreamShared::dumpHeader() << "\n";
for (sp<AAudioServiceStreamShared> sharedStream : mRegisteredStreams) {
- result << sharedStream->dump();
+ result << sharedStream->dump() << "\n";
}
if (isLocked) {
// Mix data from each application stream and write result to the shared MMAP stream.
void *AAudioServiceEndpointPlay::callbackLoop() {
- int32_t underflowCount = 0;
aaudio_result_t result = AAUDIO_OK;
int64_t timeoutNanos = getStreamInternal()->calculateReasonableTimeout();
float volume = 1.0; // to match legacy volume
bool underflowed = mMixer.mix(index, fifo, volume);
- underflowCount += underflowed ? 1 : 0;
- // TODO log underflows in each stream
// This timestamp represents the completion of data being read out of the
// client buffer. It is sent to the client and used in the timing model
// to decide when the client has room to write more data.
Timestamp timestamp(fifo->getReadCounter(), AudioClock::getNanoseconds());
clientStream->markTransferTime(timestamp);
+
+ if (underflowed) {
+ clientStream->incrementXRunCount();
+ }
}
index++;
}
}
}
- ALOGW_IF((underflowCount > 0),
- "AAudioServiceEndpointPlay(): callbackLoop() had %d underflows", underflowCount);
-
return NULL; // TODO review
}
//#define LOG_NDEBUG 0
#include <utils/Log.h>
+#include <iomanip>
+#include <iostream>
#include <mutex>
#include "binding/IAAudioService.h"
"service stream still open, state = %d", mState);
}
+std::string AAudioServiceStreamBase::dumpHeader() {
+ return std::string(" T Handle UId Run State Format Burst Chan Capacity");
+}
+
std::string AAudioServiceStreamBase::dump() const {
std::stringstream result;
- result << " -------- handle = 0x" << std::hex << mHandle << std::dec << "\n";
- result << " state = " << AAudio_convertStreamStateToText(mState) << "\n";
- result << " format = " << mAudioFormat << "\n";
- result << " framesPerBurst = " << mFramesPerBurst << "\n";
- result << " channelCount = " << mSamplesPerFrame << "\n";
- result << " capacityFrames = " << mCapacityInFrames << "\n";
- result << " owner uid = " << mMmapClient.clientUid << "\n";
+ result << " 0x" << std::setfill('0') << std::setw(8) << std::hex << mHandle
+ << std::dec << std::setfill(' ') ;
+ result << std::setw(6) << mMmapClient.clientUid;
+ result << std::setw(4) << (isRunning() ? "yes" : " no");
+ result << std::setw(6) << mState;
+ result << std::setw(7) << mAudioFormat;
+ result << std::setw(6) << mFramesPerBurst;
+ result << std::setw(5) << mSamplesPerFrame;
+ result << std::setw(9) << mCapacityInFrames;
return result.str();
}
ILLEGAL_THREAD_ID = 0
};
- std::string dump() const;
+ static std::string dumpHeader();
+
+ // does not include EOL
+ virtual std::string dump() const;
// -------------------------------------------------------------------
/**
//#define LOG_NDEBUG 0
#include <utils/Log.h>
+#include <iomanip>
+#include <iostream>
#include <mutex>
#include <aaudio/AAudio.h>
AAudioServiceStreamShared::AAudioServiceStreamShared(AAudioService &audioService)
: mAudioService(audioService)
, mTimestampPositionOffset(0)
+ , mXRunCount(0)
{
}
+std::string AAudioServiceStreamShared::dumpHeader() {
+ std::stringstream result;
+ result << AAudioServiceStreamBase::dumpHeader();
+ result << " Write# Read# Avail XRuns";
+ return result.str();
+}
+
+std::string AAudioServiceStreamShared::dump() const {
+ std::stringstream result;
+ result << AAudioServiceStreamBase::dump();
+
+ auto fifo = mAudioDataQueue->getFifoBuffer();
+ int32_t readCounter = fifo->getReadCounter();
+ int32_t writeCounter = fifo->getWriteCounter();
+ result << std::setw(10) << writeCounter;
+ result << std::setw(10) << readCounter;
+ result << std::setw(8) << (writeCounter - readCounter);
+ result << std::setw(8) << getXRunCount();
+
+ return result.str();
+}
+
int32_t AAudioServiceStreamShared::calculateBufferCapacity(int32_t requestedCapacityFrames,
int32_t framesPerBurst) {
}
AAudioServiceEndpoint *endpoint = mServiceEndpoint;
if (endpoint == nullptr) {
+ ALOGE("AAudioServiceStreamShared::start() missing endpoint");
return AAUDIO_ERROR_INVALID_STATE;
}
// For output streams, this will add the stream to the mixer.
}
AAudioServiceEndpoint *endpoint = mServiceEndpoint;
if (endpoint == nullptr) {
+ ALOGE("AAudioServiceStreamShared::pause() missing endpoint");
return AAUDIO_ERROR_INVALID_STATE;
}
endpoint->getStreamInternal()->stopClient(mClientHandle);
}
AAudioServiceEndpoint *endpoint = mServiceEndpoint;
if (endpoint == nullptr) {
+ ALOGE("AAudioServiceStreamShared::stop() missing endpoint");
return AAUDIO_ERROR_INVALID_STATE;
}
endpoint->getStreamInternal()->stopClient(mClientHandle);
aaudio_result_t AAudioServiceStreamShared::flush() {
AAudioServiceEndpoint *endpoint = mServiceEndpoint;
if (endpoint == nullptr) {
+ ALOGE("AAudioServiceStreamShared::flush() missing endpoint");
return AAUDIO_ERROR_INVALID_STATE;
}
if (mState != AAUDIO_STREAM_STATE_PAUSED) {
AAudioServiceStreamShared(android::AAudioService &aAudioService);
virtual ~AAudioServiceStreamShared() = default;
+ static std::string dumpHeader();
+
+ std::string dump() const override;
+
aaudio_result_t open(const aaudio::AAudioStreamRequest &request,
aaudio::AAudioStreamConfiguration &configurationOutput) override;
mTimestampPositionOffset.store(deltaFrames);
}
+ void incrementXRunCount() {
+ mXRunCount++;
+ }
+
+ int32_t getXRunCount() const {
+ return mXRunCount.load();
+ }
+
protected:
aaudio_result_t getDownDataDescription(AudioEndpointParcelable &parcelable) override;
SharedRingBuffer *mAudioDataQueue = nullptr;
std::atomic<int64_t> mTimestampPositionOffset;
+ std::atomic<int32_t> mXRunCount;
};
} /* namespace aaudio */
aaudio_result_t AAudioThread::start(Runnable *runnable) {
if (mHasThread) {
- ALOGE("AAudioThread::start() - mHasThread.load() already true");
+ ALOGE("AAudioThread::start() - mHasThread already true");
return AAUDIO_ERROR_INVALID_STATE;
}
// mRunnable will be read by the new thread when it starts.
aaudio_result_t AAudioThread::stop() {
if (!mHasThread) {
+ ALOGE("AAudioThread::stop() but no thread running");
return AAUDIO_ERROR_INVALID_STATE;
}
int err = pthread_join(mThread, nullptr);