Merge "Use screen dimensions as default video size"
diff --git a/camera/camera2/ICameraDeviceCallbacks.cpp b/camera/camera2/ICameraDeviceCallbacks.cpp
index 188bd8e..3cec1f4 100644
--- a/camera/camera2/ICameraDeviceCallbacks.cpp
+++ b/camera/camera2/ICameraDeviceCallbacks.cpp
@@ -57,11 +57,12 @@
         data.writeNoException();
     }
 
-    void onResultReceived(int32_t frameId, const CameraMetadata& result) {
+    void onResultReceived(int32_t requestId, const CameraMetadata& result) {
         ALOGV("onResultReceived");
         Parcel data, reply;
         data.writeInterfaceToken(ICameraDeviceCallbacks::getInterfaceDescriptor());
-        data.writeInt32(frameId);
+        data.writeInt32(requestId);
+        data.writeInt32(1); // to mark presence of metadata object
         result.writeToParcel(&data);
         remote()->transact(RESULT_RECEIVED, data, &reply, IBinder::FLAG_ONEWAY);
         data.writeNoException();
@@ -91,10 +92,14 @@
         case RESULT_RECEIVED: {
             ALOGV("RESULT_RECEIVED");
             CHECK_INTERFACE(ICameraDeviceCallbacks, data, reply);
-            int32_t frameId = data.readInt32();
+            int32_t requestId = data.readInt32();
             CameraMetadata result;
-            result.readFromParcel(const_cast<Parcel*>(&data));
-            onResultReceived(frameId, result);
+            if (data.readInt32() != 0) {
+                result.readFromParcel(const_cast<Parcel*>(&data));
+            } else {
+                ALOGW("No metadata object is present in result");
+            }
+            onResultReceived(requestId, result);
             data.readExceptionCode();
             return NO_ERROR;
             break;
diff --git a/include/media/stagefright/foundation/ALooperRoster.h b/include/media/stagefright/foundation/ALooperRoster.h
index 2e5fd73..940fc55 100644
--- a/include/media/stagefright/foundation/ALooperRoster.h
+++ b/include/media/stagefright/foundation/ALooperRoster.h
@@ -30,6 +30,7 @@
             const sp<ALooper> looper, const sp<AHandler> &handler);
 
     void unregisterHandler(ALooper::handler_id handlerID);
+    void unregisterStaleHandlers();
 
     status_t postMessage(const sp<AMessage> &msg, int64_t delayUs = 0);
     void deliverMessage(const sp<AMessage> &msg);
diff --git a/include/private/media/AudioTrackShared.h b/include/private/media/AudioTrackShared.h
index 6d778dd..1379379 100644
--- a/include/private/media/AudioTrackShared.h
+++ b/include/private/media/AudioTrackShared.h
@@ -415,6 +415,13 @@
     virtual void        framesReadyIsCalledByMultipleThreads() { }
 
     bool     setStreamEndDone();    // and return previous value
+
+    // Add to the tally of underrun frames, and inform client of underrun
+    virtual void        tallyUnderrunFrames(uint32_t frameCount);
+
+    // Return the total number of frames which AudioFlinger desired but were unavailable,
+    // and thus which resulted in an underrun.
+    virtual uint32_t    getUnderrunFrames() const { return mCblk->u.mStreaming.mUnderrunFrames; }
 };
 
 class StaticAudioTrackServerProxy : public AudioTrackServerProxy {
@@ -429,6 +436,8 @@
     virtual void        framesReadyIsCalledByMultipleThreads();
     virtual status_t    obtainBuffer(Buffer* buffer);
     virtual void        releaseBuffer(Buffer* buffer);
+    virtual void        tallyUnderrunFrames(uint32_t frameCount);
+    virtual uint32_t    getUnderrunFrames() const { return 0; }
 
 private:
     ssize_t             pollPosition(); // poll for state queue update, and return current position
diff --git a/media/libmedia/AudioTrackShared.cpp b/media/libmedia/AudioTrackShared.cpp
index 3b7616f..e7abb40 100644
--- a/media/libmedia/AudioTrackShared.cpp
+++ b/media/libmedia/AudioTrackShared.cpp
@@ -661,6 +661,14 @@
     return old;
 }
 
+void AudioTrackServerProxy::tallyUnderrunFrames(uint32_t frameCount)
+{
+    mCblk->u.mStreaming.mUnderrunFrames += frameCount;
+
+    // FIXME also wake futex so that underrun is noticed more quickly
+    (void) android_atomic_or(CBLK_UNDERRUN, &mCblk->mFlags);
+}
+
 // ---------------------------------------------------------------------------
 
 StaticAudioTrackServerProxy::StaticAudioTrackServerProxy(audio_track_cblk_t* cblk, void *buffers,
@@ -817,6 +825,17 @@
     buffer->mNonContig = 0;
 }
 
+void StaticAudioTrackServerProxy::tallyUnderrunFrames(uint32_t frameCount)
+{
+    // Unlike AudioTrackServerProxy::tallyUnderrunFrames() used for streaming tracks,
+    // we don't have a location to count underrun frames.  The underrun frame counter
+    // only exists in AudioTrackSharedStreaming.  Fortunately, underruns are not
+    // possible for static buffer tracks other than at end of buffer, so this is not a loss.
+
+    // FIXME also wake futex so that underrun is noticed more quickly
+    (void) android_atomic_or(CBLK_UNDERRUN, &mCblk->mFlags);
+}
+
 // ---------------------------------------------------------------------------
 
 }   // namespace android
diff --git a/media/libstagefright/SurfaceMediaSource.cpp b/media/libstagefright/SurfaceMediaSource.cpp
index befd4cc..b082c3a 100644
--- a/media/libstagefright/SurfaceMediaSource.cpp
+++ b/media/libstagefright/SurfaceMediaSource.cpp
@@ -65,10 +65,8 @@
     // reference once the ctor ends, as that would cause the refcount of 'this'
     // dropping to 0 at the end of the ctor.  Since all we need is a wp<...>
     // that's what we create.
-    wp<BufferQueue::ConsumerListener> listener;
-    sp<BufferQueue::ConsumerListener> proxy;
-    listener = static_cast<BufferQueue::ConsumerListener*>(this);
-    proxy = new BufferQueue::ProxyConsumerListener(listener);
+    wp<BufferQueue::ConsumerListener> listener = static_cast<BufferQueue::ConsumerListener*>(this);
+    sp<BufferQueue::ProxyConsumerListener> proxy = new BufferQueue::ProxyConsumerListener(listener);
 
     status_t err = mBufferQueue->consumerConnect(proxy, false);
     if (err != NO_ERROR) {
diff --git a/media/libstagefright/foundation/ALooper.cpp b/media/libstagefright/foundation/ALooper.cpp
index 22777a2..ebf9d8d 100644
--- a/media/libstagefright/foundation/ALooper.cpp
+++ b/media/libstagefright/foundation/ALooper.cpp
@@ -72,6 +72,10 @@
 
 ALooper::~ALooper() {
     stop();
+
+    // Since this looper is "dead" (or as good as dead by now),
+    // have ALooperRoster unregister any handlers still registered for it.
+    gLooperRoster.unregisterStaleHandlers();
 }
 
 void ALooper::setName(const char *name) {
diff --git a/media/libstagefright/foundation/ALooperRoster.cpp b/media/libstagefright/foundation/ALooperRoster.cpp
index ad10d2b..0c181ff 100644
--- a/media/libstagefright/foundation/ALooperRoster.cpp
+++ b/media/libstagefright/foundation/ALooperRoster.cpp
@@ -71,6 +71,20 @@
     mHandlers.removeItemsAt(index);
 }
 
+void ALooperRoster::unregisterStaleHandlers() {
+    Mutex::Autolock autoLock(mLock);
+
+    for (size_t i = mHandlers.size(); i-- > 0;) {
+        const HandlerInfo &info = mHandlers.valueAt(i);
+
+        sp<ALooper> looper = info.mLooper.promote();
+        if (looper == NULL) {
+            ALOGV("Unregistering stale handler %d", mHandlers.keyAt(i));
+            mHandlers.removeItemsAt(i);
+        }
+    }
+}
+
 status_t ALooperRoster::postMessage(
         const sp<AMessage> &msg, int64_t delayUs) {
     Mutex::Autolock autoLock(mLock);
diff --git a/media/libstagefright/omx/GraphicBufferSource.cpp b/media/libstagefright/omx/GraphicBufferSource.cpp
index d6fd95b..325ffcf 100644
--- a/media/libstagefright/omx/GraphicBufferSource.cpp
+++ b/media/libstagefright/omx/GraphicBufferSource.cpp
@@ -69,11 +69,8 @@
     // reference once the ctor ends, as that would cause the refcount of 'this'
     // dropping to 0 at the end of the ctor.  Since all we need is a wp<...>
     // that's what we create.
-    wp<BufferQueue::ConsumerListener> listener;
-    listener = static_cast<BufferQueue::ConsumerListener*>(this);
-
-    sp<BufferQueue::ConsumerListener> proxy;
-    proxy = new BufferQueue::ProxyConsumerListener(listener);
+    wp<BufferQueue::ConsumerListener> listener = static_cast<BufferQueue::ConsumerListener*>(this);
+    sp<BufferQueue::ProxyConsumerListener> proxy = new BufferQueue::ProxyConsumerListener(listener);
 
     mInitCheck = mBufferQueue->consumerConnect(proxy, false);
     if (mInitCheck != NO_ERROR) {
diff --git a/media/libstagefright/rtsp/ARTSPConnection.cpp b/media/libstagefright/rtsp/ARTSPConnection.cpp
index 906aef3..5116550 100644
--- a/media/libstagefright/rtsp/ARTSPConnection.cpp
+++ b/media/libstagefright/rtsp/ARTSPConnection.cpp
@@ -571,6 +571,9 @@
         if (sawCR && c == '\n') {
             line->erase(line->size() - 1, 1);
             return true;
+        } else if (c == '\n') {
+            // some reponse line ended with '\n', instead of '\r\n'.
+            return true;
         }
 
         line->append(&c, 1);
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index 628f5af..5600411c 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -140,7 +140,6 @@
                                     // but the slot is only used if track is active
     FastTrackUnderruns  mObservedUnderruns; // Most recently observed value of
                                     // mFastMixerDumpState.mTracks[mFastIndex].mUnderruns
-    uint32_t            mUnderrunCount; // Counter of total number of underruns, never reset
     volatile float      mCachedVolume;  // combined master volume and stream type volume;
                                         // 'volatile' means accessed without lock or
                                         // barrier, but is read/written atomically
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index d9c312e..f0c27c3 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -2739,8 +2739,10 @@
             track->mObservedUnderruns = underruns;
             // don't count underruns that occur while stopping or pausing
             // or stopped which can occur when flush() is called while active
-            if (!(track->isStopping() || track->isPausing() || track->isStopped())) {
-                track->mUnderrunCount += recentUnderruns;
+            if (!(track->isStopping() || track->isPausing() || track->isStopped()) &&
+                    recentUnderruns > 0) {
+                // FIXME fast mixer will pull & mix partial buffers, but we count as a full underrun
+                track->mAudioTrackServerProxy->tallyUnderrunFrames(recentUnderruns * mFrameCount);
             }
 
             // This is similar to the state machine for normal tracks,
@@ -3056,12 +3058,8 @@
                 mixerStatus = MIXER_TRACKS_READY;
             }
         } else {
-            // only implemented for normal tracks, not fast tracks
             if (framesReady < desiredFrames && !track->isStopped() && !track->isPaused()) {
-                // we missed desiredFrames whatever the actual number of frames missing was
-                cblk->u.mStreaming.mUnderrunFrames += desiredFrames;
-                // FIXME also wake futex so that underrun is noticed more quickly
-                (void) android_atomic_or(CBLK_UNDERRUN, &cblk->mFlags);
+                track->mAudioTrackServerProxy->tallyUnderrunFrames(desiredFrames);
             }
             // clear effect chain input buffer if an active track underruns to avoid sending
             // previous audio buffer again to effects
@@ -3086,7 +3084,6 @@
                     tracksToRemove->add(track);
                 }
             } else {
-                track->mUnderrunCount++;
                 // No buffers for this track. Give it a few chances to
                 // fill a buffer, then remove it from active list.
                 if (--(track->mRetryCount) <= 0) {
@@ -4911,9 +4908,9 @@
 
 void AudioFlinger::RecordThread::readInputParameters()
 {
-    delete mRsmpInBuffer;
+    delete[] mRsmpInBuffer;
     // mRsmpInBuffer is always assigned a new[] below
-    delete mRsmpOutBuffer;
+    delete[] mRsmpOutBuffer;
     mRsmpOutBuffer = NULL;
     delete mResampler;
     mResampler = NULL;
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 1f75468..e676365 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -316,7 +316,6 @@
     mPresentationCompleteFrames(0),
     mFlags(flags),
     mFastIndex(-1),
-    mUnderrunCount(0),
     mCachedVolume(1.0),
     mIsInvalid(false),
     mAudioTrackServerProxy(NULL),
@@ -389,7 +388,7 @@
 /*static*/ void AudioFlinger::PlaybackThread::Track::appendDumpHeader(String8& result)
 {
     result.append("   Name Client Type Fmt Chn mask Session fCount S F SRate  "
-                  "L dB  R dB    Server Main buf  Aux Buf Flags Underruns\n");
+                  "L dB  R dB    Server Main buf  Aux Buf Flags UndFrmCnt\n");
 }
 
 void AudioFlinger::PlaybackThread::Track::dump(char* buffer, size_t size)
@@ -470,7 +469,7 @@
             (int)mMainBuffer,
             (int)mAuxBuffer,
             mCblk->mFlags,
-            mUnderrunCount,
+            mAudioTrackServerProxy->getUnderrunFrames(),
             nowInUnderrun);
 }
 
@@ -489,10 +488,7 @@
     buffer->frameCount = buf.mFrameCount;
     buffer->raw = buf.mRaw;
     if (buf.mFrameCount == 0) {
-        // only implemented so far for normal tracks, not fast tracks
-        mCblk->u.mStreaming.mUnderrunFrames += desiredFrames;
-        // FIXME also wake futex so that underrun is noticed more quickly
-        (void) android_atomic_or(CBLK_UNDERRUN, &mCblk->mFlags);
+        mAudioTrackServerProxy->tallyUnderrunFrames(desiredFrames);
     }
     return status;
 }
diff --git a/services/camera/libcameraservice/common/FrameProcessorBase.cpp b/services/camera/libcameraservice/common/FrameProcessorBase.cpp
index 10bc6ea..e7b440a 100644
--- a/services/camera/libcameraservice/common/FrameProcessorBase.cpp
+++ b/services/camera/libcameraservice/common/FrameProcessorBase.cpp
@@ -143,7 +143,7 @@
                 __FUNCTION__, device->getId());
         return BAD_VALUE;
     }
-    int32_t frameId = entry.data.i32[0];
+    int32_t requestId = entry.data.i32[0];
 
     List<sp<FilteredListener> > listeners;
     {
@@ -151,8 +151,8 @@
 
         List<RangeListener>::iterator item = mRangeListeners.begin();
         while (item != mRangeListeners.end()) {
-            if (frameId >= item->minId &&
-                    frameId < item->maxId) {
+            if (requestId >= item->minId &&
+                    requestId < item->maxId) {
                 sp<FilteredListener> listener = item->listener.promote();
                 if (listener == 0) {
                     item = mRangeListeners.erase(item);
@@ -167,7 +167,7 @@
     ALOGV("Got %d range listeners out of %d", listeners.size(), mRangeListeners.size());
     List<sp<FilteredListener> >::iterator item = listeners.begin();
     for (; item != listeners.end(); item++) {
-        (*item)->onFrameAvailable(frameId, frame);
+        (*item)->onFrameAvailable(requestId, frame);
     }
     return OK;
 }