summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/media/AudioTrack.h14
-rw-r--r--include/media/IAudioFlinger.h1
-rw-r--r--include/media/IAudioRecord.h5
-rw-r--r--include/media/IAudioTrack.h5
-rw-r--r--include/private/media/AudioTrackShared.h1
-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
-rw-r--r--services/audioflinger/Android.mk2
-rw-r--r--services/audioflinger/AudioFlinger.cpp57
-rw-r--r--services/audioflinger/AudioFlinger.h20
13 files changed, 154 insertions, 88 deletions
diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h
index 4906bd3..98b1f3e 100644
--- a/include/media/AudioTrack.h
+++ b/include/media/AudioTrack.h
@@ -138,7 +138,7 @@ public:
* frameCount: Minimum size of track PCM buffer in frames. This defines the
* latency of the track. The actual size selected by the AudioTrack could be
* larger if the requested size is not compatible with current audio HAL
- * latency.
+ * latency. Zero means to use a default value.
* flags: See comments on audio_output_flags_t in <system/audio.h>.
* cbf: Callback function. If not null, this function is called periodically
* to request new PCM data.
@@ -460,12 +460,24 @@ protected:
{
public:
AudioTrackThread(AudioTrack& receiver, bool bCanCallJava = false);
+
+ // Do not call Thread::requestExitAndWait() without first calling requestExit().
+ // Thread::requestExitAndWait() is not virtual, and the implementation doesn't do enough.
+ virtual void requestExit();
+
+ void pause(); // suspend thread from execution at next loop boundary
+ void resume(); // allow thread to execute, if not requested to exit
+
private:
friend class AudioTrack;
virtual bool threadLoop();
virtual status_t readyToRun();
virtual void onFirstRef();
AudioTrack& mReceiver;
+ ~AudioTrackThread();
+ Mutex mMyLock; // Thread::mLock is private
+ Condition mMyCond; // Thread::mThreadExitedCondition is private
+ bool mPaused; // whether thread is currently paused
};
// body of AudioTrackThread::threadLoop()
diff --git a/include/media/IAudioFlinger.h b/include/media/IAudioFlinger.h
index 04ac3ee..86e228b 100644
--- a/include/media/IAudioFlinger.h
+++ b/include/media/IAudioFlinger.h
@@ -65,6 +65,7 @@ public:
track_flags_t flags,
const sp<IMemory>& sharedBuffer,
audio_io_handle_t output,
+ pid_t tid, // -1 means unused, otherwise must be valid non-0
int *sessionId,
status_t *status) = 0;
diff --git a/include/media/IAudioRecord.h b/include/media/IAudioRecord.h
index c486c6b..ebc03ea 100644
--- a/include/media/IAudioRecord.h
+++ b/include/media/IAudioRecord.h
@@ -35,10 +35,9 @@ public:
DECLARE_META_INTERFACE(AudioRecord);
/* After it's created the track is not active. Call start() to
- * make it active. If set, the callback will start being called.
- * tid identifies the client callback thread, or 0 if not needed.
+ * make it active.
*/
- virtual status_t start(pid_t tid, int event, int triggerSession) = 0;
+ virtual status_t start(int event, int triggerSession) = 0;
/* Stop a track. If set, the callback will cease being called and
* obtainBuffer will return an error. Buffers that are already released
diff --git a/include/media/IAudioTrack.h b/include/media/IAudioTrack.h
index 577b095..9e0e389 100644
--- a/include/media/IAudioTrack.h
+++ b/include/media/IAudioTrack.h
@@ -39,10 +39,9 @@ public:
virtual sp<IMemory> getCblk() const = 0;
/* After it's created the track is not active. Call start() to
- * make it active. If set, the callback will start being called.
- * tid identifies the client callback thread, or 0 if not needed.
+ * make it active.
*/
- virtual status_t start(pid_t tid) = 0;
+ virtual status_t start() = 0;
/* Stop a track. If set, the callback will cease being called and
* obtainBuffer will return an error. Buffers that are already released
diff --git a/include/private/media/AudioTrackShared.h b/include/private/media/AudioTrackShared.h
index af2db93..469f5ff 100644
--- a/include/private/media/AudioTrackShared.h
+++ b/include/private/media/AudioTrackShared.h
@@ -53,6 +53,7 @@ namespace android {
#define CBLK_RESTORED_MSK 0x0040
#define CBLK_RESTORED_ON 0x0040 // track has been restored after invalidation
#define CBLK_RESTORED_OFF 0x0040 // by AudioFlinger
+#define CBLK_FAST 0x0080 // AudioFlinger successfully created a fast track
// Important: do not add any virtual methods, including ~
struct audio_track_cblk_t
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: {
diff --git a/services/audioflinger/Android.mk b/services/audioflinger/Android.mk
index 4667649..7202b8b 100644
--- a/services/audioflinger/Android.mk
+++ b/services/audioflinger/Android.mk
@@ -68,4 +68,6 @@ LOCAL_CFLAGS += -DFAST_MIXER_STATISTICS
LOCAL_CFLAGS += -DSTATE_QUEUE_INSTANTIATIONS='"StateQueueInstantiations.cpp"'
+LOCAL_CFLAGS += -UHAVE_REQUEST_PRIORITY
+
include $(BUILD_SHARED_LIBRARY)
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index bce30d7..865051f 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -401,6 +401,7 @@ sp<IAudioTrack> AudioFlinger::createTrack(
IAudioFlinger::track_flags_t flags,
const sp<IMemory>& sharedBuffer,
audio_io_handle_t output,
+ pid_t tid,
int *sessionId,
status_t *status)
{
@@ -458,9 +459,8 @@ sp<IAudioTrack> AudioFlinger::createTrack(
}
ALOGV("createTrack() lSessionId: %d", lSessionId);
- bool isTimed = (flags & IAudioFlinger::TRACK_TIMED) != 0;
track = thread->createTrack_l(client, streamType, sampleRate, format,
- channelMask, frameCount, sharedBuffer, lSessionId, flags, &lStatus);
+ channelMask, frameCount, sharedBuffer, lSessionId, flags, tid, &lStatus);
// move effect chain to this output thread if an effect on same session was waiting
// for a track to be created
@@ -1569,6 +1569,7 @@ sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTrac
const sp<IMemory>& sharedBuffer,
int sessionId,
IAudioFlinger::track_flags_t flags,
+ pid_t tid,
status_t *status)
{
sp<Track> track;
@@ -1589,7 +1590,7 @@ sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTrac
) ||
// use case 2: callback handler and small power-of-2 frame count
(
- // unfortunately we can't verify that there's a callback until start()
+ (tid != -1) &&
// FIXME supported frame counts should not be hard-coded
(
(frameCount == 128) ||
@@ -1678,6 +1679,20 @@ sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTrac
chain->incTrackCnt();
}
}
+
+#ifdef HAVE_REQUEST_PRIORITY
+ if ((flags & IAudioFlinger::TRACK_FAST) && (tid != -1)) {
+ pid_t callingPid = IPCThreadState::self()->getCallingPid();
+ // we don't have CAP_SYS_NICE, nor do we want to have it as it's too powerful,
+ // so ask activity manager to do this on our behalf
+ int err = requestPriority(callingPid, tid, 1);
+ if (err != 0) {
+ ALOGW("Policy SCHED_FIFO priority %d is unavailable for pid %d tid %d; error %d",
+ 1, callingPid, tid, err);
+ }
+ }
+#endif
+
lStatus = NO_ERROR;
Exit:
@@ -3681,20 +3696,11 @@ bool AudioFlinger::PlaybackThread::Track::isReady() const {
return false;
}
-status_t AudioFlinger::PlaybackThread::Track::start(pid_t tid,
- AudioSystem::sync_event_t event,
+status_t AudioFlinger::PlaybackThread::Track::start(AudioSystem::sync_event_t event,
int triggerSession)
{
status_t status = NO_ERROR;
- ALOGV("start(%d), calling pid %d session %d tid %d",
- mName, IPCThreadState::self()->getCallingPid(), mSessionId, tid);
- // check for use case 2 with missing callback
- if (isFastTrack() && (mSharedBuffer == 0) && (tid == 0)) {
- ALOGW("AUDIO_OUTPUT_FLAG_FAST denied");
- mFlags &= ~IAudioFlinger::TRACK_FAST;
- // FIXME the track must be invalidated and moved to another thread or
- // attached directly to the normal mixer now
- }
+
sp<ThreadBase> thread = mThread.promote();
if (thread != 0) {
Mutex::Autolock _l(thread->mLock);
@@ -4467,14 +4473,13 @@ getNextBuffer_exit:
return NOT_ENOUGH_DATA;
}
-status_t AudioFlinger::RecordThread::RecordTrack::start(pid_t tid,
- AudioSystem::sync_event_t event,
+status_t AudioFlinger::RecordThread::RecordTrack::start(AudioSystem::sync_event_t event,
int triggerSession)
{
sp<ThreadBase> thread = mThread.promote();
if (thread != 0) {
RecordThread *recordThread = (RecordThread *)thread.get();
- return recordThread->start(this, tid, event, triggerSession);
+ return recordThread->start(this, event, triggerSession);
} else {
return BAD_VALUE;
}
@@ -4541,11 +4546,10 @@ AudioFlinger::PlaybackThread::OutputTrack::~OutputTrack()
clearBufferQueue();
}
-status_t AudioFlinger::PlaybackThread::OutputTrack::start(pid_t tid,
- AudioSystem::sync_event_t event,
+status_t AudioFlinger::PlaybackThread::OutputTrack::start(AudioSystem::sync_event_t event,
int triggerSession)
{
- status_t status = Track::start(tid, event, triggerSession);
+ status_t status = Track::start(event, triggerSession);
if (status != NO_ERROR) {
return status;
}
@@ -4575,7 +4579,7 @@ bool AudioFlinger::PlaybackThread::OutputTrack::write(int16_t* data, uint32_t fr
uint32_t waitTimeLeftMs = mSourceThread->waitTimeMs();
if (!mActive && frames != 0) {
- start(0);
+ start();
sp<ThreadBase> thread = mThread.promote();
if (thread != 0) {
MixerThread *mixerThread = (MixerThread *)thread.get();
@@ -4834,8 +4838,8 @@ sp<IMemory> AudioFlinger::TrackHandle::getCblk() const {
return mTrack->getCblk();
}
-status_t AudioFlinger::TrackHandle::start(pid_t tid) {
- return mTrack->start(tid);
+status_t AudioFlinger::TrackHandle::start() {
+ return mTrack->start();
}
void AudioFlinger::TrackHandle::stop() {
@@ -4988,9 +4992,9 @@ sp<IMemory> AudioFlinger::RecordHandle::getCblk() const {
return mRecordTrack->getCblk();
}
-status_t AudioFlinger::RecordHandle::start(pid_t tid, int event, int triggerSession) {
+status_t AudioFlinger::RecordHandle::start(int event, int triggerSession) {
ALOGV("RecordHandle::start()");
- return mRecordTrack->start(tid, (AudioSystem::sync_event_t)event, triggerSession);
+ return mRecordTrack->start((AudioSystem::sync_event_t)event, triggerSession);
}
void AudioFlinger::RecordHandle::stop() {
@@ -5291,9 +5295,10 @@ Exit:
}
status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrack,
- pid_t tid, AudioSystem::sync_event_t event,
+ AudioSystem::sync_event_t event,
int triggerSession)
{
+ // FIXME use tid here
ALOGV("RecordThread::start tid=%d, event %d, triggerSession %d", tid, event, triggerSession);
sp<ThreadBase> strongMe = this;
status_t status = NO_ERROR;
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index b1c5554..6b18945 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -91,6 +91,7 @@ public:
IAudioFlinger::track_flags_t flags,
const sp<IMemory>& sharedBuffer,
audio_io_handle_t output,
+ pid_t tid,
int *sessionId,
status_t *status);
@@ -376,8 +377,7 @@ private:
int sessionId);
virtual ~TrackBase();
- virtual status_t start(pid_t tid,
- AudioSystem::sync_event_t event = AudioSystem::SYNC_EVENT_NONE,
+ virtual status_t start(AudioSystem::sync_event_t event = AudioSystem::SYNC_EVENT_NONE,
int triggerSession = 0) = 0;
virtual void stop() = 0;
sp<IMemory> getCblk() const { return mCblkMemory; }
@@ -669,8 +669,7 @@ private:
virtual ~Track();
void dump(char* buffer, size_t size);
- virtual status_t start(pid_t tid,
- AudioSystem::sync_event_t event = AudioSystem::SYNC_EVENT_NONE,
+ virtual status_t start(AudioSystem::sync_event_t event = AudioSystem::SYNC_EVENT_NONE,
int triggerSession = 0);
virtual void stop();
void pause();
@@ -855,8 +854,7 @@ private:
int frameCount);
virtual ~OutputTrack();
- virtual status_t start(pid_t tid,
- AudioSystem::sync_event_t event = AudioSystem::SYNC_EVENT_NONE,
+ virtual status_t start(AudioSystem::sync_event_t event = AudioSystem::SYNC_EVENT_NONE,
int triggerSession = 0);
virtual void stop();
bool write(int16_t* data, uint32_t frames);
@@ -933,6 +931,7 @@ public:
const sp<IMemory>& sharedBuffer,
int sessionId,
IAudioFlinger::track_flags_t flags,
+ pid_t tid,
status_t *status);
AudioStreamOut* getOutput() const;
@@ -1188,7 +1187,7 @@ private:
TrackHandle(const sp<PlaybackThread::Track>& track);
virtual ~TrackHandle();
virtual sp<IMemory> getCblk() const;
- virtual status_t start(pid_t tid);
+ virtual status_t start();
virtual void stop();
virtual void flush();
virtual void mute(bool);
@@ -1227,8 +1226,7 @@ private:
int sessionId);
virtual ~RecordTrack();
- virtual status_t start(pid_t tid,
- AudioSystem::sync_event_t event = AudioSystem::SYNC_EVENT_NONE,
+ virtual status_t start(AudioSystem::sync_event_t event = AudioSystem::SYNC_EVENT_NONE,
int triggerSession = 0);
virtual void stop();
@@ -1276,7 +1274,7 @@ private:
int sessionId,
status_t *status);
- status_t start(RecordTrack* recordTrack, pid_t tid,
+ status_t start(RecordTrack* recordTrack,
AudioSystem::sync_event_t event,
int triggerSession);
void stop(RecordTrack* recordTrack);
@@ -1335,7 +1333,7 @@ private:
RecordHandle(const sp<RecordThread::RecordTrack>& recordTrack);
virtual ~RecordHandle();
virtual sp<IMemory> getCblk() const;
- virtual status_t start(pid_t tid, int event, int triggerSession);
+ virtual status_t start(int event, int triggerSession);
virtual void stop();
virtual status_t onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags);