Merge changes Iafb91645,I56a0ec7b into nyc-dr1-dev
am: bcc30e06dd

Change-Id: I65122a9ae9abaed35324cc2c6d6db5ee49e2c68e
diff --git a/camera/camera2/CaptureRequest.cpp b/camera/camera2/CaptureRequest.cpp
index fb43708..0d689a6 100644
--- a/camera/camera2/CaptureRequest.cpp
+++ b/camera/camera2/CaptureRequest.cpp
@@ -37,7 +37,7 @@
     mMetadata.clear();
     mSurfaceList.clear();
 
-    status_t err;
+    status_t err = OK;
 
     if ((err = mMetadata.readFromParcel(parcel)) != OK) {
         ALOGE("%s: Failed to read metadata from parcel", __FUNCTION__);
@@ -65,19 +65,16 @@
         }
 
         // Surface.writeToParcel
-        const char16_t* name = parcel->readString16Inplace(&len);
-        ALOGV("%s: Read surface name = %s", __FUNCTION__,
-            name != NULL ? String8(name).string() : "<null>");
-        sp<IBinder> binder(parcel->readStrongBinder());
-        ALOGV("%s: Read surface binder = %p",
-              __FUNCTION__, binder.get());
+        view::Surface surfaceShim;
+        if ((err = surfaceShim.readFromParcel(parcel)) != OK) {
+            ALOGE("%s: Failed to read output target Surface %d from parcel: %s (%d)",
+                    __FUNCTION__, i, strerror(-err), err);
+            return err;
+        }
 
         sp<Surface> surface;
-
-        if (binder != NULL) {
-            sp<IGraphicBufferProducer> gbp =
-                    interface_cast<IGraphicBufferProducer>(binder);
-            surface = new Surface(gbp);
+        if (surfaceShim.graphicBufferProducer != NULL) {
+            surface = new Surface(surfaceShim.graphicBufferProducer);
         }
 
         mSurfaceList.push_back(surface);
@@ -99,7 +96,7 @@
         return BAD_VALUE;
     }
 
-    status_t err;
+    status_t err = OK;
 
     if ((err = mMetadata.writeToParcel(parcel)) != OK) {
         return err;
@@ -111,20 +108,18 @@
     parcel->writeInt32(size);
 
     for (int32_t i = 0; i < size; ++i) {
-        sp<Surface> surface = mSurfaceList[i];
-
-        sp<IBinder> binder;
-        if (surface != 0) {
-            binder = IInterface::asBinder(surface->getIGraphicBufferProducer());
-        }
-
         // not sure if readParcelableArray does this, hard to tell from source
         parcel->writeString16(String16("android.view.Surface"));
 
         // Surface.writeToParcel
-        parcel->writeString16(String16("unknown_name"));
-        // Surface.nativeWriteToParcel
-        parcel->writeStrongBinder(binder);
+        view::Surface surfaceShim;
+        surfaceShim.name = String16("unknown_name");
+        surfaceShim.graphicBufferProducer = mSurfaceList[i]->getIGraphicBufferProducer();
+        if ((err = surfaceShim.writeToParcel(parcel)) != OK) {
+            ALOGE("%s: Failed to write output target Surface %d to parcel: %s (%d)",
+                    __FUNCTION__, i, strerror(-err), err);
+            return err;
+        }
     }
 
     parcel->writeInt32(mIsReprocess ? 1 : 0);
diff --git a/include/media/ToneGenerator.h b/include/media/ToneGenerator.h
index 75515ac..a419e17 100644
--- a/include/media/ToneGenerator.h
+++ b/include/media/ToneGenerator.h
@@ -313,7 +313,7 @@
 
         short mA1_Q14;  // Q14 coefficient
         // delay line of full amplitude generator
-        short mS1, mS2;  // delay line S2 oldest
+        long mS1, mS2;  // delay line S2 oldest
         short mS2_0;  // saved value for reinitialisation
         short mAmplitude_Q15;  // Q15 amplitude
     };
diff --git a/media/libmedia/ToneGenerator.cpp b/media/libmedia/ToneGenerator.cpp
index 2f53637..9a087ff 100644
--- a/media/libmedia/ToneGenerator.cpp
+++ b/media/libmedia/ToneGenerator.cpp
@@ -1612,8 +1612,8 @@
         lS1 = (long)0;
         lS2 = (long)mS2_0;
     } else {
-        lS1 = (long)mS1;
-        lS2 = (long)mS2;
+        lS1 = mS1;
+        lS2 = mS2;
     }
     lA1 = (long)mA1_Q14;
     lAmplitude = (long)mAmplitude_Q15;
@@ -1649,8 +1649,8 @@
     }
 
     // save status
-    mS1 = (short)lS1;
-    mS2 = (short)lS2;
+    mS1 = lS1;
+    mS2 = lS2;
 }
 
 }  // end namespace android
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
index b47a4f1..8fc2b8e 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -141,6 +141,17 @@
         mAudioSink->flush();
         mAudioSink->close();
     }
+
+    // Try to avoid racing condition in case callback is still on.
+    Mutex::Autolock autoLock(mLock);
+    mUseAudioCallback = false;
+    flushQueue(&mAudioQueue);
+    flushQueue(&mVideoQueue);
+    mWakeLock.clear();
+    mMediaClock.clear();
+    mVideoScheduler.clear();
+    mNotify.clear();
+    mAudioSink.clear();
 }
 
 void NuPlayer::Renderer::queueBuffer(
@@ -744,7 +755,7 @@
         case MediaPlayerBase::AudioSink::CB_EVENT_STREAM_END:
         {
             ALOGV("AudioSink::CB_EVENT_STREAM_END");
-            me->notifyEOS(true /* audio */, ERROR_END_OF_STREAM);
+            me->notifyEOSCallback();
             break;
         }
 
@@ -759,6 +770,16 @@
     return 0;
 }
 
+void NuPlayer::Renderer::notifyEOSCallback() {
+    Mutex::Autolock autoLock(mLock);
+
+    if (!mUseAudioCallback) {
+        return;
+    }
+
+    notifyEOS(true /* audio */, ERROR_END_OF_STREAM);
+}
+
 size_t NuPlayer::Renderer::fillAudioBuffer(void *buffer, size_t size) {
     Mutex::Autolock autoLock(mLock);
 
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
index 004e21c..fe7f8fa 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
@@ -212,6 +212,7 @@
     status_t getCurrentPositionFromAnchor(
             int64_t *mediaUs, int64_t nowUs, bool allowPastQueuedVideo = false);
 
+    void notifyEOSCallback();
     size_t fillAudioBuffer(void *buffer, size_t size);
 
     bool onDrainAudioQueue();
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index 99a85f5..7cb568d 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -4110,11 +4110,13 @@
     if (!mDataSource->getUInt32(offset, &flags)) {
         return ERROR_MALFORMED;
     }
-    ALOGV("fragment run flags: %08x", flags);
-
-    if (flags & 0xff000000) {
-        return -EINVAL;
-    }
+    // |version| only affects SampleCompositionTimeOffset field.
+    // If version == 0, SampleCompositionTimeOffset is uint32_t;
+    // Otherwise, SampleCompositionTimeOffset is int32_t.
+    // Sample.compositionOffset is defined as int32_t.
+    uint8_t version = flags >> 24;
+    flags &= 0xffffff;
+    ALOGV("fragment run version: 0x%02x, flags: 0x%06x", version, flags);
 
     if ((flags & kFirstSampleFlagsPresent) && (flags & kSampleFlagsPresent)) {
         // These two shall not be used together.
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index ff5c4d4..e476424 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -2160,14 +2160,19 @@
             CHECK(msg->findPointer("buffers", (void **)&dstBuffers));
 
             dstBuffers->clear();
-            const Vector<BufferInfo> &srcBuffers = mPortBuffers[portIndex];
+            // If we're using input surface (either non-persistent created by
+            // createInputSurface(), or persistent set by setInputSurface()),
+            // give the client an empty input buffers array.
+            if (portIndex != kPortIndexInput || !mHaveInputSurface) {
+                const Vector<BufferInfo> &srcBuffers = mPortBuffers[portIndex];
 
-            for (size_t i = 0; i < srcBuffers.size(); ++i) {
-                const BufferInfo &info = srcBuffers.itemAt(i);
+                for (size_t i = 0; i < srcBuffers.size(); ++i) {
+                    const BufferInfo &info = srcBuffers.itemAt(i);
 
-                dstBuffers->push_back(
-                        (portIndex == kPortIndexInput && mCrypto != NULL)
-                                ? info.mEncryptedData : info.mData);
+                    dstBuffers->push_back(
+                            (portIndex == kPortIndexInput && mCrypto != NULL)
+                                    ? info.mEncryptedData : info.mData);
+                }
             }
 
             (new AMessage)->postReply(replyID);
diff --git a/services/audioflinger/BufferProviders.cpp b/services/audioflinger/BufferProviders.cpp
index 2ca2cac..7b6dfcb 100644
--- a/services/audioflinger/BufferProviders.cpp
+++ b/services/audioflinger/BufferProviders.cpp
@@ -474,18 +474,18 @@
     ALOGV("processFrames(%zu %zu)  remaining(%zu)", *dstFrames, *srcFrames, mRemaining);
     // Note dstFrames is the required number of frames.
 
-    // Ensure consumption from src is as expected.
-    //TODO: add logic to track "very accurate" consumption related to speed, original sampling
-    //rate, actual frames processed.
-    const size_t targetSrc = *dstFrames * mPlaybackRate.mSpeed;
-    if (*srcFrames < targetSrc) { // limit dst frames to that possible
-        *dstFrames = *srcFrames / mPlaybackRate.mSpeed;
-    } else if (*srcFrames > targetSrc + 1) {
-        *srcFrames = targetSrc + 1;
-    }
-
     if (!mAudioPlaybackRateValid) {
         //fallback mode
+        // Ensure consumption from src is as expected.
+        // TODO: add logic to track "very accurate" consumption related to speed, original sampling
+        // rate, actual frames processed.
+
+        const size_t targetSrc = *dstFrames * mPlaybackRate.mSpeed;
+        if (*srcFrames < targetSrc) { // limit dst frames to that possible
+            *dstFrames = *srcFrames / mPlaybackRate.mSpeed;
+        } else if (*srcFrames > targetSrc + 1) {
+            *srcFrames = targetSrc + 1;
+        }
         if (*dstFrames > 0) {
             switch(mPlaybackRate.mFallbackMode) {
             case AUDIO_TIMESTRETCH_FALLBACK_CUT_REPEAT:
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index a671128..6aedd29 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -3106,9 +3106,9 @@
                 if (!keepWakeLock()) {
                     releaseWakeLock_l();
                     released = true;
+                    mWakeLockUids.clear();
+                    mActiveTracksGeneration++;
                 }
-                mWakeLockUids.clear();
-                mActiveTracksGeneration++;
                 ALOGV("wait async completion");
                 mWaitWorkCV.wait(mLock);
                 ALOGV("async completion/wake");
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index aeab451..48a2a99 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -170,6 +170,9 @@
         return res;
     }
 
+    /** Register in-flight map to the status tracker */
+    mInFlightStatusId = mStatusTracker->addComponent();
+
     /** Create buffer manager */
     mBufferManager = new Camera3BufferManager();
 
@@ -2196,6 +2199,10 @@
             aeTriggerCancelOverride));
     if (res < 0) return res;
 
+    if (mInFlightMap.size() == 1) {
+        mStatusTracker->markComponentActive(mInFlightStatusId);
+    }
+
     return OK;
 }
 
@@ -2252,6 +2259,11 @@
 
         mInFlightMap.removeItemsAt(idx, 1);
 
+        // Indicate idle inFlightMap to the status tracker
+        if (mInFlightMap.size() == 0) {
+            mStatusTracker->markComponentIdle(mInFlightStatusId, Fence::NO_FENCE);
+        }
+
         ALOGVV("%s: removed frame %d from InFlightMap", __FUNCTION__, frameNumber);
      }
 
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index 3244258..17893a9 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -725,6 +725,7 @@
 
     Mutex                  mInFlightLock; // Protects mInFlightMap
     InFlightMap            mInFlightMap;
+    int                    mInFlightStatusId;
 
     status_t registerInFlight(uint32_t frameNumber,
             int32_t numBuffers, CaptureResultExtras resultExtras, bool hasInput,