Merge "Add a BufferItem parameter to onFrameAvailable" into lmp-mr1-dev
diff --git a/camera/VendorTagDescriptor.cpp b/camera/VendorTagDescriptor.cpp
index 0dda6b6..dce313a 100644
--- a/camera/VendorTagDescriptor.cpp
+++ b/camera/VendorTagDescriptor.cpp
@@ -206,7 +206,7 @@
         return res;
     }
 
-    size_t sectionCount;
+    size_t sectionCount = 0;
     if (tagCount > 0) {
         if ((res = parcel->readInt32(reinterpret_cast<int32_t*>(&sectionCount))) != OK) {
             ALOGE("%s: could not read section count for.", __FUNCTION__);
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/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..6f46f9e 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);
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/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp
index dda3657..e4a5674 100644
--- a/media/libmedia/AudioSystem.cpp
+++ b/media/libmedia/AudioSystem.cpp
@@ -543,21 +543,6 @@
     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
 sp<IAudioPolicyService> AudioSystem::gAudioPolicyService;
 sp<AudioSystem::AudioPolicyServiceClient> AudioSystem::gAudioPolicyServiceClient;
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 97c8d84..082a5e1 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -2135,14 +2135,21 @@
 
     // usage to stream type mapping
     switch (aa.usage) {
-    case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY:
+    case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY: {
         // TODO once AudioPolicyManager fully supports audio_attributes_t,
-        //   remove stream change based on phone state
-        if (AudioSystem::getPhoneState() == AUDIO_MODE_RINGTONE) {
+        //   remove stream change based on stream activity
+        bool active;
+        status_t status = AudioSystem::isStreamActive(AUDIO_STREAM_RING, &active, 0);
+        if (status == NO_ERROR && active == true) {
             mStreamType = AUDIO_STREAM_RING;
             break;
         }
-        /// FALL THROUGH
+        status = AudioSystem::isStreamActive(AUDIO_STREAM_ALARM, &active, 0);
+        if (status == NO_ERROR && active == true) {
+            mStreamType = AUDIO_STREAM_ALARM;
+            break;
+        }
+    }    /// FALL THROUGH
     case AUDIO_USAGE_MEDIA:
     case AUDIO_USAGE_GAME:
     case AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
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..0e520a8 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
@@ -1311,11 +1311,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/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/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/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..89181b5 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;
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/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/camera/libcameraservice/api1/client2/Parameters.cpp b/services/camera/libcameraservice/api1/client2/Parameters.cpp
index 7b90d28..42a5507 100644
--- a/services/camera/libcameraservice/api1/client2/Parameters.cpp
+++ b/services/camera/libcameraservice/api1/client2/Parameters.cpp
@@ -2954,6 +2954,10 @@
             staticInfo(ANDROID_SENSOR_INFO_PHYSICAL_SIZE, 2, 2);
     if (!sensorSize.count) return NO_INIT;
 
+    camera_metadata_ro_entry_t pixelArraySize =
+            staticInfo(ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE, 2, 2);
+    if (!pixelArraySize.count) return NO_INIT;
+
     float arrayAspect = static_cast<float>(fastInfo.arrayWidth) /
             fastInfo.arrayHeight;
     float stillAspect = static_cast<float>(pictureWidth) / pictureHeight;
@@ -3003,6 +3007,16 @@
         vertCropFactor = (arrayAspect < stillAspect) ?
                 (arrayAspect / stillAspect) : 1.f;
     }
+
+    /**
+     * Convert the crop factors w.r.t the active array size to the crop factors
+     * w.r.t the pixel array size.
+     */
+    horizCropFactor *= (static_cast<float>(fastInfo.arrayWidth) /
+                            pixelArraySize.data.i32[0]);
+    vertCropFactor *= (static_cast<float>(fastInfo.arrayHeight) /
+                            pixelArraySize.data.i32[1]);
+
     ALOGV("Horiz crop factor: %f, vert crop fact: %f",
             horizCropFactor, vertCropFactor);
     /**