AudioFlinger track flags and server's fast policy
Change-Id: I72358c8e6829d173b3e60ced8a8babc089869fac
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index fb5a7e1..ad386f6 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -504,7 +504,7 @@
bool isTimed = (flags & IAudioFlinger::TRACK_TIMED) != 0;
track = thread->createTrack_l(client, streamType, sampleRate, format,
- channelMask, frameCount, sharedBuffer, lSessionId, isTimed, &lStatus);
+ channelMask, frameCount, sharedBuffer, lSessionId, flags, &lStatus);
// move effect chain to this output thread if an effect on same session was waiting
// for a track to be created
@@ -1608,12 +1608,50 @@
int frameCount,
const sp<IMemory>& sharedBuffer,
int sessionId,
- bool isTimed,
+ IAudioFlinger::track_flags_t flags,
status_t *status)
{
sp<Track> track;
status_t lStatus;
+ bool isTimed = (flags & IAudioFlinger::TRACK_TIMED) != 0;
+
+ // client expresses a preference for FAST, but we get the final say
+ if ((flags & IAudioFlinger::TRACK_FAST) &&
+ !(
+ // not timed
+ (!isTimed) &&
+ // either of these use cases:
+ (
+ // use case 1: shared buffer with any frame count
+ (
+ (sharedBuffer != 0)
+ ) ||
+ // use case 2: callback handler and small power-of-2 frame count
+ (
+ // unfortunately we can't verify that there's a callback until start()
+ // FIXME supported frame counts should not be hard-coded
+ (
+ (frameCount == 128) ||
+ (frameCount == 256) ||
+ (frameCount == 512)
+ )
+ )
+ ) &&
+ // PCM data
+ audio_is_linear_pcm(format) &&
+ // mono or stereo
+ ( (channelMask == AUDIO_CHANNEL_OUT_MONO) ||
+ (channelMask == AUDIO_CHANNEL_OUT_STEREO) ) &&
+ // hardware sample rate
+ (sampleRate == mSampleRate)
+ // FIXME test that MixerThread for this fast track has a capable output HAL
+ // FIXME add a permission test also?
+ ) ) {
+ ALOGW("AUDIO_POLICY_OUTPUT_FLAG_FAST denied");
+ flags &= ~IAudioFlinger::TRACK_FAST;
+ }
+
if (mType == DIRECT) {
if ((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM) {
if (sampleRate != mSampleRate || format != mFormat || channelMask != mChannelMask) {
@@ -1661,7 +1699,7 @@
if (!isTimed) {
track = new Track(this, client, streamType, sampleRate, format,
- channelMask, frameCount, sharedBuffer, sessionId);
+ channelMask, frameCount, sharedBuffer, sessionId, flags);
} else {
track = TimedTrack::create(this, client, streamType, sampleRate, format,
channelMask, frameCount, sharedBuffer, sessionId);
@@ -3550,7 +3588,8 @@
uint32_t channelMask,
int frameCount,
const sp<IMemory>& sharedBuffer,
- int sessionId)
+ int sessionId,
+ IAudioFlinger::track_flags_t flags)
: TrackBase(thread, client, sampleRate, format, channelMask, frameCount, sharedBuffer, sessionId),
mMute(false),
// mFillingUpStatus ?
@@ -3561,7 +3600,8 @@
mMainBuffer(thread->mixBuffer()),
mAuxBuffer(NULL),
mAuxEffectId(0), mHasVolumeController(false),
- mPresentationCompleteFrames(0)
+ mPresentationCompleteFrames(0),
+ mFlags(flags)
{
if (mCblk != NULL) {
// NOTE: audio_track_cblk_t::frameSize for 8 bit PCM data is based on a sample size of
@@ -3707,6 +3747,13 @@
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_POLICY_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);
@@ -3922,7 +3969,7 @@
const sp<IMemory>& sharedBuffer,
int sessionId)
: Track(thread, client, streamType, sampleRate, format, channelMask,
- frameCount, sharedBuffer, sessionId),
+ frameCount, sharedBuffer, sessionId, IAudioFlinger::TRACK_TIMED),
mTimedSilenceBuffer(NULL),
mTimedSilenceBufferSize(0),
mTimedAudioOutputOnTime(false),
@@ -4400,7 +4447,8 @@
audio_format_t format,
uint32_t channelMask,
int frameCount)
- : Track(playbackThread, NULL, AUDIO_STREAM_CNT, sampleRate, format, channelMask, frameCount, NULL, 0),
+ : Track(playbackThread, NULL, AUDIO_STREAM_CNT, sampleRate, format, channelMask, frameCount,
+ NULL, 0, IAudioFlinger::TRACK_DEFAULT),
mActive(false), mSourceThread(sourceThread)
{
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 3051514..de59f6d 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -662,7 +662,8 @@
uint32_t channelMask,
int frameCount,
const sp<IMemory>& sharedBuffer,
- int sessionId);
+ int sessionId,
+ IAudioFlinger::track_flags_t flags);
virtual ~Track();
void dump(char* buffer, size_t size);
@@ -689,6 +690,9 @@
int16_t *mainBuffer() const { return mMainBuffer; }
int auxEffectId() const { return mAuxEffectId; }
+ bool isFastTrack() const
+ { return (mFlags & IAudioFlinger::TRACK_FAST) != 0; }
+
protected:
// for numerous
friend class PlaybackThread;
@@ -742,6 +746,8 @@
bool mHasVolumeController;
size_t mPresentationCompleteFrames; // number of frames written to the audio HAL
// when this track will be fully rendered
+ private:
+ IAudioFlinger::track_flags_t mFlags;
}; // end of Track
class TimedTrack : public Track {
@@ -913,7 +919,7 @@
int frameCount,
const sp<IMemory>& sharedBuffer,
int sessionId,
- bool isTimed,
+ IAudioFlinger::track_flags_t flags,
status_t *status);
AudioStreamOut* getOutput() const;