summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authorGlenn Kasten <gkasten@google.com>2012-02-28 10:39:56 -0800
committerGlenn Kasten <gkasten@google.com>2012-04-22 14:50:01 -0700
commit3acbd053c842e76e1a40fc8a0bf62de87eebf00f (patch)
tree1d6dcc01039a1af770131c6b427efa27a2e5755f /media
parentf853499c6a088ef8506cacbb3ccdffa87e0cec3e (diff)
downloadframeworks_av-3acbd053c842e76e1a40fc8a0bf62de87eebf00f.zip
frameworks_av-3acbd053c842e76e1a40fc8a0bf62de87eebf00f.tar.gz
frameworks_av-3acbd053c842e76e1a40fc8a0bf62de87eebf00f.tar.bz2
Configure policy of mediaserver threads
Change-Id: Ifd825590ba36996064a458f64453a94b84722cb0
Diffstat (limited to 'media')
-rw-r--r--media/libmedia/AudioRecord.cpp8
-rw-r--r--media/libmedia/AudioTrack.cpp113
-rw-r--r--media/libmedia/IAudioFlinger.cpp5
-rw-r--r--media/libmedia/IAudioRecord.cpp6
-rw-r--r--media/libmedia/IAudioTrack.cpp5
5 files changed, 93 insertions, 44 deletions
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index 1fdc536..950f5c6 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -321,8 +321,8 @@ status_t AudioRecord::start(AudioSystem::sync_event_t event, int triggerSession)
cblk->lock.lock();
if (!(cblk->flags & CBLK_INVALID_MSK)) {
cblk->lock.unlock();
- ALOGV("mAudioRecord->start(tid=%d)", tid);
- ret = mAudioRecord->start(tid, event, triggerSession);
+ ALOGV("mAudioRecord->start()");
+ ret = mAudioRecord->start(event, triggerSession);
cblk->lock.lock();
if (ret == DEAD_OBJECT) {
android_atomic_or(CBLK_INVALID_ON, &cblk->flags);
@@ -542,7 +542,7 @@ status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
"user=%08x, server=%08x", cblk->user, cblk->server);
cblk->lock.unlock();
// callback thread or sync event hasn't changed
- result = mAudioRecord->start(0, AudioSystem::SYNC_EVENT_SAME, 0);
+ result = mAudioRecord->start(AudioSystem::SYNC_EVENT_SAME, 0);
cblk->lock.lock();
if (result == DEAD_OBJECT) {
android_atomic_or(CBLK_INVALID_ON, &cblk->flags);
@@ -781,7 +781,7 @@ status_t AudioRecord::restoreRecord_l(audio_track_cblk_t*& cblk)
mFrameCount, getInput_l());
if (result == NO_ERROR) {
// callback thread or sync event hasn't changed
- result = mAudioRecord->start(0, AudioSystem::SYNC_EVENT_SAME, 0);
+ result = mAudioRecord->start(AudioSystem::SYNC_EVENT_SAME, 0);
}
if (result != NO_ERROR) {
mActive = false;
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 25d79d6..9d338f3 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -73,6 +73,8 @@ status_t AudioTrack::getMinFrameCount(
*frameCount = (sampleRate == 0) ? afFrameCount * minBufCount :
afFrameCount * minBufCount * sampleRate / afSampleRate;
+ ALOGV("getMinFrameCount=%d: afFrameCount=%d, minBufCount=%d, afSampleRate=%d, afLatency=%d",
+ *frameCount, afFrameCount, minBufCount, afSampleRate, afLatency);
return NO_ERROR;
}
@@ -159,6 +161,7 @@ AudioTrack::~AudioTrack()
// Otherwise the callback thread will never exit.
stop();
if (mAudioTrackThread != 0) {
+ mAudioTrackThread->requestExit(); // see comment in AudioTrack.h
mAudioTrackThread->requestExitAndWait();
mAudioTrackThread.clear();
}
@@ -223,6 +226,7 @@ status_t AudioTrack::set(
// force direct flag if format is not linear PCM
if (!audio_is_linear_pcm(format)) {
flags = (audio_output_flags_t)
+ // FIXME why can't we allow direct AND fast?
((flags | AUDIO_OUTPUT_FLAG_DIRECT) & ~AUDIO_OUTPUT_FLAG_FAST);
}
// only allow deep buffering for music stream type
@@ -255,6 +259,11 @@ status_t AudioTrack::set(
mAuxEffectId = 0;
mCbf = cbf;
+ if (cbf != NULL) {
+ mAudioTrackThread = new AudioTrackThread(*this, threadCanCallJava);
+ mAudioTrackThread->run("AudioTrack", ANDROID_PRIORITY_AUDIO, 0 /*stack*/);
+ }
+
// create the IAudioTrack
status_t status = createTrack_l(streamType,
sampleRate,
@@ -266,13 +275,13 @@ status_t AudioTrack::set(
output);
if (status != NO_ERROR) {
+ if (mAudioTrackThread != 0) {
+ mAudioTrackThread->requestExit();
+ mAudioTrackThread.clear();
+ }
return status;
}
- if (cbf != NULL) {
- mAudioTrackThread = new AudioTrackThread(*this, threadCanCallJava);
- }
-
mStatus = NO_ERROR;
mStreamType = streamType;
@@ -349,14 +358,6 @@ void AudioTrack::start()
status_t status = NO_ERROR;
ALOGV("start %p", this);
- if (t != 0) {
- if (t->exitPending()) {
- if (t->requestExitAndWait() == WOULD_BLOCK) {
- ALOGE("AudioTrack::start called from thread");
- return;
- }
- }
- }
AutoMutex lock(mLock);
// acquire a strong reference on the IMemory and IAudioTrack so that they cannot be destroyed
@@ -373,26 +374,19 @@ void AudioTrack::start()
cblk->bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS;
cblk->waitTimeMs = 0;
android_atomic_and(~CBLK_DISABLED_ON, &cblk->flags);
- pid_t tid;
if (t != 0) {
- t->run("AudioTrack", ANDROID_PRIORITY_AUDIO);
- tid = t->getTid(); // pid_t is unknown until run()
- ALOGV("getTid=%d", tid);
- if (tid == -1) {
- tid = 0;
- }
+ t->resume();
} else {
mPreviousPriority = getpriority(PRIO_PROCESS, 0);
mPreviousSchedulingGroup = androidGetThreadSchedulingGroup(0);
androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO);
- tid = 0; // not gettid()
}
ALOGV("start %p before lock cblk %p", this, mCblk);
if (!(cblk->flags & CBLK_INVALID_MSK)) {
cblk->lock.unlock();
- ALOGV("mAudioTrack->start(tid=%d)", tid);
- status = mAudioTrack->start(tid);
+ ALOGV("mAudioTrack->start()");
+ status = mAudioTrack->start();
cblk->lock.lock();
if (status == DEAD_OBJECT) {
android_atomic_or(CBLK_INVALID_ON, &cblk->flags);
@@ -406,7 +400,7 @@ void AudioTrack::start()
ALOGV("start() failed");
mActive = false;
if (t != 0) {
- t->requestExit();
+ t->pause();
} else {
setpriority(PRIO_PROCESS, 0, mPreviousPriority);
androidSetThreadSchedulingGroup(0, mPreviousSchedulingGroup);
@@ -439,7 +433,7 @@ void AudioTrack::stop()
flush_l();
}
if (t != 0) {
- t->requestExit();
+ t->pause();
} else {
setpriority(PRIO_PROCESS, 0, mPreviousPriority);
androidSetThreadSchedulingGroup(0, mPreviousSchedulingGroup);
@@ -771,7 +765,7 @@ status_t AudioTrack::createTrack_l(
(sharedBuffer != 0) ||
// use case 2: callback handler
(mCbf != NULL))) {
- ALOGW("AUDIO_OUTPUT_FLAG_FAST denied");
+ ALOGW("AUDIO_OUTPUT_FLAG_FAST denied by client");
flags = (audio_output_flags_t) (flags & ~AUDIO_OUTPUT_FLAG_FAST);
}
ALOGV("createTrack_l() output %d afFrameCount %d afLatency %d", output, afFrameCount, afLatency);
@@ -787,6 +781,13 @@ status_t AudioTrack::createTrack_l(
if (minBufCount < 2) minBufCount = 2;
int minFrameCount = (afFrameCount*sampleRate*minBufCount)/afSampleRate;
+ ALOGV("minFrameCount: %d, afFrameCount=%d, minBufCount=%d, sampleRate=%d, afSampleRate=%d"
+ ", afLatency=%d",
+ minFrameCount, afFrameCount, minBufCount, sampleRate, afSampleRate, afLatency);
+#define MIN_FRAME_COUNT_FAST 128 // FIXME hard-coded
+ if ((flags & AUDIO_OUTPUT_FLAG_FAST) && (minFrameCount > MIN_FRAME_COUNT_FAST)) {
+ minFrameCount = MIN_FRAME_COUNT_FAST;
+ }
if (sharedBuffer == 0) {
if (frameCount == 0) {
@@ -800,7 +801,7 @@ status_t AudioTrack::createTrack_l(
if (mNotificationFramesAct > (uint32_t)frameCount/2) {
mNotificationFramesAct = frameCount/2;
}
- if (frameCount < minFrameCount && !(flags & AUDIO_OUTPUT_FLAG_FAST)) {
+ if (frameCount < minFrameCount) {
// not ALOGW because it happens all the time when playing key clicks over A2DP
ALOGV("Minimum buffer size corrected from %d to %d",
frameCount, minFrameCount);
@@ -821,8 +822,13 @@ status_t AudioTrack::createTrack_l(
if (mIsTimed) {
trackFlags |= IAudioFlinger::TRACK_TIMED;
}
+
+ pid_t tid = -1;
if (flags & AUDIO_OUTPUT_FLAG_FAST) {
trackFlags |= IAudioFlinger::TRACK_FAST;
+ if (mAudioTrackThread != 0) {
+ tid = mAudioTrackThread->getTid();
+ }
}
sp<IAudioTrack> track = audioFlinger->createTrack(getpid(),
@@ -834,6 +840,7 @@ status_t AudioTrack::createTrack_l(
trackFlags,
sharedBuffer,
output,
+ tid,
&mSessionId,
&status);
@@ -849,7 +856,15 @@ status_t AudioTrack::createTrack_l(
mAudioTrack = track;
mCblkMemory = cblk;
mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer());
- android_atomic_or(CBLK_DIRECTION_OUT, &mCblk->flags);
+ // old has the previous value of mCblk->flags before the "or" operation
+ int32_t old = android_atomic_or(CBLK_DIRECTION_OUT, &mCblk->flags);
+ if (flags & AUDIO_OUTPUT_FLAG_FAST) {
+ if (old & CBLK_FAST) {
+ ALOGI("AUDIO_OUTPUT_FLAG_FAST successful; frameCount %u", mCblk->frameCount);
+ } else {
+ ALOGW("AUDIO_OUTPUT_FLAG_FAST denied by server; frameCount %u", mCblk->frameCount);
+ }
+ }
if (sharedBuffer == 0) {
mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
} else {
@@ -926,7 +941,7 @@ status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
"user=%08x, server=%08x", this, cblk->user, cblk->server);
//unlock cblk mutex before calling mAudioTrack->start() (see issue #1617140)
cblk->lock.unlock();
- result = mAudioTrack->start(0); // callback thread hasn't changed
+ result = mAudioTrack->start();
cblk->lock.lock();
if (result == DEAD_OBJECT) {
android_atomic_or(CBLK_INVALID_ON, &cblk->flags);
@@ -958,7 +973,7 @@ create_new_track:
if (mActive && (cblk->flags & CBLK_DISABLED_MSK)) {
android_atomic_and(~CBLK_DISABLED_ON, &cblk->flags);
ALOGW("obtainBuffer() track %p disabled, restarting", this);
- mAudioTrack->start(0); // callback thread hasn't changed
+ mAudioTrack->start();
}
cblk->waitTimeMs = 0;
@@ -1096,7 +1111,7 @@ status_t TimedAudioTrack::queueTimedBuffer(const sp<IMemory>& buffer,
if (mActive && (mCblk->flags & CBLK_DISABLED_MSK)) {
android_atomic_and(~CBLK_DISABLED_ON, &mCblk->flags);
ALOGW("queueTimedBuffer() track %p disabled, restarting", this);
- mAudioTrack->start(0);
+ mAudioTrack->start();
}
return mAudioTrack->queueTimedBuffer(buffer, pts);
@@ -1301,7 +1316,7 @@ status_t AudioTrack::restoreTrack_l(audio_track_cblk_t*& cblk, bool fromStart)
}
}
if (mActive) {
- result = mAudioTrack->start(0); // callback thread hasn't changed
+ result = mAudioTrack->start();
ALOGW_IF(result != NO_ERROR, "restoreTrack_l() start() failed status %d", result);
}
if (fromStart && result == NO_ERROR) {
@@ -1369,12 +1384,24 @@ status_t AudioTrack::dump(int fd, const Vector<String16>& args) const
// =========================================================================
AudioTrack::AudioTrackThread::AudioTrackThread(AudioTrack& receiver, bool bCanCallJava)
- : Thread(bCanCallJava), mReceiver(receiver)
+ : Thread(bCanCallJava), mReceiver(receiver), mPaused(true)
+{
+}
+
+AudioTrack::AudioTrackThread::~AudioTrackThread()
{
}
bool AudioTrack::AudioTrackThread::threadLoop()
{
+ {
+ AutoMutex _l(mMyLock);
+ if (mPaused) {
+ mMyCond.wait(mMyLock);
+ // caller will check for exitPending()
+ return true;
+ }
+ }
return mReceiver.processAudioBuffer(this);
}
@@ -1387,6 +1414,28 @@ void AudioTrack::AudioTrackThread::onFirstRef()
{
}
+void AudioTrack::AudioTrackThread::requestExit()
+{
+ // must be in this order to avoid a race condition
+ Thread::requestExit();
+ mMyCond.signal();
+}
+
+void AudioTrack::AudioTrackThread::pause()
+{
+ AutoMutex _l(mMyLock);
+ mPaused = true;
+}
+
+void AudioTrack::AudioTrackThread::resume()
+{
+ AutoMutex _l(mMyLock);
+ if (mPaused) {
+ mPaused = false;
+ mMyCond.signal();
+ }
+}
+
// =========================================================================
diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp
index 2b5126f..e8dd438 100644
--- a/media/libmedia/IAudioFlinger.cpp
+++ b/media/libmedia/IAudioFlinger.cpp
@@ -91,6 +91,7 @@ public:
track_flags_t flags,
const sp<IMemory>& sharedBuffer,
audio_io_handle_t output,
+ pid_t tid,
int *sessionId,
status_t *status)
{
@@ -106,6 +107,7 @@ public:
data.writeInt32((int32_t) flags);
data.writeStrongBinder(sharedBuffer->asBinder());
data.writeInt32((int32_t) output);
+ data.writeInt32((int32_t) tid);
int lSessionId = 0;
if (sessionId != NULL) {
lSessionId = *sessionId;
@@ -701,11 +703,12 @@ status_t BnAudioFlinger::onTransact(
track_flags_t flags = (track_flags_t) data.readInt32();
sp<IMemory> buffer = interface_cast<IMemory>(data.readStrongBinder());
audio_io_handle_t output = (audio_io_handle_t) data.readInt32();
+ pid_t tid = (pid_t) data.readInt32();
int sessionId = data.readInt32();
status_t status;
sp<IAudioTrack> track = createTrack(pid,
(audio_stream_type_t) streamType, sampleRate, format,
- channelCount, bufferCount, flags, buffer, output, &sessionId, &status);
+ channelCount, bufferCount, flags, buffer, output, tid, &sessionId, &status);
reply->writeInt32(sessionId);
reply->writeInt32(status);
reply->writeStrongBinder(track->asBinder());
diff --git a/media/libmedia/IAudioRecord.cpp b/media/libmedia/IAudioRecord.cpp
index 58c6d38..57a80a9 100644
--- a/media/libmedia/IAudioRecord.cpp
+++ b/media/libmedia/IAudioRecord.cpp
@@ -42,11 +42,10 @@ public:
{
}
- virtual status_t start(pid_t tid, int event, int triggerSession)
+ virtual status_t start(int event, int triggerSession)
{
Parcel data, reply;
data.writeInterfaceToken(IAudioRecord::getInterfaceDescriptor());
- data.writeInt32(tid);
data.writeInt32(event);
data.writeInt32(triggerSession);
status_t status = remote()->transact(START, data, &reply);
@@ -93,10 +92,9 @@ status_t BnAudioRecord::onTransact(
} break;
case START: {
CHECK_INTERFACE(IAudioRecord, data, reply);
- pid_t tid = (pid_t) data.readInt32();
int event = data.readInt32();
int triggerSession = data.readInt32();
- reply->writeInt32(start(tid, event, triggerSession));
+ reply->writeInt32(start(event, triggerSession));
return NO_ERROR;
} break;
case STOP: {
diff --git a/media/libmedia/IAudioTrack.cpp b/media/libmedia/IAudioTrack.cpp
index 09f31a7..867d1a5 100644
--- a/media/libmedia/IAudioTrack.cpp
+++ b/media/libmedia/IAudioTrack.cpp
@@ -61,11 +61,10 @@ public:
return cblk;
}
- virtual status_t start(pid_t tid)
+ virtual status_t start()
{
Parcel data, reply;
data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
- data.writeInt32(tid);
status_t status = remote()->transact(START, data, &reply);
if (status == NO_ERROR) {
status = reply.readInt32();
@@ -180,7 +179,7 @@ status_t BnAudioTrack::onTransact(
} break;
case START: {
CHECK_INTERFACE(IAudioTrack, data, reply);
- reply->writeInt32(start(data.readInt32()));
+ reply->writeInt32(start());
return NO_ERROR;
} break;
case STOP: {