Merge "Support IDR requests in wifi display, MediaCodec and ACodec." into jb-mr1-dev
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index a44fb3e..de116a9 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -1063,11 +1063,11 @@
         // the config change is always sent from playback or record threads to avoid deadlock
         // with AudioSystem::gLock
         for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
-            mPlaybackThreads.valueAt(i)->sendConfigEvent(AudioSystem::OUTPUT_OPENED);
+            mPlaybackThreads.valueAt(i)->sendIoConfigEvent(AudioSystem::OUTPUT_OPENED);
         }
 
         for (size_t i = 0; i < mRecordThreads.size(); i++) {
-            mRecordThreads.valueAt(i)->sendConfigEvent(AudioSystem::INPUT_OPENED);
+            mRecordThreads.valueAt(i)->sendIoConfigEvent(AudioSystem::INPUT_OPENED);
         }
     }
 }
@@ -1202,20 +1202,28 @@
     return status;
 }
 
-void AudioFlinger::ThreadBase::sendConfigEvent(int event, int param)
+void AudioFlinger::ThreadBase::sendIoConfigEvent(int event, int param)
 {
     Mutex::Autolock _l(mLock);
-    sendConfigEvent_l(event, param);
+    sendIoConfigEvent_l(event, param);
 }
 
-// sendConfigEvent_l() must be called with ThreadBase::mLock held
-void AudioFlinger::ThreadBase::sendConfigEvent_l(int event, int param)
+// sendIoConfigEvent_l() must be called with ThreadBase::mLock held
+void AudioFlinger::ThreadBase::sendIoConfigEvent_l(int event, int param)
 {
-    ConfigEvent configEvent;
-    configEvent.mEvent = event;
-    configEvent.mParam = param;
-    mConfigEvents.add(configEvent);
-    ALOGV("sendConfigEvent() num events %d event %d, param %d", mConfigEvents.size(), event, param);
+    IoConfigEvent *ioEvent = new IoConfigEvent(event, param);
+    mConfigEvents.add(static_cast<ConfigEvent *>(ioEvent));
+    ALOGV("sendIoConfigEvent() num events %d event %d, param %d", mConfigEvents.size(), event, param);
+    mWaitWorkCV.signal();
+}
+
+// sendPrioConfigEvent_l() must be called with ThreadBase::mLock held
+void AudioFlinger::ThreadBase::sendPrioConfigEvent_l(pid_t pid, pid_t tid, int32_t prio)
+{
+    PrioConfigEvent *prioEvent = new PrioConfigEvent(pid, tid, prio);
+    mConfigEvents.add(static_cast<ConfigEvent *>(prioEvent));
+    ALOGV("sendPrioConfigEvent_l() num events %d pid %d, tid %d prio %d",
+          mConfigEvents.size(), pid, tid, prio);
     mWaitWorkCV.signal();
 }
 
@@ -1224,14 +1232,31 @@
     mLock.lock();
     while (!mConfigEvents.isEmpty()) {
         ALOGV("processConfigEvents() remaining events %d", mConfigEvents.size());
-        ConfigEvent configEvent = mConfigEvents[0];
+        ConfigEvent *event = mConfigEvents[0];
         mConfigEvents.removeAt(0);
         // release mLock before locking AudioFlinger mLock: lock order is always
         // AudioFlinger then ThreadBase to avoid cross deadlock
         mLock.unlock();
-        mAudioFlinger->mLock.lock();
-        audioConfigChanged_l(configEvent.mEvent, configEvent.mParam);
-        mAudioFlinger->mLock.unlock();
+        switch(event->type()) {
+            case CFG_EVENT_PRIO: {
+                PrioConfigEvent *prioEvent = static_cast<PrioConfigEvent *>(event);
+                int err = requestPriority(prioEvent->pid(), prioEvent->tid(), prioEvent->prio());
+                if (err != 0) {
+                    ALOGW("Policy SCHED_FIFO priority %d is unavailable for pid %d tid %d; error %d",
+                          prioEvent->prio(), prioEvent->pid(), prioEvent->tid(), err);
+                }
+            } break;
+            case CFG_EVENT_IO: {
+                IoConfigEvent *ioEvent = static_cast<IoConfigEvent *>(event);
+                mAudioFlinger->mLock.lock();
+                audioConfigChanged_l(ioEvent->event(), ioEvent->param());
+                mAudioFlinger->mLock.unlock();
+            } break;
+            default:
+                ALOGE("processConfigEvents() unknown event type %d", event->type());
+                break;
+        }
+        delete event;
         mLock.lock();
     }
     mLock.unlock();
@@ -1281,10 +1306,8 @@
 
     snprintf(buffer, SIZE, "\n\nPending config events: \n");
     result.append(buffer);
-    snprintf(buffer, SIZE, " Index event param\n");
-    result.append(buffer);
     for (size_t i = 0; i < mConfigEvents.size(); i++) {
-        snprintf(buffer, SIZE, " %02d    %02d    %d\n", i, mConfigEvents[i].mEvent, mConfigEvents[i].mParam);
+        mConfigEvents[i]->dump(buffer, SIZE);
         result.append(buffer);
     }
     result.append("\n");
@@ -1819,16 +1842,12 @@
             chain->setStrategy(AudioSystem::getStrategyForStream(track->streamType()));
             chain->incTrackCnt();
         }
-    }
 
-    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, kPriorityAudioApp);
-        if (err != 0) {
-            ALOGW("Policy SCHED_FIFO priority %d is unavailable for pid %d tid %d; error %d",
-                    kPriorityAudioApp, callingPid, tid, err);
+        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
+            sendPrioConfigEvent_l(callingPid, tid, kPriorityAudioApp);
         }
     }
 
@@ -3506,7 +3525,7 @@
                         mTracks[i]->mCblk->sampleRate = 2 * sampleRate();
                     }
                 }
-                sendConfigEvent_l(AudioSystem::OUTPUT_CONFIG_CHANGED);
+                sendIoConfigEvent_l(AudioSystem::OUTPUT_CONFIG_CHANGED);
             }
         }
 
@@ -3872,7 +3891,7 @@
             }
             if (status == NO_ERROR && reconfig) {
                 readOutputParameters();
-                sendConfigEvent_l(AudioSystem::OUTPUT_CONFIG_CHANGED);
+                sendIoConfigEvent_l(AudioSystem::OUTPUT_CONFIG_CHANGED);
             }
         }
 
@@ -5984,7 +6003,7 @@
     inputStandBy();
     acquireWakeLock();
 
-    // used to verify we've read at least one before evaluating how many bytes were read
+    // used to verify we've read at least once before evaluating how many bytes were read
     bool readOnce = false;
 
     // start recording
@@ -6499,9 +6518,9 @@
 
     if (framesReady == 0) {
         mBytesRead = mInput->stream->read(mInput->stream, mRsmpInBuffer, mInputBytes);
-        if (mBytesRead < 0) {
-            ALOGE("RecordThread::getNextBuffer() Error reading audio input");
-            if (mActiveTrack->mState == TrackBase::ACTIVE) {
+        if (mBytesRead <= 0) {
+            if ((mBytesRead < 0) && (mActiveTrack->mState == TrackBase::ACTIVE)) {
+                ALOGE("RecordThread::getNextBuffer() Error reading audio input");
                 // Force input into standby so that it tries to
                 // recover at next read attempt
                 inputStandBy();
@@ -6625,7 +6644,7 @@
                 }
                 if (status == NO_ERROR) {
                     readInputParameters();
-                    sendConfigEvent_l(AudioSystem::INPUT_CONFIG_CHANGED);
+                    sendIoConfigEvent_l(AudioSystem::INPUT_CONFIG_CHANGED);
                 }
             }
         }
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index c956861..8a020fa 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -471,14 +471,63 @@
             Vector < sp<SyncEvent> >mSyncEvents;
         };
 
+        enum {
+            CFG_EVENT_IO,
+            CFG_EVENT_PRIO
+        };
+
         class ConfigEvent {
         public:
-            ConfigEvent() : mEvent(0), mParam(0) {}
+            ConfigEvent(int type) : mType(type) {}
+            virtual ~ConfigEvent() {}
 
-            int mEvent;
-            int mParam;
+                     int type() const { return mType; }
+
+            virtual  void dump(char *buffer, size_t size) = 0;
+
+        private:
+            const int mType;
         };
 
+        class IoConfigEvent : public ConfigEvent {
+        public:
+            IoConfigEvent(int event, int param) :
+                ConfigEvent(CFG_EVENT_IO), mEvent(event), mParam(event) {}
+            virtual ~IoConfigEvent() {}
+
+                    int event() const { return mEvent; }
+                    int param() const { return mParam; }
+
+            virtual  void dump(char *buffer, size_t size) {
+                snprintf(buffer, size, "IO event: event %d, param %d\n", mEvent, mParam);
+            }
+
+        private:
+            const int mEvent;
+            const int mParam;
+        };
+
+        class PrioConfigEvent : public ConfigEvent {
+        public:
+            PrioConfigEvent(pid_t pid, pid_t tid, int32_t prio) :
+                ConfigEvent(CFG_EVENT_PRIO), mPid(pid), mTid(tid), mPrio(prio) {}
+            virtual ~PrioConfigEvent() {}
+
+                    pid_t pid() const { return mPid; }
+                    pid_t tid() const { return mTid; }
+                    int32_t prio() const { return mPrio; }
+
+            virtual  void dump(char *buffer, size_t size) {
+                snprintf(buffer, size, "Prio event: pid %d, tid %d, prio %d\n", mPid, mTid, mPrio);
+            }
+
+        private:
+            const pid_t mPid;
+            const pid_t mTid;
+            const int32_t mPrio;
+        };
+
+
         class PMDeathRecipient : public IBinder::DeathRecipient {
         public:
                         PMDeathRecipient(const wp<ThreadBase>& thread) : mThread(thread) {}
@@ -516,8 +565,9 @@
         virtual     status_t    setParameters(const String8& keyValuePairs);
         virtual     String8     getParameters(const String8& keys) = 0;
         virtual     void        audioConfigChanged_l(int event, int param = 0) = 0;
-                    void        sendConfigEvent(int event, int param = 0);
-                    void        sendConfigEvent_l(int event, int param = 0);
+                    void        sendIoConfigEvent(int event, int param = 0);
+                    void        sendIoConfigEvent_l(int event, int param = 0);
+                    void        sendPrioConfigEvent_l(pid_t pid, pid_t tid, int32_t prio);
                     void        processConfigEvents();
 
                     // see note at declaration of mStandby, mOutDevice and mInDevice
@@ -666,7 +716,7 @@
                     Vector<String8>         mNewParameters;
                     status_t                mParamStatus;
 
-                    Vector<ConfigEvent>     mConfigEvents;
+                    Vector<ConfigEvent *>     mConfigEvents;
 
                     // These fields are written and read by thread itself without lock or barrier,
                     // and read by other threads without lock or barrier via standby() , outDevice()