Configure policy of mediaserver threads

Change-Id: Ifd825590ba36996064a458f64453a94b84722cb0
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 @@
      * 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 @@
     {
     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 @@
                                 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 @@
     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 @@
     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 @@
 #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 @@
         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 @@
                             "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 @@
                 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 @@
 
     *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 @@
         // 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 @@
     // 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 @@
     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 @@
                                   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 @@
     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 @@
         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 @@
             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 @@
             flush_l();
         }
         if (t != 0) {
-            t->requestExit();
+            t->pause();
         } else {
             setpriority(PRIO_PROCESS, 0, mPreviousPriority);
             androidSetThreadSchedulingGroup(0, mPreviousSchedulingGroup);
@@ -771,7 +765,7 @@
             (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 @@
         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 @@
             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 @@
     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 @@
                                                       trackFlags,
                                                       sharedBuffer,
                                                       output,
+                                                      tid,
                                                       &mSessionId,
                                                       &status);
 
@@ -849,7 +856,15 @@
     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 @@
                                 "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 @@
     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 @@
     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 @@
                 }
             }
             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 @@
 // =========================================================================
 
 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::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 @@
                                 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 @@
         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 @@
             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 @@
     {
     }
 
-    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 @@
         } 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 @@
         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 @@
         } 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 += -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 @@
         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 @@
         }
         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 @@
         const sp<IMemory>& sharedBuffer,
         int sessionId,
         IAudioFlinger::track_flags_t flags,
+        pid_t tid,
         status_t *status)
 {
     sp<Track> track;
@@ -1589,7 +1590,7 @@
               ) ||
               // 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 @@
             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 @@
     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 @@
     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 @@
     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 @@
     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 @@
     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 @@
     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 @@
 }
 
 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 @@
                                 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 @@
                                         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 @@
             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 @@
                                         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 @@
                                     const sp<IMemory>& sharedBuffer,
                                     int sessionId,
                                     IAudioFlinger::track_flags_t flags,
+                                    pid_t tid,
                                     status_t *status);
 
                     AudioStreamOut* getOutput() const;
@@ -1188,7 +1187,7 @@
                             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 @@
                                         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 @@
                         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 @@
         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);