Merge "MatroskaExtractor: use GetTrackByNumber instead of GetTrackByIndex" into lmp-mr1-dev
diff --git a/cmds/screenrecord/FrameOutput.cpp b/cmds/screenrecord/FrameOutput.cpp
index 03e0062..bef74f5 100644
--- a/cmds/screenrecord/FrameOutput.cpp
+++ b/cmds/screenrecord/FrameOutput.cpp
@@ -206,7 +206,7 @@
 }
 
 // Callback; executes on arbitrary thread.
-void FrameOutput::onFrameAvailable() {
+void FrameOutput::onFrameAvailable(const BufferItem& /* item */) {
     Mutex::Autolock _l(mMutex);
     mFrameAvailable = true;
     mEventCond.signal();
diff --git a/cmds/screenrecord/FrameOutput.h b/cmds/screenrecord/FrameOutput.h
index c49ec3b..4c0c3be 100644
--- a/cmds/screenrecord/FrameOutput.h
+++ b/cmds/screenrecord/FrameOutput.h
@@ -62,7 +62,7 @@
     }
 
     // (overrides GLConsumer::FrameAvailableListener method)
-    virtual void onFrameAvailable();
+    virtual void onFrameAvailable(const BufferItem& item);
 
     // Reduces RGBA to RGB, in place.
     static void reduceRgbaToRgb(uint8_t* buf, unsigned int pixelCount);
diff --git a/cmds/screenrecord/Overlay.cpp b/cmds/screenrecord/Overlay.cpp
index 7fef53d..c659170 100644
--- a/cmds/screenrecord/Overlay.cpp
+++ b/cmds/screenrecord/Overlay.cpp
@@ -274,7 +274,7 @@
 }
 
 // Callback; executes on arbitrary thread.
-void Overlay::onFrameAvailable() {
+void Overlay::onFrameAvailable(const BufferItem& /* item */) {
     ALOGV("Overlay::onFrameAvailable");
     Mutex::Autolock _l(mMutex);
     mFrameAvailable = true;
diff --git a/cmds/screenrecord/Overlay.h b/cmds/screenrecord/Overlay.h
index b1b5c29..ee3444d 100644
--- a/cmds/screenrecord/Overlay.h
+++ b/cmds/screenrecord/Overlay.h
@@ -78,7 +78,7 @@
             const Program& texRender, TextRenderer& textRenderer);
 
     // (overrides GLConsumer::FrameAvailableListener method)
-    virtual void onFrameAvailable();
+    virtual void onFrameAvailable(const BufferItem& item);
 
     // (overrides Thread method)
     virtual bool threadLoop();
diff --git a/drm/mediadrm/plugins/clearkey/DrmPlugin.h b/drm/mediadrm/plugins/clearkey/DrmPlugin.h
index 27df9cd..6139f1f 100644
--- a/drm/mediadrm/plugins/clearkey/DrmPlugin.h
+++ b/drm/mediadrm/plugins/clearkey/DrmPlugin.h
@@ -113,11 +113,21 @@
         return android::ERROR_DRM_CANNOT_HANDLE;
     }
 
+    virtual status_t getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop) {
+        UNUSED(ssid);
+        UNUSED(secureStop);
+        return android::ERROR_DRM_CANNOT_HANDLE;
+    }
+
     virtual status_t releaseSecureStops(const Vector<uint8_t>& ssRelease) {
         UNUSED(ssRelease);
         return android::ERROR_DRM_CANNOT_HANDLE;
     }
 
+    virtual status_t releaseAllSecureStops() {
+        return android::ERROR_DRM_CANNOT_HANDLE;
+    }
+
     virtual status_t getPropertyString(
             const String8& name, String8& value) const;
 
diff --git a/drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.cpp b/drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.cpp
index 2ea554b..7eac0a1 100644
--- a/drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.cpp
+++ b/drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.cpp
@@ -305,6 +305,24 @@
         return OK;
     }
 
+    status_t MockDrmPlugin::getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop)
+    {
+        Mutex::Autolock lock(mLock);
+        ALOGD("MockDrmPlugin::getSecureStop()");
+
+        // Properties used in mock test, set by cts test app returned from mock plugin
+        //   byte[] mock-secure-stop  -> first secure stop in list
+
+        ssize_t index = mByteArrayProperties.indexOfKey(String8("mock-secure-stop"));
+        if (index < 0) {
+            ALOGD("Missing 'mock-secure-stop' parameter for mock");
+            return BAD_VALUE;
+        } else {
+            secureStop = mByteArrayProperties.valueAt(index);
+        }
+        return OK;
+    }
+
     status_t MockDrmPlugin::getSecureStops(List<Vector<uint8_t> > &secureStops)
     {
         Mutex::Autolock lock(mLock);
@@ -349,6 +367,13 @@
         return OK;
     }
 
+    status_t MockDrmPlugin::releaseAllSecureStops()
+    {
+        Mutex::Autolock lock(mLock);
+        ALOGD("MockDrmPlugin::releaseAllSecureStops()");
+        return OK;
+    }
+
     status_t MockDrmPlugin::getPropertyString(String8 const &name, String8 &value) const
     {
         ALOGD("MockDrmPlugin::getPropertyString(name=%s)", name.string());
diff --git a/drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.h b/drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.h
index 4b63299..d1d8058 100644
--- a/drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.h
+++ b/drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.h
@@ -88,7 +88,9 @@
         status_t unprovisionDevice();
 
         status_t getSecureStops(List<Vector<uint8_t> > &secureStops);
+        status_t getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop);
         status_t releaseSecureStops(Vector<uint8_t> const &ssRelease);
+        status_t releaseAllSecureStops();
 
         status_t getPropertyString(String8 const &name, String8 &value ) const;
         status_t getPropertyByteArray(String8 const &name,
diff --git a/include/camera/ProCamera.h b/include/camera/ProCamera.h
index 83a3028..e9b687a 100644
--- a/include/camera/ProCamera.h
+++ b/include/camera/ProCamera.h
@@ -265,7 +265,7 @@
         }
 
     protected:
-        virtual void onFrameAvailable() {
+        virtual void onFrameAvailable(const BufferItem& /* item */) {
             sp<ProCamera> c = mCamera.promote();
             if (c.get() != NULL) {
                 c->onFrameAvailable(mStreamId);
diff --git a/include/media/AudioEffect.h b/include/media/AudioEffect.h
index 4932d40..583695d 100644
--- a/include/media/AudioEffect.h
+++ b/include/media/AudioEffect.h
@@ -133,10 +133,11 @@
      *
      * Returned value
      *   *descriptor updated with descriptors of pre processings enabled by default
-     *   *count      number of descriptors returned if returned status is N_ERROR.
+     *   *count      number of descriptors returned if returned status is NO_ERROR.
      *               total number of pre processing enabled by default if returned status is
      *               NO_MEMORY. This happens if the count passed as input is less than the number
-     *               of descriptors to return
+     *               of descriptors to return.
+     *               *count is limited to kMaxPreProcessing on return.
      */
     static status_t queryDefaultPreProcessing(int audioSession,
                                               effect_descriptor_t *descriptors,
@@ -391,6 +392,10 @@
       */
      static status_t guidToString(const effect_uuid_t *guid, char *str, size_t maxLen);
 
+     // kMaxPreProcessing is a reasonable value for the maximum number of preprocessing effects
+     // that can be applied simultaneously.
+     static const uint32_t kMaxPreProcessing = 10;
+
 protected:
      bool                    mEnabled;           // enable state
      int32_t                 mSessionId;         // audio session ID
diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h
index f8c0198..6a0f2a6 100644
--- a/include/media/AudioSystem.h
+++ b/include/media/AudioSystem.h
@@ -116,8 +116,6 @@
     static status_t getLatency(audio_io_handle_t output,
                                uint32_t* latency);
 
-    static bool routedToA2dpOutput(audio_stream_type_t streamType);
-
     // return status NO_ERROR implies *buffSize > 0
     static status_t getInputBufferSize(uint32_t sampleRate, audio_format_t format,
         audio_channel_mask_t channelMask, size_t* buffSize);
@@ -377,7 +375,10 @@
     friend class AudioFlingerClient;
     friend class AudioPolicyServiceClient;
 
-    static Mutex gLock;
+    static Mutex gLock;     // protects all members except gAudioPolicyService,
+                            // gAudioPolicyServiceClient, and gAudioPortCallback
+    static Mutex gLockAPS;  // protects gAudioPolicyService and gAudioPolicyServiceClient
+    static Mutex gLockAPC;  // protects gAudioPortCallback
     static sp<IAudioFlinger> gAudioFlinger;
     static audio_error_callback gAudioErrorCallback;
 
diff --git a/include/media/ICrypto.h b/include/media/ICrypto.h
index 9dcb8d9..07742ca 100644
--- a/include/media/ICrypto.h
+++ b/include/media/ICrypto.h
@@ -41,6 +41,8 @@
     virtual bool requiresSecureDecoderComponent(
             const char *mime) const = 0;
 
+    virtual void notifyResolution(uint32_t width, uint32_t height) = 0;
+
     virtual ssize_t decrypt(
             bool secure,
             const uint8_t key[16],
@@ -64,4 +66,3 @@
 }  // namespace android
 
 #endif // ANDROID_ICRYPTO_H_
-
diff --git a/include/media/IDrm.h b/include/media/IDrm.h
index 68de87a..affcbd7 100644
--- a/include/media/IDrm.h
+++ b/include/media/IDrm.h
@@ -73,8 +73,10 @@
     virtual status_t unprovisionDevice() = 0;
 
     virtual status_t getSecureStops(List<Vector<uint8_t> > &secureStops) = 0;
+    virtual status_t getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop) = 0;
 
     virtual status_t releaseSecureStops(Vector<uint8_t> const &ssRelease) = 0;
+    virtual status_t releaseAllSecureStops() = 0;
 
     virtual status_t getPropertyString(String8 const &name, String8 &value) const = 0;
     virtual status_t getPropertyByteArray(String8 const &name,
@@ -137,4 +139,3 @@
 }  // namespace android
 
 #endif // ANDROID_IDRM_H_
-
diff --git a/include/media/stagefright/SurfaceMediaSource.h b/include/media/stagefright/SurfaceMediaSource.h
index 43b75fd..d15a226 100644
--- a/include/media/stagefright/SurfaceMediaSource.h
+++ b/include/media/stagefright/SurfaceMediaSource.h
@@ -124,7 +124,7 @@
     // Implementation of the BufferQueue::ConsumerListener interface.  These
     // calls are used to notify the Surface of asynchronous events in the
     // BufferQueue.
-    virtual void onFrameAvailable();
+    virtual void onFrameAvailable(const BufferItem& item);
 
     // Used as a hook to BufferQueue::disconnect()
     // This is called by the client side when it is done
diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp
index dda3657..f5c3383 100644
--- a/media/libmedia/AudioSystem.cpp
+++ b/media/libmedia/AudioSystem.cpp
@@ -32,6 +32,8 @@
 
 // client singleton for AudioFlinger binder interface
 Mutex AudioSystem::gLock;
+Mutex AudioSystem::gLockAPS;
+Mutex AudioSystem::gLockAPC;
 sp<IAudioFlinger> AudioSystem::gAudioFlinger;
 sp<AudioSystem::AudioFlingerClient> AudioSystem::gAudioFlingerClient;
 audio_error_callback AudioSystem::gAudioErrorCallback = NULL;
@@ -70,9 +72,9 @@
         }
         binder->linkToDeath(gAudioFlingerClient);
         gAudioFlinger = interface_cast<IAudioFlinger>(binder);
+        LOG_ALWAYS_FATAL_IF(gAudioFlinger == 0);
         gAudioFlinger->registerClient(gAudioFlingerClient);
     }
-    ALOGE_IF(gAudioFlinger==0, "no AudioFlinger!?");
 
     return gAudioFlinger;
 }
@@ -543,22 +545,8 @@
     gAudioErrorCallback = cb;
 }
 
-
-bool AudioSystem::routedToA2dpOutput(audio_stream_type_t streamType)
-{
-    switch (streamType) {
-    case AUDIO_STREAM_MUSIC:
-    case AUDIO_STREAM_VOICE_CALL:
-    case AUDIO_STREAM_BLUETOOTH_SCO:
-    case AUDIO_STREAM_SYSTEM:
-        return true;
-    default:
-        return false;
-    }
-}
-
-
 // client singleton for AudioPolicyService binder interface
+// protected by gLockAPS
 sp<IAudioPolicyService> AudioSystem::gAudioPolicyService;
 sp<AudioSystem::AudioPolicyServiceClient> AudioSystem::gAudioPolicyServiceClient;
 
@@ -566,7 +554,7 @@
 // establish binder interface to AudioPolicy service
 const sp<IAudioPolicyService>& AudioSystem::get_audio_policy_service()
 {
-    gLock.lock();
+    Mutex::Autolock _l(gLockAPS);
     if (gAudioPolicyService == 0) {
         sp<IServiceManager> sm = defaultServiceManager();
         sp<IBinder> binder;
@@ -582,15 +570,10 @@
         }
         binder->linkToDeath(gAudioPolicyServiceClient);
         gAudioPolicyService = interface_cast<IAudioPolicyService>(binder);
-        gLock.unlock();
-        // Registering the client takes the AudioPolicyService lock.
-        // Don't hold the AudioSystem lock at the same time.
+        LOG_ALWAYS_FATAL_IF(gAudioPolicyService == 0);
         gAudioPolicyService->registerClient(gAudioPolicyServiceClient);
-    } else {
-        // There exists a benign race condition where gAudioPolicyService
-        // is set, but gAudioPolicyServiceClient is not yet registered.
-        gLock.unlock();
     }
+
     return gAudioPolicyService;
 }
 
@@ -856,9 +839,18 @@
 
 void AudioSystem::clearAudioConfigCache()
 {
-    Mutex::Autolock _l(gLock);
+    // called by restoreTrack_l(), which needs new IAudioFlinger and IAudioPolicyService instances
     ALOGV("clearAudioConfigCache()");
-    gOutputs.clear();
+    {
+        Mutex::Autolock _l(gLock);
+        gOutputs.clear();
+        gAudioFlinger.clear();
+    }
+    {
+        Mutex::Autolock _l(gLockAPS);
+        gAudioPolicyService.clear();
+    }
+    // Do not clear gAudioPortCallback
 }
 
 bool AudioSystem::isOffloadSupported(const audio_offload_info_t& info)
@@ -920,7 +912,7 @@
 
 void AudioSystem::setAudioPortCallback(sp<AudioPortCallback> callBack)
 {
-    Mutex::Autolock _l(gLock);
+    Mutex::Autolock _l(gLockAPC);
     gAudioPortCallback = callBack;
 }
 
@@ -952,18 +944,23 @@
 
 void AudioSystem::AudioPolicyServiceClient::binderDied(const wp<IBinder>& who __unused)
 {
-    Mutex::Autolock _l(gLock);
-    if (gAudioPortCallback != 0) {
-        gAudioPortCallback->onServiceDied();
+    {
+        Mutex::Autolock _l(gLockAPC);
+        if (gAudioPortCallback != 0) {
+            gAudioPortCallback->onServiceDied();
+        }
     }
-    AudioSystem::gAudioPolicyService.clear();
+    {
+        Mutex::Autolock _l(gLockAPS);
+        AudioSystem::gAudioPolicyService.clear();
+    }
 
     ALOGW("AudioPolicyService server died!");
 }
 
 void AudioSystem::AudioPolicyServiceClient::onAudioPortListUpdate()
 {
-    Mutex::Autolock _l(gLock);
+    Mutex::Autolock _l(gLockAPC);
     if (gAudioPortCallback != 0) {
         gAudioPortCallback->onAudioPortListUpdate();
     }
@@ -971,7 +968,7 @@
 
 void AudioSystem::AudioPolicyServiceClient::onAudioPatchListUpdate()
 {
-    Mutex::Autolock _l(gLock);
+    Mutex::Autolock _l(gLockAPC);
     if (gAudioPortCallback != 0) {
         gAudioPortCallback->onAudioPatchListUpdate();
     }
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 082a5e1..cd493f6 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -1828,7 +1828,7 @@
     status_t result;
 
     // refresh the audio configuration cache in this process to make sure we get new
-    // output parameters in createTrack_l()
+    // output parameters and new IAudioFlinger in createTrack_l()
     AudioSystem::clearAudioConfigCache();
 
     if (isOffloadedOrDirect_l()) {
diff --git a/media/libmedia/IAudioPolicyService.cpp b/media/libmedia/IAudioPolicyService.cpp
index 256cb3f..89178f1 100644
--- a/media/libmedia/IAudioPolicyService.cpp
+++ b/media/libmedia/IAudioPolicyService.cpp
@@ -23,6 +23,7 @@
 
 #include <binder/Parcel.h>
 
+#include <media/AudioEffect.h>
 #include <media/IAudioPolicyService.h>
 
 #include <system/audio.h>
@@ -704,8 +705,8 @@
 
         case GET_OUTPUT_FOR_ATTR: {
             CHECK_INTERFACE(IAudioPolicyService, data, reply);
-            audio_attributes_t *attr = (audio_attributes_t *) calloc(1, sizeof(audio_attributes_t));
-            data.read(attr, sizeof(audio_attributes_t));
+            audio_attributes_t attr;
+            data.read(&attr, sizeof(audio_attributes_t));
             uint32_t samplingRate = data.readInt32();
             audio_format_t format = (audio_format_t) data.readInt32();
             audio_channel_mask_t channelMask = data.readInt32();
@@ -716,7 +717,7 @@
             if (hasOffloadInfo) {
                 data.read(&offloadInfo, sizeof(audio_offload_info_t));
             }
-            audio_io_handle_t output = getOutputForAttr(attr,
+            audio_io_handle_t output = getOutputForAttr(&attr,
                     samplingRate,
                     format,
                     channelMask,
@@ -916,16 +917,18 @@
             CHECK_INTERFACE(IAudioPolicyService, data, reply);
             int audioSession = data.readInt32();
             uint32_t count = data.readInt32();
+            if (count > AudioEffect::kMaxPreProcessing) {
+                count = AudioEffect::kMaxPreProcessing;
+            }
             uint32_t retCount = count;
-            effect_descriptor_t *descriptors =
-                    (effect_descriptor_t *)new char[count * sizeof(effect_descriptor_t)];
+            effect_descriptor_t *descriptors = new effect_descriptor_t[count];
             status_t status = queryDefaultPreProcessing(audioSession, descriptors, &retCount);
             reply->writeInt32(status);
             if (status != NO_ERROR && status != NO_MEMORY) {
                 retCount = 0;
             }
             reply->writeInt32(retCount);
-            if (retCount) {
+            if (retCount != 0) {
                 if (retCount < count) {
                     count = retCount;
                 }
diff --git a/media/libmedia/ICrypto.cpp b/media/libmedia/ICrypto.cpp
index 0d5f990..c26c5bf 100644
--- a/media/libmedia/ICrypto.cpp
+++ b/media/libmedia/ICrypto.cpp
@@ -33,6 +33,7 @@
     DESTROY_PLUGIN,
     REQUIRES_SECURE_COMPONENT,
     DECRYPT,
+    NOTIFY_RESOLUTION,
 };
 
 struct BpCrypto : public BpInterface<ICrypto> {
@@ -149,6 +150,15 @@
         return result;
     }
 
+    virtual void notifyResolution(
+        uint32_t width, uint32_t height) {
+        Parcel data, reply;
+        data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
+        data.writeInt32(width);
+        data.writeInt32(height);
+        remote()->transact(NOTIFY_RESOLUTION, data, &reply);
+    }
+
 private:
     DISALLOW_EVIL_CONSTRUCTORS(BpCrypto);
 };
@@ -290,10 +300,20 @@
             return OK;
         }
 
+        case NOTIFY_RESOLUTION:
+        {
+            CHECK_INTERFACE(ICrypto, data, reply);
+
+            int32_t width = data.readInt32();
+            int32_t height = data.readInt32();
+            notifyResolution(width, height);
+
+            return OK;
+        }
+
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
 }
 
 }  // namespace android
-
diff --git a/media/libmedia/IDrm.cpp b/media/libmedia/IDrm.cpp
index 1904839..7e74de9 100644
--- a/media/libmedia/IDrm.cpp
+++ b/media/libmedia/IDrm.cpp
@@ -54,7 +54,9 @@
     SIGN_RSA,
     VERIFY,
     SET_LISTENER,
-    UNPROVISION_DEVICE
+    UNPROVISION_DEVICE,
+    GET_SECURE_STOP,
+    RELEASE_ALL_SECURE_STOPS
 };
 
 struct BpDrm : public BpInterface<IDrm> {
@@ -255,6 +257,17 @@
         return reply.readInt32();
     }
 
+    virtual status_t getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
+
+        writeVector(data, ssid);
+        remote()->transact(GET_SECURE_STOP, data, &reply);
+
+        readVector(reply, secureStop);
+        return reply.readInt32();
+    }
+
     virtual status_t releaseSecureStops(Vector<uint8_t> const &ssRelease) {
         Parcel data, reply;
         data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
@@ -265,6 +278,15 @@
         return reply.readInt32();
     }
 
+    virtual status_t releaseAllSecureStops() {
+        Parcel data, reply;
+        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
+
+        remote()->transact(RELEASE_ALL_SECURE_STOPS, data, &reply);
+
+        return reply.readInt32();
+    }
+
     virtual status_t getPropertyString(String8 const &name, String8 &value) const {
         Parcel data, reply;
         data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
@@ -655,6 +677,17 @@
             return OK;
         }
 
+        case GET_SECURE_STOP:
+        {
+            CHECK_INTERFACE(IDrm, data, reply);
+            Vector<uint8_t> ssid, secureStop;
+            readVector(data, ssid);
+            status_t result = getSecureStop(ssid, secureStop);
+            writeVector(reply, secureStop);
+            reply->writeInt32(result);
+            return OK;
+        }
+
         case RELEASE_SECURE_STOPS:
         {
             CHECK_INTERFACE(IDrm, data, reply);
@@ -664,6 +697,13 @@
             return OK;
         }
 
+        case RELEASE_ALL_SECURE_STOPS:
+        {
+            CHECK_INTERFACE(IDrm, data, reply);
+            reply->writeInt32(releaseAllSecureStops());
+            return OK;
+        }
+
         case GET_PROPERTY_STRING:
         {
             CHECK_INTERFACE(IDrm, data, reply);
@@ -809,4 +849,3 @@
 }
 
 }  // namespace android
-
diff --git a/media/libmediaplayerservice/Crypto.cpp b/media/libmediaplayerservice/Crypto.cpp
index 62593b2..8ee7c0b 100644
--- a/media/libmediaplayerservice/Crypto.cpp
+++ b/media/libmediaplayerservice/Crypto.cpp
@@ -257,4 +257,12 @@
             errorDetailMsg);
 }
 
+void Crypto::notifyResolution(uint32_t width, uint32_t height) {
+    Mutex::Autolock autoLock(mLock);
+
+    if (mInitCheck == OK && mPlugin != NULL) {
+        mPlugin->notifyResolution(width, height);
+    }
+}
+
 }  // namespace android
diff --git a/media/libmediaplayerservice/Crypto.h b/media/libmediaplayerservice/Crypto.h
index c44ae34..0037c2e 100644
--- a/media/libmediaplayerservice/Crypto.h
+++ b/media/libmediaplayerservice/Crypto.h
@@ -45,6 +45,8 @@
     virtual bool requiresSecureDecoderComponent(
             const char *mime) const;
 
+    virtual void notifyResolution(uint32_t width, uint32_t height);
+
     virtual ssize_t decrypt(
             bool secure,
             const uint8_t key[16],
diff --git a/media/libmediaplayerservice/Drm.cpp b/media/libmediaplayerservice/Drm.cpp
index d222316..2a8b2c6 100644
--- a/media/libmediaplayerservice/Drm.cpp
+++ b/media/libmediaplayerservice/Drm.cpp
@@ -449,6 +449,20 @@
     return mPlugin->getSecureStops(secureStops);
 }
 
+status_t Drm::getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop) {
+    Mutex::Autolock autoLock(mLock);
+
+    if (mInitCheck != OK) {
+        return mInitCheck;
+    }
+
+    if (mPlugin == NULL) {
+        return -EINVAL;
+    }
+
+    return mPlugin->getSecureStop(ssid, secureStop);
+}
+
 status_t Drm::releaseSecureStops(Vector<uint8_t> const &ssRelease) {
     Mutex::Autolock autoLock(mLock);
 
@@ -463,6 +477,20 @@
     return mPlugin->releaseSecureStops(ssRelease);
 }
 
+status_t Drm::releaseAllSecureStops() {
+    Mutex::Autolock autoLock(mLock);
+
+    if (mInitCheck != OK) {
+        return mInitCheck;
+    }
+
+    if (mPlugin == NULL) {
+        return -EINVAL;
+    }
+
+    return mPlugin->releaseAllSecureStops();
+}
+
 status_t Drm::getPropertyString(String8 const &name, String8 &value ) const {
     Mutex::Autolock autoLock(mLock);
 
diff --git a/media/libmediaplayerservice/Drm.h b/media/libmediaplayerservice/Drm.h
index 9e23e2e..0e1eb2c 100644
--- a/media/libmediaplayerservice/Drm.h
+++ b/media/libmediaplayerservice/Drm.h
@@ -78,8 +78,10 @@
     virtual status_t unprovisionDevice();
 
     virtual status_t getSecureStops(List<Vector<uint8_t> > &secureStops);
+    virtual status_t getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop);
 
     virtual status_t releaseSecureStops(Vector<uint8_t> const &ssRelease);
+    virtual status_t releaseAllSecureStops();
 
     virtual status_t getPropertyString(String8 const &name, String8 &value ) const;
     virtual status_t getPropertyByteArray(String8 const &name,
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
index 6859a1a..d446cec 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
@@ -45,6 +45,10 @@
         bool uidValid,
         uid_t uid)
     : Source(notify),
+      mAudioTimeUs(0),
+      mAudioLastDequeueTimeUs(0),
+      mVideoTimeUs(0),
+      mVideoLastDequeueTimeUs(0),
       mFetchSubtitleDataGeneration(0),
       mFetchTimedTextDataGeneration(0),
       mDurationUs(0ll),
@@ -62,8 +66,6 @@
 }
 
 void NuPlayer::GenericSource::resetDataSource() {
-    mAudioTimeUs = 0;
-    mVideoTimeUs = 0;
     mHTTPService.clear();
     mHttpSource.clear();
     mUri.clear();
@@ -644,17 +646,13 @@
           track->mSource->start();
           track->mIndex = trackIndex;
 
-          status_t avail;
-          if (!track->mPackets->hasBufferAvailable(&avail)) {
-              // sync from other source
-              TRESPASS();
-              break;
-          }
-
           int64_t timeUs, actualTimeUs;
           const bool formatChange = true;
-          sp<AMessage> latestMeta = track->mPackets->getLatestEnqueuedMeta();
-          CHECK(latestMeta != NULL && latestMeta->findInt64("timeUs", &timeUs));
+          if (trackType == MEDIA_TRACK_TYPE_AUDIO) {
+              timeUs = mAudioLastDequeueTimeUs;
+          } else {
+              timeUs = mVideoLastDequeueTimeUs;
+          }
           readBuffer(trackType, timeUs, &actualTimeUs, formatChange);
           readBuffer(counterpartType, -1, NULL, formatChange);
           ALOGV("timeUs %lld actualTimeUs %lld", timeUs, actualTimeUs);
@@ -866,6 +864,11 @@
     int64_t timeUs;
     status_t eosResult; // ignored
     CHECK((*accessUnit)->meta()->findInt64("timeUs", &timeUs));
+    if (audio) {
+        mAudioLastDequeueTimeUs = timeUs;
+    } else {
+        mVideoLastDequeueTimeUs = timeUs;
+    }
 
     if (mSubtitleTrack.mSource != NULL
             && !mSubtitleTrack.mPackets->hasBufferAvailable(&eosResult)) {
@@ -1132,10 +1135,12 @@
         readBuffer(MEDIA_TRACK_TYPE_VIDEO, seekTimeUs, &actualTimeUs);
 
         seekTimeUs = actualTimeUs;
+        mVideoLastDequeueTimeUs = seekTimeUs;
     }
 
     if (mAudioTrack.mSource != NULL) {
         readBuffer(MEDIA_TRACK_TYPE_AUDIO, seekTimeUs);
+        mAudioLastDequeueTimeUs = seekTimeUs;
     }
 
     setDrmPlaybackStatusIfNeeded(Playback::START, seekTimeUs / 1000);
@@ -1311,11 +1316,9 @@
             if ((seeking || formatChange)
                     && (trackType == MEDIA_TRACK_TYPE_AUDIO
                     || trackType == MEDIA_TRACK_TYPE_VIDEO)) {
-                ATSParser::DiscontinuityType type = formatChange
-                        ? (seeking
-                                ? ATSParser::DISCONTINUITY_FORMATCHANGE
-                                : ATSParser::DISCONTINUITY_NONE)
-                        : ATSParser::DISCONTINUITY_SEEK;
+                ATSParser::DiscontinuityType type = (formatChange && seeking)
+                        ? ATSParser::DISCONTINUITY_FORMATCHANGE
+                        : ATSParser::DISCONTINUITY_NONE;
                 track->mPackets->queueDiscontinuity( type, NULL, true /* discard */);
             }
 
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.h b/media/libmediaplayerservice/nuplayer/GenericSource.h
index f8601ea..7a03df0 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.h
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.h
@@ -106,8 +106,10 @@
 
     Track mAudioTrack;
     int64_t mAudioTimeUs;
+    int64_t mAudioLastDequeueTimeUs;
     Track mVideoTrack;
     int64_t mVideoTimeUs;
+    int64_t mVideoLastDequeueTimeUs;
     Track mSubtitleTrack;
     Track mTimedTextTrack;
 
diff --git a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp
index a003c81..02e9caf 100644
--- a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp
@@ -98,6 +98,10 @@
 }
 
 sp<AMessage> NuPlayer::HTTPLiveSource::getFormat(bool audio) {
+    if (mLiveSession == NULL) {
+        return NULL;
+    }
+
     sp<AMessage> format;
     status_t err = mLiveSession->getStreamFormat(
             audio ? LiveSession::STREAMTYPE_AUDIO
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index 931451f..47bd989 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -95,21 +95,21 @@
     DISALLOW_EVIL_CONSTRUCTORS(SetSurfaceAction);
 };
 
-struct NuPlayer::ShutdownDecoderAction : public Action {
-    ShutdownDecoderAction(bool audio, bool video)
+struct NuPlayer::FlushDecoderAction : public Action {
+    FlushDecoderAction(FlushCommand audio, FlushCommand video)
         : mAudio(audio),
           mVideo(video) {
     }
 
     virtual void execute(NuPlayer *player) {
-        player->performDecoderShutdown(mAudio, mVideo);
+        player->performDecoderFlush(mAudio, mVideo);
     }
 
 private:
-    bool mAudio;
-    bool mVideo;
+    FlushCommand mAudio;
+    FlushCommand mVideo;
 
-    DISALLOW_EVIL_CONSTRUCTORS(ShutdownDecoderAction);
+    DISALLOW_EVIL_CONSTRUCTORS(FlushDecoderAction);
 };
 
 struct NuPlayer::PostMessageAction : public Action {
@@ -522,19 +522,24 @@
         {
             ALOGV("kWhatSetVideoNativeWindow");
 
-            mDeferredActions.push_back(
-                    new ShutdownDecoderAction(
-                        false /* audio */, true /* video */));
-
             sp<RefBase> obj;
             CHECK(msg->findObject("native-window", &obj));
 
+            if (mSource->getFormat(false /* audio */) == NULL) {
+                performSetSurface(static_cast<NativeWindowWrapper *>(obj.get()));
+                break;
+            }
+
+            mDeferredActions.push_back(
+                    new FlushDecoderAction(FLUSH_CMD_FLUSH /* audio */,
+                                           FLUSH_CMD_SHUTDOWN /* video */));
+
             mDeferredActions.push_back(
                     new SetSurfaceAction(
                         static_cast<NativeWindowWrapper *>(obj.get())));
 
             if (obj != NULL) {
-                if (mStarted && mSource->getFormat(false /* audio */) != NULL) {
+                if (mStarted) {
                     // Issue a seek to refresh the video screen only if started otherwise
                     // the extractor may not yet be started and will assert.
                     // If the video decoder is not set (perhaps audio only in this case)
@@ -749,7 +754,9 @@
                 switch (*flushing) {
                     case NONE:
                         mDeferredActions.push_back(
-                                new ShutdownDecoderAction(audio, !audio /* video */));
+                                new FlushDecoderAction(
+                                    audio ? FLUSH_CMD_SHUTDOWN : FLUSH_CMD_NONE,
+                                    audio ? FLUSH_CMD_NONE : FLUSH_CMD_SHUTDOWN));
                         processDeferredActions();
                         break;
                     case FLUSHING_DECODER:
@@ -872,8 +879,9 @@
             ALOGV("kWhatReset");
 
             mDeferredActions.push_back(
-                    new ShutdownDecoderAction(
-                        true /* audio */, true /* video */));
+                    new FlushDecoderAction(
+                        FLUSH_CMD_SHUTDOWN /* audio */,
+                        FLUSH_CMD_SHUTDOWN /* video */));
 
             mDeferredActions.push_back(
                     new SimpleAction(&NuPlayer::performReset));
@@ -893,7 +901,8 @@
                     seekTimeUs, needNotify);
 
             mDeferredActions.push_back(
-                    new SimpleAction(&NuPlayer::performDecoderFlush));
+                    new FlushDecoderAction(FLUSH_CMD_FLUSH /* audio */,
+                                           FLUSH_CMD_FLUSH /* video */));
 
             mDeferredActions.push_back(
                     new SeekAction(seekTimeUs, needNotify));
@@ -1625,7 +1634,9 @@
     ALOGI("queueDecoderShutdown audio=%d, video=%d", audio, video);
 
     mDeferredActions.push_back(
-            new ShutdownDecoderAction(audio, video));
+            new FlushDecoderAction(
+                audio ? FLUSH_CMD_SHUTDOWN : FLUSH_CMD_NONE,
+                video ? FLUSH_CMD_SHUTDOWN : FLUSH_CMD_NONE));
 
     mDeferredActions.push_back(
             new SimpleAction(&NuPlayer::performScanSources));
@@ -1770,40 +1781,22 @@
     // everything's flushed, continue playback.
 }
 
-void NuPlayer::performDecoderFlush() {
-    ALOGV("performDecoderFlush");
+void NuPlayer::performDecoderFlush(FlushCommand audio, FlushCommand video) {
+    ALOGV("performDecoderFlush audio=%d, video=%d", audio, video);
 
-    if (mAudioDecoder == NULL && mVideoDecoder == NULL) {
+    if ((audio == FLUSH_CMD_NONE || mAudioDecoder == NULL)
+            && (video == FLUSH_CMD_NONE || mVideoDecoder == NULL)) {
         return;
     }
 
     mTimeDiscontinuityPending = true;
 
-    if (mAudioDecoder != NULL) {
-        flushDecoder(true /* audio */, false /* needShutdown */);
+    if (audio != FLUSH_CMD_NONE && mAudioDecoder != NULL) {
+        flushDecoder(true /* audio */, (audio == FLUSH_CMD_SHUTDOWN));
     }
 
-    if (mVideoDecoder != NULL) {
-        flushDecoder(false /* audio */, false /* needShutdown */);
-    }
-}
-
-void NuPlayer::performDecoderShutdown(bool audio, bool video) {
-    ALOGV("performDecoderShutdown audio=%d, video=%d", audio, video);
-
-    if ((!audio || mAudioDecoder == NULL)
-            && (!video || mVideoDecoder == NULL)) {
-        return;
-    }
-
-    mTimeDiscontinuityPending = true;
-
-    if (audio && mAudioDecoder != NULL) {
-        flushDecoder(true /* audio */, true /* needShutdown */);
-    }
-
-    if (video && mVideoDecoder != NULL) {
-        flushDecoder(false /* audio */, true /* needShutdown */);
+    if (video != FLUSH_CMD_NONE && mVideoDecoder != NULL) {
+        flushDecoder(false /* audio */, (video == FLUSH_CMD_SHUTDOWN));
     }
 }
 
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h
index 14056ca..121f7dd 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h
@@ -94,7 +94,7 @@
     struct Action;
     struct SeekAction;
     struct SetSurfaceAction;
-    struct ShutdownDecoderAction;
+    struct FlushDecoderAction;
     struct PostMessageAction;
     struct SimpleAction;
 
@@ -159,6 +159,12 @@
         SHUT_DOWN,
     };
 
+    enum FlushCommand {
+        FLUSH_CMD_NONE,
+        FLUSH_CMD_FLUSH,
+        FLUSH_CMD_SHUTDOWN,
+    };
+
     // Once the current flush is complete this indicates whether the
     // notion of time has changed.
     bool mTimeDiscontinuityPending;
@@ -229,8 +235,7 @@
     void processDeferredActions();
 
     void performSeek(int64_t seekTimeUs, bool needNotify);
-    void performDecoderFlush();
-    void performDecoderShutdown(bool audio, bool video);
+    void performDecoderFlush(FlushCommand audio, FlushCommand video);
     void performReset();
     void performScanSources();
     void performSetSurface(const sp<NativeWindowWrapper> &wrapper);
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
index 5d9001c..d9e3ee8 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -629,6 +629,10 @@
 
             mAudioQueue.erase(mAudioQueue.begin());
             entry = NULL;
+            // Need to stop the track here, because that will play out the last
+            // little bit at the end of the file. Otherwise short files won't play.
+            mAudioSink->stop();
+            mNumFramesWritten = 0;
             return false;
         }
 
diff --git a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
index ffacb8f..52ae9ee 100644
--- a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
@@ -506,7 +506,7 @@
             sp<AnotherPacketSource> source = info->mSource;
             if (source != NULL) {
                 source->queueDiscontinuity(
-                        ATSParser::DISCONTINUITY_SEEK,
+                        ATSParser::DISCONTINUITY_TIME,
                         NULL,
                         true /* discard */);
             }
diff --git a/media/libmediaplayerservice/nuplayer/StreamingSource.cpp b/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
index 2e9a29a..27f5159 100644
--- a/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
@@ -80,7 +80,7 @@
             mFinalResult = ERROR_END_OF_STREAM;
             break;
         } else if (n == INFO_DISCONTINUITY) {
-            int32_t type = ATSParser::DISCONTINUITY_SEEK;
+            int32_t type = ATSParser::DISCONTINUITY_TIME;
 
             int32_t mask;
             if (extra != NULL
@@ -118,7 +118,7 @@
 
                 mTSParser->signalDiscontinuity(
                         ((type & 1) == 0)
-                            ? ATSParser::DISCONTINUITY_SEEK
+                            ? ATSParser::DISCONTINUITY_TIME
                             : ATSParser::DISCONTINUITY_FORMATCHANGE,
                         extra);
             } else {
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index df47bd5..d7ddc89 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -1011,6 +1011,16 @@
                         mFlags |= kFlagOutputFormatChanged;
                         postActivityNotificationIfPossible();
                     }
+
+                    // Notify mCrypto of video resolution changes
+                    if (mCrypto != NULL) {
+                      int32_t height, width;
+                      if (mOutputFormat->findInt32("height", &height) &&
+                          mOutputFormat->findInt32("width", &width)) {
+                        mCrypto->notifyResolution(width, height);
+                      }
+                    }
+
                     break;
                 }
 
diff --git a/media/libstagefright/SurfaceMediaSource.cpp b/media/libstagefright/SurfaceMediaSource.cpp
index 4e1c65c..530383b 100644
--- a/media/libstagefright/SurfaceMediaSource.cpp
+++ b/media/libstagefright/SurfaceMediaSource.cpp
@@ -448,7 +448,7 @@
 }
 
 // Part of the BufferQueue::ConsumerListener
-void SurfaceMediaSource::onFrameAvailable() {
+void SurfaceMediaSource::onFrameAvailable(const BufferItem& /* item */) {
     ALOGV("onFrameAvailable");
 
     sp<FrameAvailableListener> listener;
diff --git a/media/libstagefright/httplive/LiveSession.cpp b/media/libstagefright/httplive/LiveSession.cpp
index fba6b09..874c118 100644
--- a/media/libstagefright/httplive/LiveSession.cpp
+++ b/media/libstagefright/httplive/LiveSession.cpp
@@ -1458,7 +1458,7 @@
                     extra->setInt64("timeUs", timeUs);
                     discontinuityQueue = mDiscontinuities.valueFor(indexToType(j));
                     discontinuityQueue->queueDiscontinuity(
-                            ATSParser::DISCONTINUITY_SEEK, extra, true);
+                            ATSParser::DISCONTINUITY_TIME, extra, true);
                 } else {
                     int32_t type;
                     int64_t srcSegmentStartTimeUs;
diff --git a/media/libstagefright/httplive/PlaylistFetcher.cpp b/media/libstagefright/httplive/PlaylistFetcher.cpp
index 30fa868..eb3154a 100644
--- a/media/libstagefright/httplive/PlaylistFetcher.cpp
+++ b/media/libstagefright/httplive/PlaylistFetcher.cpp
@@ -1155,7 +1155,7 @@
         extra->setInt64(IStreamListener::kKeyMediaTimeUs, 0);
 
         mTSParser->signalDiscontinuity(
-                ATSParser::DISCONTINUITY_SEEK, extra);
+                ATSParser::DISCONTINUITY_TIME, extra);
 
         mAbsoluteTimeAnchorUs = mNextPTSTimeUs;
         mNextPTSTimeUs = -1ll;
@@ -1587,6 +1587,7 @@
                 mStartTimeUsNotify->setInt32("streamMask", LiveSession::STREAMTYPE_AUDIO);
                 mStartTimeUsNotify->post();
                 mStartTimeUsNotify.clear();
+                mStartup = false;
             }
         }
 
diff --git a/media/libstagefright/mpeg2ts/ATSParser.h b/media/libstagefright/mpeg2ts/ATSParser.h
index 8986a22..204934d 100644
--- a/media/libstagefright/mpeg2ts/ATSParser.h
+++ b/media/libstagefright/mpeg2ts/ATSParser.h
@@ -41,8 +41,6 @@
         DISCONTINUITY_ABSOLUTE_TIME     = 8,
         DISCONTINUITY_TIME_OFFSET       = 16,
 
-        DISCONTINUITY_SEEK              = DISCONTINUITY_TIME,
-
         // For legacy reasons this also implies a time discontinuity.
         DISCONTINUITY_FORMATCHANGE      =
             DISCONTINUITY_AUDIO_FORMAT
diff --git a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
index a03f6f9..ed40bdd 100644
--- a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
+++ b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
@@ -262,6 +262,10 @@
         }
     }
 
+    if (type == ATSParser::DISCONTINUITY_NONE) {
+        return;
+    }
+
     mEOSResult = OK;
     mLastQueuedTimeUs = 0;
     mLatestEnqueuedMeta = NULL;
diff --git a/media/libstagefright/omx/GraphicBufferSource.cpp b/media/libstagefright/omx/GraphicBufferSource.cpp
index 3e70956..44c7edc 100644
--- a/media/libstagefright/omx/GraphicBufferSource.cpp
+++ b/media/libstagefright/omx/GraphicBufferSource.cpp
@@ -750,7 +750,7 @@
 }
 
 // BufferQueue::ConsumerListener callback
-void GraphicBufferSource::onFrameAvailable() {
+void GraphicBufferSource::onFrameAvailable(const BufferItem& /*item*/) {
     Mutex::Autolock autoLock(mMutex);
 
     ALOGV("onFrameAvailable exec=%d avail=%zu",
diff --git a/media/libstagefright/omx/GraphicBufferSource.h b/media/libstagefright/omx/GraphicBufferSource.h
index c0860ab..c8e3775 100644
--- a/media/libstagefright/omx/GraphicBufferSource.h
+++ b/media/libstagefright/omx/GraphicBufferSource.h
@@ -137,7 +137,7 @@
     // into the codec buffer, and call Empty[This]Buffer.  If we're not yet
     // executing or there's no codec buffer available, we just increment
     // mNumFramesAvailable and return.
-    virtual void onFrameAvailable();
+    virtual void onFrameAvailable(const BufferItem& item);
 
     // BufferQueue::ConsumerListener interface, called when the client has
     // released one or more GraphicBuffers.  We clear out the appropriate
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 7b65de7..ea9d7d3 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -2633,7 +2633,8 @@
     // Check whether the destination thread has a channel count of FCC_2, which is
     // currently required for (most) effects. Prevent moving the effect chain here rather
     // than disabling the addEffect_l() call in dstThread below.
-    if (dstThread->mChannelCount != FCC_2) {
+    if ((dstThread->type() == ThreadBase::MIXER || dstThread->type() == ThreadBase::DUPLICATING) &&
+            dstThread->mChannelCount != FCC_2) {
         ALOGW("moveEffectChain_l() effect chain failed because"
                 " destination thread %p channel count(%u) != %u",
                 dstThread, dstThread->mChannelCount, FCC_2);
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index e443476..71a6a73 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -4660,7 +4660,11 @@
     if (outputsReady(outputTracks)) {
         mAudioMixer->process(AudioBufferProvider::kInvalidPTS);
     } else {
-        memset(mSinkBuffer, 0, mSinkBufferSize);
+        if (mMixerBufferValid) {
+            memset(mMixerBuffer, 0, mMixerBufferSize);
+        } else {
+            memset(mSinkBuffer, 0, mSinkBufferSize);
+        }
     }
     sleepTime = 0;
     writeFrames = mNormalFrameCount;
diff --git a/services/camera/libcameraservice/api1/client2/BurstCapture.cpp b/services/camera/libcameraservice/api1/client2/BurstCapture.cpp
index 0bfdfd4..5502dcb 100644
--- a/services/camera/libcameraservice/api1/client2/BurstCapture.cpp
+++ b/services/camera/libcameraservice/api1/client2/BurstCapture.cpp
@@ -44,7 +44,7 @@
     return INVALID_OPERATION;
 }
 
-void BurstCapture::onFrameAvailable() {
+void BurstCapture::onFrameAvailable(const BufferItem &/*item*/) {
     ALOGV("%s", __FUNCTION__);
     Mutex::Autolock l(mInputMutex);
     if(!mInputChanged) {
diff --git a/services/camera/libcameraservice/api1/client2/BurstCapture.h b/services/camera/libcameraservice/api1/client2/BurstCapture.h
index ea321fd..c3b7722 100644
--- a/services/camera/libcameraservice/api1/client2/BurstCapture.h
+++ b/services/camera/libcameraservice/api1/client2/BurstCapture.h
@@ -39,7 +39,7 @@
     BurstCapture(wp<Camera2Client> client, wp<CaptureSequencer> sequencer);
     virtual ~BurstCapture();
 
-    virtual void onFrameAvailable();
+    virtual void onFrameAvailable(const BufferItem& item);
     virtual status_t start(Vector<CameraMetadata> &metadatas, int32_t firstCaptureId);
 
 protected:
diff --git a/services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp b/services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp
index bf3318e..eadaa00 100644
--- a/services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp
@@ -46,7 +46,7 @@
     deleteStream();
 }
 
-void CallbackProcessor::onFrameAvailable() {
+void CallbackProcessor::onFrameAvailable(const BufferItem& /*item*/) {
     Mutex::Autolock l(mInputMutex);
     if (!mCallbackAvailable) {
         mCallbackAvailable = true;
diff --git a/services/camera/libcameraservice/api1/client2/CallbackProcessor.h b/services/camera/libcameraservice/api1/client2/CallbackProcessor.h
index 613f5be..7fdc329 100644
--- a/services/camera/libcameraservice/api1/client2/CallbackProcessor.h
+++ b/services/camera/libcameraservice/api1/client2/CallbackProcessor.h
@@ -44,7 +44,7 @@
     CallbackProcessor(sp<Camera2Client> client);
     ~CallbackProcessor();
 
-    void onFrameAvailable();
+    void onFrameAvailable(const BufferItem& item);
 
     // Set to NULL to disable the direct-to-app callback window
     status_t setCallbackWindow(sp<ANativeWindow> callbackWindow);
diff --git a/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp b/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp
index b433781..2772267 100644
--- a/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp
@@ -51,7 +51,7 @@
     deleteStream();
 }
 
-void JpegProcessor::onFrameAvailable() {
+void JpegProcessor::onFrameAvailable(const BufferItem& /*item*/) {
     Mutex::Autolock l(mInputMutex);
     if (!mCaptureAvailable) {
         mCaptureAvailable = true;
diff --git a/services/camera/libcameraservice/api1/client2/JpegProcessor.h b/services/camera/libcameraservice/api1/client2/JpegProcessor.h
index b2c05df..2040b30 100644
--- a/services/camera/libcameraservice/api1/client2/JpegProcessor.h
+++ b/services/camera/libcameraservice/api1/client2/JpegProcessor.h
@@ -47,7 +47,7 @@
     ~JpegProcessor();
 
     // CpuConsumer listener implementation
-    void onFrameAvailable();
+    void onFrameAvailable(const BufferItem& item);
 
     status_t updateStream(const Parameters &params);
     status_t deleteStream();
diff --git a/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp b/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp
index 9e7fff8..470624b 100644
--- a/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp
@@ -635,7 +635,7 @@
     return OK;
 }
 
-void StreamingProcessor::onFrameAvailable() {
+void StreamingProcessor::onFrameAvailable(const BufferItem& /*item*/) {
     ATRACE_CALL();
     Mutex::Autolock l(mMutex);
     if (!mRecordingFrameAvailable) {
diff --git a/services/camera/libcameraservice/api1/client2/StreamingProcessor.h b/services/camera/libcameraservice/api1/client2/StreamingProcessor.h
index 8466af4..1d679a4 100644
--- a/services/camera/libcameraservice/api1/client2/StreamingProcessor.h
+++ b/services/camera/libcameraservice/api1/client2/StreamingProcessor.h
@@ -80,7 +80,7 @@
     status_t incrementStreamingIds();
 
     // Callback for new recording frames from HAL
-    virtual void onFrameAvailable();
+    virtual void onFrameAvailable(const BufferItem& item);
     // Callback from stagefright which returns used recording frames
     void releaseRecordingFrame(const sp<IMemory>& mem);
 
diff --git a/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp b/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
index 8f78103..8b7e4b4 100644
--- a/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
@@ -66,7 +66,7 @@
     disconnect();
 }
 
-void ZslProcessor::onFrameAvailable() {
+void ZslProcessor::onFrameAvailable(const BufferItem& /*item*/) {
     Mutex::Autolock l(mInputMutex);
     if (!mZslBufferAvailable) {
         mZslBufferAvailable = true;
diff --git a/services/camera/libcameraservice/api1/client2/ZslProcessor.h b/services/camera/libcameraservice/api1/client2/ZslProcessor.h
index b6533cf..2099c38 100644
--- a/services/camera/libcameraservice/api1/client2/ZslProcessor.h
+++ b/services/camera/libcameraservice/api1/client2/ZslProcessor.h
@@ -53,7 +53,7 @@
     ~ZslProcessor();
 
     // From mZslConsumer
-    virtual void onFrameAvailable();
+    virtual void onFrameAvailable(const BufferItem& item);
     // From FrameProcessor
     virtual void onResultAvailable(const CaptureResult &result);
 
diff --git a/services/camera/libcameraservice/gui/RingBufferConsumer.cpp b/services/camera/libcameraservice/gui/RingBufferConsumer.cpp
index f8562ec..d0f29de 100644
--- a/services/camera/libcameraservice/gui/RingBufferConsumer.cpp
+++ b/services/camera/libcameraservice/gui/RingBufferConsumer.cpp
@@ -268,7 +268,7 @@
     return OK;
 }
 
-void RingBufferConsumer::onFrameAvailable() {
+void RingBufferConsumer::onFrameAvailable(const android::BufferItem& item) {
     status_t err;
 
     {
@@ -321,7 +321,7 @@
         item.mGraphicBuffer = mSlots[item.mBuf].mGraphicBuffer;
     } // end of mMutex lock
 
-    ConsumerBase::onFrameAvailable();
+    ConsumerBase::onFrameAvailable(item);
 }
 
 void RingBufferConsumer::unpinBuffer(const BufferItem& item) {
diff --git a/services/camera/libcameraservice/gui/RingBufferConsumer.h b/services/camera/libcameraservice/gui/RingBufferConsumer.h
index da97a11..90fd734 100644
--- a/services/camera/libcameraservice/gui/RingBufferConsumer.h
+++ b/services/camera/libcameraservice/gui/RingBufferConsumer.h
@@ -165,7 +165,7 @@
   private:
 
     // Override ConsumerBase::onFrameAvailable
-    virtual void onFrameAvailable();
+    virtual void onFrameAvailable(const android::BufferItem& item);
 
     void pinBufferLocked(const BufferItem& item);
     void unpinBuffer(const BufferItem& item);