Merge "Remove timing jitter during startup of audio" into jb-mr2-dev
diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h
index db5a7ab..64f82bb 100644
--- a/include/media/AudioTrack.h
+++ b/include/media/AudioTrack.h
@@ -599,6 +599,7 @@
     int                     mPreviousPriority;          // before start()
     SchedPolicy             mPreviousSchedulingGroup;
     AudioTrackClientProxy*  mProxy;
+    bool                    mAwaitBoost;    // thread should wait for priority boost before running
 };
 
 class TimedAudioTrack : public AudioTrack
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 1bd839f..7eeb4f8 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -893,9 +893,11 @@
         ALOGW("Requested frameCount %u but received frameCount %u", frameCount, temp);
     }
     frameCount = temp;
+    mAwaitBoost = false;
     if (flags & AUDIO_OUTPUT_FLAG_FAST) {
         if (trackFlags & IAudioFlinger::TRACK_FAST) {
             ALOGV("AUDIO_OUTPUT_FLAG_FAST successful; frameCount %u", frameCount);
+            mAwaitBoost = true;
         } else {
             ALOGV("AUDIO_OUTPUT_FLAG_FAST denied by server; frameCount %u", frameCount);
             // once denied, do not request again if IAudioTrack is re-created
@@ -1219,6 +1221,25 @@
     size_t writtenSize;
 
     mLock.lock();
+    if (mAwaitBoost) {
+        mAwaitBoost = false;
+        mLock.unlock();
+        static const int32_t kMaxTries = 5;
+        int32_t tryCounter = kMaxTries;
+        uint32_t pollUs = 10000;
+        do {
+            int policy = sched_getscheduler(0);
+            if (policy == SCHED_FIFO || policy == SCHED_RR) {
+                break;
+            }
+            usleep(pollUs);
+            pollUs <<= 1;
+        } while (tryCounter-- > 0);
+        if (tryCounter < 0) {
+            ALOGE("did not receive expected priority boost on time");
+        }
+        return true;
+    }
     // acquire a strong reference on the IMemory and IAudioTrack so that they cannot be destroyed
     // while we are accessing the cblk
     sp<IAudioTrack> audioTrack = mAudioTrack;
diff --git a/services/audioflinger/FastMixer.cpp b/services/audioflinger/FastMixer.cpp
index 24a6dfe..21df1d7 100644
--- a/services/audioflinger/FastMixer.cpp
+++ b/services/audioflinger/FastMixer.cpp
@@ -170,6 +170,10 @@
                 if (old <= 0) {
                     __futex_syscall4(coldFutexAddr, FUTEX_WAIT_PRIVATE, old - 1, NULL);
                 }
+                int policy = sched_getscheduler(0);
+                if (!(policy == SCHED_FIFO || policy == SCHED_RR)) {
+                    ALOGE("did not receive expected priority boost");
+                }
                 // This may be overly conservative; there could be times that the normal mixer
                 // requests such a brief cold idle that it doesn't require resetting this flag.
                 isWarm = false;
diff --git a/services/audioflinger/ISchedulingPolicyService.cpp b/services/audioflinger/ISchedulingPolicyService.cpp
index 218aa6b..0079968 100644
--- a/services/audioflinger/ISchedulingPolicyService.cpp
+++ b/services/audioflinger/ISchedulingPolicyService.cpp
@@ -37,14 +37,15 @@
     {
     }
 
-    virtual int requestPriority(int32_t pid, int32_t tid, int32_t prio)
+    virtual int requestPriority(int32_t pid, int32_t tid, int32_t prio, bool asynchronous)
     {
         Parcel data, reply;
         data.writeInterfaceToken(ISchedulingPolicyService::getInterfaceDescriptor());
         data.writeInt32(pid);
         data.writeInt32(tid);
         data.writeInt32(prio);
-        remote()->transact(REQUEST_PRIORITY_TRANSACTION, data, &reply, IBinder::FLAG_ONEWAY);
+        uint32_t flags = asynchronous ? IBinder::FLAG_ONEWAY : 0;
+        remote()->transact(REQUEST_PRIORITY_TRANSACTION, data, &reply, flags);
         // fail on exception
         if (reply.readExceptionCode() != 0) return -1;
         return reply.readInt32();
diff --git a/services/audioflinger/ISchedulingPolicyService.h b/services/audioflinger/ISchedulingPolicyService.h
index a38e67e..b94b191 100644
--- a/services/audioflinger/ISchedulingPolicyService.h
+++ b/services/audioflinger/ISchedulingPolicyService.h
@@ -27,7 +27,7 @@
     DECLARE_META_INTERFACE(SchedulingPolicyService);
 
     virtual int         requestPriority(/*pid_t*/int32_t pid, /*pid_t*/int32_t tid,
-                                                int32_t prio) = 0;
+                                                int32_t prio, bool asynchronous) = 0;
 
 };
 
diff --git a/services/audioflinger/SchedulingPolicyService.cpp b/services/audioflinger/SchedulingPolicyService.cpp
index 59cc99a..36e62e9 100644
--- a/services/audioflinger/SchedulingPolicyService.cpp
+++ b/services/audioflinger/SchedulingPolicyService.cpp
@@ -25,7 +25,7 @@
 static const String16 _scheduling_policy("scheduling_policy");
 static Mutex sMutex;
 
-int requestPriority(pid_t pid, pid_t tid, int32_t prio)
+int requestPriority(pid_t pid, pid_t tid, int32_t prio, bool asynchronous)
 {
     // FIXME merge duplicated code related to service lookup, caching, and error recovery
     sp<ISchedulingPolicyService> sps;
@@ -46,7 +46,7 @@
         }
         sleep(1);
     }
-    return sps->requestPriority(pid, tid, prio);
+    return sps->requestPriority(pid, tid, prio, asynchronous);
 }
 
 }   // namespace android
diff --git a/services/audioflinger/SchedulingPolicyService.h b/services/audioflinger/SchedulingPolicyService.h
index 7ac8454..a9870d4 100644
--- a/services/audioflinger/SchedulingPolicyService.h
+++ b/services/audioflinger/SchedulingPolicyService.h
@@ -21,7 +21,10 @@
 
 // Request elevated priority for thread tid, whose thread group leader must be pid.
 // The priority parameter is currently restricted to either 1 or 2.
-int requestPriority(pid_t pid, pid_t tid, int32_t prio);
+// The asynchronous parameter should be 'true' to return immediately,
+// after the request is enqueued but not necessarily executed.
+// The default value 'false' means to return after request has been enqueued and executed.
+int requestPriority(pid_t pid, pid_t tid, int32_t prio, bool asynchronous = false);
 
 }   // namespace android
 
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 47ca100..539bb4f 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -373,7 +373,9 @@
         switch(event->type()) {
             case CFG_EVENT_PRIO: {
                 PrioConfigEvent *prioEvent = static_cast<PrioConfigEvent *>(event);
-                int err = requestPriority(prioEvent->pid(), prioEvent->tid(), prioEvent->prio());
+                // FIXME Need to understand why this has be done asynchronously
+                int err = requestPriority(prioEvent->pid(), prioEvent->tid(), prioEvent->prio(),
+                        true /*asynchronous*/);
                 if (err != 0) {
                     ALOGW("Policy SCHED_FIFO priority %d is unavailable for pid %d tid %d; "
                           "error %d",