am b27ce2fb: am 416685d0: Merge "Fix format warnings"

* commit 'b27ce2fba0049897558f1f3df9039f443ee4bc88':
  Fix format warnings
diff --git a/drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.cpp b/drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.cpp
index 69fa7a0fc..6efc712 100644
--- a/drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.cpp
+++ b/drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.cpp
@@ -45,7 +45,7 @@
     // MockDrmFactory
     bool MockDrmFactory::isCryptoSchemeSupported(const uint8_t uuid[16])
     {
-        return (!memcmp(uuid, mock_uuid, sizeof(uuid)));
+        return (!memcmp(uuid, mock_uuid, sizeof(mock_uuid)));
     }
 
     bool MockDrmFactory::isContentTypeSupported(const String8 &mimeType)
@@ -65,7 +65,7 @@
     // MockCryptoFactory
     bool MockCryptoFactory::isCryptoSchemeSupported(const uint8_t uuid[16]) const
     {
-        return (!memcmp(uuid, mock_uuid, sizeof(uuid)));
+        return (!memcmp(uuid, mock_uuid, sizeof(mock_uuid)));
     }
 
     status_t MockCryptoFactory::createPlugin(const uint8_t uuid[16], const void *data,
@@ -254,7 +254,9 @@
         return OK;
     }
 
-    status_t MockDrmPlugin::getProvisionRequest(Vector<uint8_t> &request,
+    status_t MockDrmPlugin::getProvisionRequest(String8 const &certType,
+                                                String8 const &certAuthority,
+                                                Vector<uint8_t> &request,
                                                 String8 &defaultUrl)
     {
         Mutex::Autolock lock(mLock);
@@ -282,7 +284,9 @@
         return OK;
     }
 
-    status_t MockDrmPlugin::provideProvisionResponse(Vector<uint8_t> const &response)
+    status_t MockDrmPlugin::provideProvisionResponse(Vector<uint8_t> const &response,
+                                                     Vector<uint8_t> &certificate,
+                                                     Vector<uint8_t> &wrappedKey)
     {
         Mutex::Autolock lock(mLock);
         ALOGD("MockDrmPlugin::provideProvisionResponse(%s)",
@@ -600,6 +604,33 @@
         return OK;
     }
 
+    status_t MockDrmPlugin::signRSA(Vector<uint8_t> const &sessionId,
+                                    String8 const &algorithm,
+                                    Vector<uint8_t> const &message,
+                                    Vector<uint8_t> const &wrappedKey,
+                                    Vector<uint8_t> &signature)
+    {
+        Mutex::Autolock lock(mLock);
+        ALOGD("MockDrmPlugin::signRSA(sessionId=%s, algorithm=%s, keyId=%s, "
+              "message=%s, signature=%s)",
+              vectorToString(sessionId).string(),
+              algorithm.string(),
+              vectorToString(message).string(),
+              vectorToString(wrappedKey).string(),
+              vectorToString(signature).string());
+
+        // Properties used in mock test, set by mock plugin and verifed cts test app
+        //   byte[] wrappedKey         -> mock-wrappedkey
+        //   byte[] message            -> mock-message
+        //   byte[] signature          -> mock-signature
+        mByteArrayProperties.add(String8("mock-sessionid"), sessionId);
+        mStringProperties.add(String8("mock-algorithm"), algorithm);
+        mByteArrayProperties.add(String8("mock-message"), message);
+        mByteArrayProperties.add(String8("mock-wrappedkey"), wrappedKey);
+        mByteArrayProperties.add(String8("mock-signature"), signature);
+        return OK;
+    }
+
     ssize_t MockDrmPlugin::findSession(Vector<uint8_t> const &sessionId) const
     {
         ALOGD("findSession: nsessions=%d, size=%d", mSessions.size(), sessionId.size());
diff --git a/drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.h b/drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.h
index 2297f9b..97d7052 100644
--- a/drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.h
+++ b/drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.h
@@ -76,10 +76,14 @@
         status_t queryKeyStatus(Vector<uint8_t> const &sessionId,
                                 KeyedVector<String8, String8> &infoMap) const;
 
-        status_t getProvisionRequest(Vector<uint8_t> &request,
-                                             String8 &defaultUrl);
+        status_t getProvisionRequest(String8 const &certType,
+                                     String8 const &certAuthority,
+                                     Vector<uint8_t> &request,
+                                     String8 &defaultUrl);
 
-        status_t provideProvisionResponse(Vector<uint8_t> const &response);
+        status_t provideProvisionResponse(Vector<uint8_t> const &response,
+                                          Vector<uint8_t> &certificate,
+                                          Vector<uint8_t> &wrappedKey);
 
         status_t getSecureStops(List<Vector<uint8_t> > &secureStops);
         status_t releaseSecureStops(Vector<uint8_t> const &ssRelease);
@@ -122,6 +126,12 @@
                         Vector<uint8_t> const &signature,
                         bool &match);
 
+        status_t signRSA(Vector<uint8_t> const &sessionId,
+                         String8 const &algorithm,
+                         Vector<uint8_t> const &message,
+                         Vector<uint8_t> const &wrappedKey,
+                         Vector<uint8_t> &signature);
+
     private:
         String8 vectorToString(Vector<uint8_t> const &vector) const;
         String8 arrayToString(uint8_t const *array, size_t len) const;
diff --git a/include/media/IDrm.h b/include/media/IDrm.h
index 5ef26af..32ae28e 100644
--- a/include/media/IDrm.h
+++ b/include/media/IDrm.h
@@ -61,10 +61,14 @@
     virtual status_t queryKeyStatus(Vector<uint8_t> const &sessionId,
                                     KeyedVector<String8, String8> &infoMap) const = 0;
 
-    virtual status_t getProvisionRequest(Vector<uint8_t> &request,
+    virtual status_t getProvisionRequest(String8 const &certType,
+                                         String8 const &certAuthority,
+                                         Vector<uint8_t> &request,
                                          String8 &defaulUrl) = 0;
 
-    virtual status_t provideProvisionResponse(Vector<uint8_t> const &response) = 0;
+    virtual status_t provideProvisionResponse(Vector<uint8_t> const &response,
+                                              Vector<uint8_t> &certificate,
+                                              Vector<uint8_t> &wrappedKey) = 0;
 
     virtual status_t getSecureStops(List<Vector<uint8_t> > &secureStops) = 0;
 
@@ -107,6 +111,12 @@
                             Vector<uint8_t> const &signature,
                             bool &match) = 0;
 
+    virtual status_t signRSA(Vector<uint8_t> const &sessionId,
+                             String8 const &algorithm,
+                             Vector<uint8_t> const &message,
+                             Vector<uint8_t> const &wrappedKey,
+                             Vector<uint8_t> &signature) = 0;
+
     virtual status_t setListener(const sp<IDrmClient>& listener) = 0;
 
 private:
diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h
index 46c62dc..7ba5acc 100644
--- a/include/media/stagefright/ACodec.h
+++ b/include/media/stagefright/ACodec.h
@@ -203,7 +203,6 @@
     unsigned mDequeueCounter;
     bool mStoreMetaDataInOutputBuffers;
     int32_t mMetaDataBuffersToSubmit;
-    size_t mNumUndequeuedBuffers;
 
     int64_t mRepeatFrameDelayUs;
     int64_t mMaxPtsGapUs;
@@ -254,6 +253,8 @@
             int32_t numChannels, int32_t sampleRate, int32_t bitRate,
             int32_t aacProfile, bool isADTS);
 
+    status_t setupAC3Codec(bool encoder, int32_t numChannels, int32_t sampleRate);
+
     status_t selectAudioPortFormat(
             OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE desiredFormat);
 
diff --git a/include/media/stagefright/MediaDefs.h b/include/media/stagefright/MediaDefs.h
index 85693d4..cf5beda 100644
--- a/include/media/stagefright/MediaDefs.h
+++ b/include/media/stagefright/MediaDefs.h
@@ -44,6 +44,7 @@
 extern const char *MEDIA_MIMETYPE_AUDIO_FLAC;
 extern const char *MEDIA_MIMETYPE_AUDIO_AAC_ADTS;
 extern const char *MEDIA_MIMETYPE_AUDIO_MSGSM;
+extern const char *MEDIA_MIMETYPE_AUDIO_AC3;
 
 extern const char *MEDIA_MIMETYPE_CONTAINER_MPEG4;
 extern const char *MEDIA_MIMETYPE_CONTAINER_WAV;
diff --git a/include/media/stagefright/OMXCodec.h b/include/media/stagefright/OMXCodec.h
index daaf20f..5121c17 100644
--- a/include/media/stagefright/OMXCodec.h
+++ b/include/media/stagefright/OMXCodec.h
@@ -248,6 +248,8 @@
             int32_t numChannels, int32_t sampleRate, int32_t bitRate,
             int32_t aacProfile, bool isADTS);
 
+    status_t setAC3Format(int32_t numChannels, int32_t sampleRate);
+
     void setG711Format(int32_t numChannels);
 
     status_t setVideoPortFormatType(
diff --git a/media/libmedia/IDrm.cpp b/media/libmedia/IDrm.cpp
index f7a9a75..f1a6a9f 100644
--- a/media/libmedia/IDrm.cpp
+++ b/media/libmedia/IDrm.cpp
@@ -51,6 +51,7 @@
     ENCRYPT,
     DECRYPT,
     SIGN,
+    SIGN_RSA,
     VERIFY,
     SET_LISTENER
 };
@@ -196,11 +197,15 @@
         return reply.readInt32();
     }
 
-    virtual status_t getProvisionRequest(Vector<uint8_t> &request,
+    virtual status_t getProvisionRequest(String8 const &certType,
+                                         String8 const &certAuthority,
+                                         Vector<uint8_t> &request,
                                          String8 &defaultUrl) {
         Parcel data, reply;
         data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
 
+        data.writeString8(certType);
+        data.writeString8(certAuthority);
         remote()->transact(GET_PROVISION_REQUEST, data, &reply);
 
         readVector(reply, request);
@@ -209,13 +214,18 @@
         return reply.readInt32();
     }
 
-    virtual status_t provideProvisionResponse(Vector<uint8_t> const &response) {
+    virtual status_t provideProvisionResponse(Vector<uint8_t> const &response,
+                                              Vector<uint8_t> &certificate,
+                                              Vector<uint8_t> &wrappedKey) {
         Parcel data, reply;
         data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
 
         writeVector(data, response);
         remote()->transact(PROVIDE_PROVISION_RESPONSE, data, &reply);
 
+        readVector(reply, certificate);
+        readVector(reply, wrappedKey);
+
         return reply.readInt32();
     }
 
@@ -386,6 +396,25 @@
         return reply.readInt32();
     }
 
+    virtual status_t signRSA(Vector<uint8_t> const &sessionId,
+                             String8 const &algorithm,
+                             Vector<uint8_t> const &message,
+                             Vector<uint8_t> const &wrappedKey,
+                             Vector<uint8_t> &signature) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
+
+        writeVector(data, sessionId);
+        data.writeString8(algorithm);
+        writeVector(data, message);
+        writeVector(data, wrappedKey);
+
+        remote()->transact(SIGN_RSA, data, &reply);
+        readVector(reply, signature);
+
+        return reply.readInt32();
+    }
+
     virtual status_t setListener(const sp<IDrmClient>& listener) {
         Parcel data, reply;
         data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
@@ -563,9 +592,13 @@
         case GET_PROVISION_REQUEST:
         {
             CHECK_INTERFACE(IDrm, data, reply);
+            String8 certType = data.readString8();
+            String8 certAuthority = data.readString8();
+
             Vector<uint8_t> request;
             String8 defaultUrl;
-            status_t result = getProvisionRequest(request, defaultUrl);
+            status_t result = getProvisionRequest(certType, certAuthority,
+                                                  request, defaultUrl);
             writeVector(reply, request);
             reply->writeString8(defaultUrl);
             reply->writeInt32(result);
@@ -576,8 +609,13 @@
         {
             CHECK_INTERFACE(IDrm, data, reply);
             Vector<uint8_t> response;
+            Vector<uint8_t> certificate;
+            Vector<uint8_t> wrappedKey;
             readVector(data, response);
-            reply->writeInt32(provideProvisionResponse(response));
+            status_t result = provideProvisionResponse(response, certificate, wrappedKey);
+            writeVector(reply, certificate);
+            writeVector(reply, wrappedKey);
+            reply->writeInt32(result);
             return OK;
         }
 
@@ -725,6 +763,20 @@
             return OK;
         }
 
+        case SIGN_RSA:
+        {
+            CHECK_INTERFACE(IDrm, data, reply);
+            Vector<uint8_t> sessionId, message, wrappedKey, signature;
+            readVector(data, sessionId);
+            String8 algorithm = data.readString8();
+            readVector(data, message);
+            readVector(data, wrappedKey);
+            uint32_t result = signRSA(sessionId, algorithm, message, wrappedKey, signature);
+            writeVector(reply, signature);
+            reply->writeInt32(result);
+            return OK;
+        }
+
     case SET_LISTENER: {
         CHECK_INTERFACE(IDrm, data, reply);
         sp<IDrmClient> listener =
diff --git a/media/libmediaplayerservice/Drm.cpp b/media/libmediaplayerservice/Drm.cpp
index eebcb79..d50037f 100644
--- a/media/libmediaplayerservice/Drm.cpp
+++ b/media/libmediaplayerservice/Drm.cpp
@@ -28,9 +28,21 @@
 #include <media/stagefright/foundation/AString.h>
 #include <media/stagefright/foundation/hexdump.h>
 #include <media/stagefright/MediaErrors.h>
+#include <binder/IServiceManager.h>
+#include <binder/IPCThreadState.h>
 
 namespace android {
 
+static bool checkPermission(const char* permissionString) {
+#ifndef HAVE_ANDROID_OS
+    return true;
+#endif
+    if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
+    bool ok = checkCallingPermission(String16(permissionString));
+    if (!ok) ALOGE("Request requires %s", permissionString);
+    return ok;
+}
+
 KeyedVector<Vector<uint8_t>, String8> Drm::mUUIDToLibraryPathMap;
 KeyedVector<String8, wp<SharedLibrary> > Drm::mLibraryPathToOpenLibraryMap;
 Mutex Drm::mMapLock;
@@ -373,7 +385,8 @@
     return mPlugin->queryKeyStatus(sessionId, infoMap);
 }
 
-status_t Drm::getProvisionRequest(Vector<uint8_t> &request, String8 &defaultUrl) {
+status_t Drm::getProvisionRequest(String8 const &certType, String8 const &certAuthority,
+                                  Vector<uint8_t> &request, String8 &defaultUrl) {
     Mutex::Autolock autoLock(mLock);
 
     if (mInitCheck != OK) {
@@ -384,10 +397,13 @@
         return -EINVAL;
     }
 
-    return mPlugin->getProvisionRequest(request, defaultUrl);
+    return mPlugin->getProvisionRequest(certType, certAuthority,
+                                        request, defaultUrl);
 }
 
-status_t Drm::provideProvisionResponse(Vector<uint8_t> const &response) {
+status_t Drm::provideProvisionResponse(Vector<uint8_t> const &response,
+                                       Vector<uint8_t> &certificate,
+                                       Vector<uint8_t> &wrappedKey) {
     Mutex::Autolock autoLock(mLock);
 
     if (mInitCheck != OK) {
@@ -398,7 +414,7 @@
         return -EINVAL;
     }
 
-    return mPlugin->provideProvisionResponse(response);
+    return mPlugin->provideProvisionResponse(response, certificate, wrappedKey);
 }
 
 
@@ -589,6 +605,28 @@
     return mPlugin->verify(sessionId, keyId, message, signature, match);
 }
 
+status_t Drm::signRSA(Vector<uint8_t> const &sessionId,
+                      String8 const &algorithm,
+                      Vector<uint8_t> const &message,
+                      Vector<uint8_t> const &wrappedKey,
+                      Vector<uint8_t> &signature) {
+    Mutex::Autolock autoLock(mLock);
+
+    if (mInitCheck != OK) {
+        return mInitCheck;
+    }
+
+    if (mPlugin == NULL) {
+        return -EINVAL;
+    }
+
+    if (!checkPermission("android.permission.ACCESS_DRM_CERTIFICATES")) {
+        return -EPERM;
+    }
+
+    return mPlugin->signRSA(sessionId, algorithm, message, wrappedKey, signature);
+}
+
 void Drm::binderDied(const wp<IBinder> &the_late_who)
 {
     delete mPlugin;
diff --git a/media/libmediaplayerservice/Drm.h b/media/libmediaplayerservice/Drm.h
index 119fd50..3d4b0fc 100644
--- a/media/libmediaplayerservice/Drm.h
+++ b/media/libmediaplayerservice/Drm.h
@@ -66,10 +66,14 @@
     virtual status_t queryKeyStatus(Vector<uint8_t> const &sessionId,
                                     KeyedVector<String8, String8> &infoMap) const;
 
-    virtual status_t getProvisionRequest(Vector<uint8_t> &request,
+    virtual status_t getProvisionRequest(String8 const &certType,
+                                         String8 const &certAuthority,
+                                         Vector<uint8_t> &request,
                                          String8 &defaulUrl);
 
-    virtual status_t provideProvisionResponse(Vector<uint8_t> const &response);
+    virtual status_t provideProvisionResponse(Vector<uint8_t> const &response,
+                                              Vector<uint8_t> &certificate,
+                                              Vector<uint8_t> &wrappedKey);
 
     virtual status_t getSecureStops(List<Vector<uint8_t> > &secureStops);
 
@@ -111,6 +115,12 @@
                             Vector<uint8_t> const &signature,
                             bool &match);
 
+    virtual status_t signRSA(Vector<uint8_t> const &sessionId,
+                             String8 const &algorithm,
+                             Vector<uint8_t> const &message,
+                             Vector<uint8_t> const &wrappedKey,
+                             Vector<uint8_t> &signature);
+
     virtual status_t setListener(const sp<IDrmClient>& listener);
 
     virtual void sendEvent(DrmPlugin::EventType eventType, int extra,
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 2d04bbb..9e1c62a 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -35,7 +35,9 @@
 
 #include <media/hardware/HardwareAPI.h>
 
+#include <OMX_AudioExt.h>
 #include <OMX_Component.h>
+#include <OMX_IndexExt.h>
 
 #include "include/avc_utils.h"
 
@@ -638,34 +640,18 @@
         return err;
     }
 
-    // FIXME: assume that surface is controlled by app (native window
-    // returns the number for the case when surface is not controlled by app)
-    // FIXME2: This means that minUndeqeueudBufs can be 1 larger than reported
-    // For now, try to allocate 1 more buffer, but don't fail if unsuccessful
-
-    // Use conservative allocation while also trying to reduce starvation
-    //
-    // 1. allocate at least nBufferCountMin + minUndequeuedBuffers - that is the
-    //    minimum needed for the consumer to be able to work
-    // 2. try to allocate two (2) additional buffers to reduce starvation from
-    //    the consumer
-    //    plus an extra buffer to account for incorrect minUndequeuedBufs
-    for (OMX_U32 extraBuffers = 2 + 1; /* condition inside loop */; extraBuffers--) {
-        OMX_U32 newBufferCount =
-            def.nBufferCountMin + *minUndequeuedBuffers + extraBuffers;
+    // XXX: Is this the right logic to use?  It's not clear to me what the OMX
+    // buffer counts refer to - how do they account for the renderer holding on
+    // to buffers?
+    if (def.nBufferCountActual < def.nBufferCountMin + *minUndequeuedBuffers) {
+        OMX_U32 newBufferCount = def.nBufferCountMin + *minUndequeuedBuffers;
         def.nBufferCountActual = newBufferCount;
         err = mOMX->setParameter(
                 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
 
-        if (err == OK) {
-            *minUndequeuedBuffers += extraBuffers;
-            break;
-        }
-
-        ALOGW("[%s] setting nBufferCountActual to %lu failed: %d",
-                mComponentName.c_str(), newBufferCount, err);
-        /* exit condition */
-        if (extraBuffers == 0) {
+        if (err != OK) {
+            ALOGE("[%s] setting nBufferCountActual to %lu failed: %d",
+                    mComponentName.c_str(), newBufferCount, err);
             return err;
         }
     }
@@ -690,7 +676,6 @@
             &bufferCount, &bufferSize, &minUndequeuedBuffers);
     if (err != 0)
         return err;
-    mNumUndequeuedBuffers = minUndequeuedBuffers;
 
     ALOGV("[%s] Allocating %lu buffers from a native window of size %lu on "
          "output port",
@@ -756,7 +741,6 @@
             &bufferCount, &bufferSize, &minUndequeuedBuffers);
     if (err != 0)
         return err;
-    mNumUndequeuedBuffers = minUndequeuedBuffers;
 
     ALOGV("[%s] Allocating %lu meta buffers on output port",
          mComponentName.c_str(), bufferCount);
@@ -997,6 +981,10 @@
             "audio_decoder.flac", "audio_encoder.flac" },
         { MEDIA_MIMETYPE_AUDIO_MSGSM,
             "audio_decoder.gsm", "audio_encoder.gsm" },
+        { MEDIA_MIMETYPE_VIDEO_MPEG2,
+            "video_decoder.mpeg2", "video_encoder.mpeg2" },
+        { MEDIA_MIMETYPE_AUDIO_AC3,
+            "audio_decoder.ac3", "audio_encoder.ac3" },
     };
 
     static const size_t kNumMimeToRole =
@@ -1295,6 +1283,15 @@
         } else {
             err = setupRawAudioFormat(kPortIndexInput, sampleRate, numChannels);
         }
+    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AC3)) {
+        int32_t numChannels;
+        int32_t sampleRate;
+        if (!msg->findInt32("channel-count", &numChannels)
+                || !msg->findInt32("sample-rate", &sampleRate)) {
+            err = INVALID_OPERATION;
+        } else {
+            err = setupAC3Codec(encoder, numChannels, sampleRate);
+        }
     }
 
     if (err != OK) {
@@ -1491,6 +1488,44 @@
             mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
 }
 
+status_t ACodec::setupAC3Codec(
+        bool encoder, int32_t numChannels, int32_t sampleRate) {
+    status_t err = setupRawAudioFormat(
+            encoder ? kPortIndexInput : kPortIndexOutput, sampleRate, numChannels);
+
+    if (err != OK) {
+        return err;
+    }
+
+    if (encoder) {
+        ALOGW("AC3 encoding is not supported.");
+        return INVALID_OPERATION;
+    }
+
+    OMX_AUDIO_PARAM_ANDROID_AC3TYPE def;
+    InitOMXParams(&def);
+    def.nPortIndex = kPortIndexInput;
+
+    err = mOMX->getParameter(
+            mNode,
+            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3,
+            &def,
+            sizeof(def));
+
+    if (err != OK) {
+        return err;
+    }
+
+    def.nChannels = numChannels;
+    def.nSampleRate = sampleRate;
+
+    return mOMX->setParameter(
+            mNode,
+            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3,
+            &def,
+            sizeof(def));
+}
+
 static OMX_AUDIO_AMRBANDMODETYPE pickModeFromBitRate(
         bool isAMRWB, int32_t bps) {
     if (isAMRWB) {
@@ -2447,7 +2482,19 @@
         return;
     }
 
-    while (countBuffersOwnedByNativeWindow() > mNumUndequeuedBuffers
+    int minUndequeuedBufs = 0;
+    status_t err = mNativeWindow->query(
+            mNativeWindow.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
+            &minUndequeuedBufs);
+
+    if (err != OK) {
+        ALOGE("[%s] NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d)",
+                mComponentName.c_str(), strerror(-err), -err);
+
+        minUndequeuedBufs = 0;
+    }
+
+    while (countBuffersOwnedByNativeWindow() > (size_t)minUndequeuedBufs
             && dequeueBufferFromNativeWindow() != NULL) {
         // these buffers will be submitted as regular buffers; account for this
         if (mStoreMetaDataInOutputBuffers && mMetaDataBuffersToSubmit > 0) {
@@ -2573,7 +2620,7 @@
         {
             OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio;
 
-            switch (audioDef->eEncoding) {
+            switch ((int)audioDef->eEncoding) {
                 case OMX_AUDIO_CodingPCM:
                 {
                     OMX_AUDIO_PARAM_PCMMODETYPE params;
@@ -2679,6 +2726,24 @@
                     break;
                 }
 
+                case OMX_AUDIO_CodingAndroidAC3:
+                {
+                    OMX_AUDIO_PARAM_ANDROID_AC3TYPE params;
+                    InitOMXParams(&params);
+                    params.nPortIndex = kPortIndexOutput;
+
+                    CHECK_EQ((status_t)OK, mOMX->getParameter(
+                            mNode,
+                            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3,
+                            &params,
+                            sizeof(params)));
+
+                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AC3);
+                    notify->setInt32("channel-count", params.nChannels);
+                    notify->setInt32("sample-rate", params.nSampleRate);
+                    break;
+                }
+
                 default:
                     TRESPASS();
             }
diff --git a/media/libstagefright/MediaDefs.cpp b/media/libstagefright/MediaDefs.cpp
index b5d4e44..340cba7 100644
--- a/media/libstagefright/MediaDefs.cpp
+++ b/media/libstagefright/MediaDefs.cpp
@@ -42,6 +42,7 @@
 const char *MEDIA_MIMETYPE_AUDIO_FLAC = "audio/flac";
 const char *MEDIA_MIMETYPE_AUDIO_AAC_ADTS = "audio/aac-adts";
 const char *MEDIA_MIMETYPE_AUDIO_MSGSM = "audio/gsm";
+const char *MEDIA_MIMETYPE_AUDIO_AC3 = "audio/ac3";
 
 const char *MEDIA_MIMETYPE_CONTAINER_MPEG4 = "video/mp4";
 const char *MEDIA_MIMETYPE_CONTAINER_WAV = "audio/x-wav";
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 450fb3b..96c5a32 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -42,7 +42,9 @@
 #include <utils/Vector.h>
 
 #include <OMX_Audio.h>
+#include <OMX_AudioExt.h>
 #include <OMX_Component.h>
+#include <OMX_IndexExt.h>
 
 #include "include/avc_utils.h"
 
@@ -94,7 +96,6 @@
 
 #define CODEC_LOGI(x, ...) ALOGI("[%s] "x, mComponentName, ##__VA_ARGS__)
 #define CODEC_LOGV(x, ...) ALOGV("[%s] "x, mComponentName, ##__VA_ARGS__)
-#define CODEC_LOGW(x, ...) ALOGW("[%s] "x, mComponentName, ##__VA_ARGS__)
 #define CODEC_LOGE(x, ...) ALOGE("[%s] "x, mComponentName, ##__VA_ARGS__)
 
 struct OMXCodecObserver : public BnOMXObserver {
@@ -531,6 +532,17 @@
                     sampleRate,
                     numChannels);
         }
+    } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AC3, mMIME)) {
+        int32_t numChannels;
+        int32_t sampleRate;
+        CHECK(meta->findInt32(kKeyChannelCount, &numChannels));
+        CHECK(meta->findInt32(kKeySampleRate, &sampleRate));
+
+        status_t err = setAC3Format(numChannels, sampleRate);
+        if (err != OK) {
+            CODEC_LOGE("setAC3Format() failed (err = %d)", err);
+            return err;
+        }
     } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_G711_ALAW, mMIME)
             || !strcasecmp(MEDIA_MIMETYPE_AUDIO_G711_MLAW, mMIME)) {
         // These are PCM-like formats with a fixed sample rate but
@@ -1397,6 +1409,10 @@
             "audio_decoder.flac", "audio_encoder.flac" },
         { MEDIA_MIMETYPE_AUDIO_MSGSM,
             "audio_decoder.gsm", "audio_encoder.gsm" },
+        { MEDIA_MIMETYPE_VIDEO_MPEG2,
+            "video_decoder.mpeg2", "video_encoder.mpeg2" },
+        { MEDIA_MIMETYPE_AUDIO_AC3,
+            "audio_decoder.ac3", "audio_encoder.ac3" },
     };
 
     static const size_t kNumMimeToRole =
@@ -1780,42 +1796,21 @@
                 strerror(-err), -err);
         return err;
     }
-    // FIXME: assume that surface is controlled by app (native window
-    // returns the number for the case when surface is not controlled by app)
-    // FIXME2: This means that minUndeqeueudBufs can be 1 larger than reported
-    // For now, try to allocate 1 more buffer, but don't fail if unsuccessful
 
-    // Use conservative allocation while also trying to reduce starvation
-    //
-    // 1. allocate at least nBufferCountMin + minUndequeuedBuffers - that is the
-    //    minimum needed for the consumer to be able to work
-    // 2. try to allocate two (2) additional buffers to reduce starvation from
-    //    the consumer
-    //    plus an extra buffer to account for incorrect minUndequeuedBufs
-    CODEC_LOGI("OMX-buffers: min=%u actual=%u undeq=%d+1",
-            def.nBufferCountMin, def.nBufferCountActual, minUndequeuedBufs);
-
-    for (OMX_U32 extraBuffers = 2 + 1; /* condition inside loop */; extraBuffers--) {
-        OMX_U32 newBufferCount =
-            def.nBufferCountMin + minUndequeuedBufs + extraBuffers;
+    // XXX: Is this the right logic to use?  It's not clear to me what the OMX
+    // buffer counts refer to - how do they account for the renderer holding on
+    // to buffers?
+    if (def.nBufferCountActual < def.nBufferCountMin + minUndequeuedBufs) {
+        OMX_U32 newBufferCount = def.nBufferCountMin + minUndequeuedBufs;
         def.nBufferCountActual = newBufferCount;
         err = mOMX->setParameter(
                 mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
-
-        if (err == OK) {
-            minUndequeuedBufs += extraBuffers;
-            break;
-        }
-
-        CODEC_LOGW("setting nBufferCountActual to %lu failed: %d",
-                newBufferCount, err);
-        /* exit condition */
-        if (extraBuffers == 0) {
+        if (err != OK) {
+            CODEC_LOGE("setting nBufferCountActual to %lu failed: %d",
+                    newBufferCount, err);
             return err;
         }
     }
-    CODEC_LOGI("OMX-buffers: min=%u actual=%u undeq=%d+1",
-            def.nBufferCountMin, def.nBufferCountActual, minUndequeuedBufs);
 
     err = native_window_set_buffer_count(
             mNativeWindow.get(), def.nBufferCountActual);
@@ -3513,6 +3508,31 @@
     return OK;
 }
 
+status_t OMXCodec::setAC3Format(int32_t numChannels, int32_t sampleRate) {
+    OMX_AUDIO_PARAM_ANDROID_AC3TYPE def;
+    InitOMXParams(&def);
+    def.nPortIndex = kPortIndexInput;
+
+    status_t err = mOMX->getParameter(
+            mNode,
+            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3,
+            &def,
+            sizeof(def));
+
+    if (err != OK) {
+        return err;
+    }
+
+    def.nChannels = numChannels;
+    def.nSampleRate = sampleRate;
+
+    return mOMX->setParameter(
+            mNode,
+            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3,
+            &def,
+            sizeof(def));
+}
+
 void OMXCodec::setG711Format(int32_t numChannels) {
     CHECK(!mIsEncoder);
     setRawAudioFormat(kPortIndexInput, 8000, numChannels);
@@ -4446,6 +4466,17 @@
                 mOutputFormat->setInt32(kKeyChannelCount, numChannels);
                 mOutputFormat->setInt32(kKeySampleRate, sampleRate);
                 mOutputFormat->setInt32(kKeyBitRate, bitRate);
+            } else if (audio_def->eEncoding ==
+                    (OMX_AUDIO_CODINGTYPE)OMX_AUDIO_CodingAndroidAC3) {
+                mOutputFormat->setCString(
+                        kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AC3);
+                int32_t numChannels, sampleRate, bitRate;
+                inputFormat->findInt32(kKeyChannelCount, &numChannels);
+                inputFormat->findInt32(kKeySampleRate, &sampleRate);
+                inputFormat->findInt32(kKeyBitRate, &bitRate);
+                mOutputFormat->setInt32(kKeyChannelCount, numChannels);
+                mOutputFormat->setInt32(kKeySampleRate, sampleRate);
+                mOutputFormat->setInt32(kKeyBitRate, bitRate);
             } else {
                 CHECK(!"Should not be here. Unknown audio encoding.");
             }
diff --git a/media/libstagefright/mpeg2ts/ATSParser.cpp b/media/libstagefright/mpeg2ts/ATSParser.cpp
index 2c8cf8d..d1afd8b 100644
--- a/media/libstagefright/mpeg2ts/ATSParser.cpp
+++ b/media/libstagefright/mpeg2ts/ATSParser.cpp
@@ -508,6 +508,11 @@
                     ElementaryStreamQueue::PCM_AUDIO);
             break;
 
+        case STREAMTYPE_AC3:
+            mQueue = new ElementaryStreamQueue(
+                    ElementaryStreamQueue::AC3);
+            break;
+
         default:
             break;
     }
@@ -616,6 +621,7 @@
         case STREAMTYPE_MPEG2_AUDIO:
         case STREAMTYPE_MPEG2_AUDIO_ADTS:
         case STREAMTYPE_PCM_AUDIO:
+        case STREAMTYPE_AC3:
             return true;
 
         default:
diff --git a/media/libstagefright/mpeg2ts/ATSParser.h b/media/libstagefright/mpeg2ts/ATSParser.h
index 8a80069..86b025f 100644
--- a/media/libstagefright/mpeg2ts/ATSParser.h
+++ b/media/libstagefright/mpeg2ts/ATSParser.h
@@ -89,6 +89,10 @@
         STREAMTYPE_MPEG2_AUDIO_ADTS     = 0x0f,
         STREAMTYPE_MPEG4_VIDEO          = 0x10,
         STREAMTYPE_H264                 = 0x1b,
+
+        // From ATSC A/53 Part 3:2009, 6.7.1
+        STREAMTYPE_AC3                  = 0x81,
+
         STREAMTYPE_PCM_AUDIO            = 0x83,
     };
 
diff --git a/media/libstagefright/mpeg2ts/ESQueue.cpp b/media/libstagefright/mpeg2ts/ESQueue.cpp
index 1960b27..e9252cc 100644
--- a/media/libstagefright/mpeg2ts/ESQueue.cpp
+++ b/media/libstagefright/mpeg2ts/ESQueue.cpp
@@ -57,6 +57,122 @@
     }
 }
 
+// Parse AC3 header assuming the current ptr is start position of syncframe,
+// update metadata only applicable, and return the payload size
+static unsigned parseAC3SyncFrame(
+        const uint8_t *ptr, size_t size, sp<MetaData> *metaData) {
+    static const unsigned channelCountTable[] = {2, 1, 2, 3, 3, 4, 4, 5};
+    static const unsigned samplingRateTable[] = {48000, 44100, 32000};
+    static const unsigned rates[] = {32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256,
+            320, 384, 448, 512, 576, 640};
+
+    static const unsigned frameSizeTable[19][3] = {
+        { 64, 69, 96 },
+        { 80, 87, 120 },
+        { 96, 104, 144 },
+        { 112, 121, 168 },
+        { 128, 139, 192 },
+        { 160, 174, 240 },
+        { 192, 208, 288 },
+        { 224, 243, 336 },
+        { 256, 278, 384 },
+        { 320, 348, 480 },
+        { 384, 417, 576 },
+        { 448, 487, 672 },
+        { 512, 557, 768 },
+        { 640, 696, 960 },
+        { 768, 835, 1152 },
+        { 896, 975, 1344 },
+        { 1024, 1114, 1536 },
+        { 1152, 1253, 1728 },
+        { 1280, 1393, 1920 },
+    };
+
+    ABitReader bits(ptr, size);
+    unsigned syncStartPos = 0;  // in bytes
+    if (bits.numBitsLeft() < 16) {
+        return 0;
+    }
+    if (bits.getBits(16) != 0x0B77) {
+        return 0;
+    }
+
+    if (bits.numBitsLeft() < 16 + 2 + 6 + 5 + 3 + 3) {
+        ALOGV("Not enough bits left for further parsing");
+        return 0;
+    }
+    bits.skipBits(16);  // crc1
+
+    unsigned fscod = bits.getBits(2);
+    if (fscod == 3) {
+        ALOGW("Incorrect fscod in AC3 header");
+        return 0;
+    }
+
+    unsigned frmsizecod = bits.getBits(6);
+    if (frmsizecod > 37) {
+        ALOGW("Incorrect frmsizecod in AC3 header");
+        return 0;
+    }
+
+    unsigned bsid = bits.getBits(5);
+    if (bsid > 8) {
+        ALOGW("Incorrect bsid in AC3 header. Possibly E-AC-3?");
+        return 0;
+    }
+
+    unsigned bsmod = bits.getBits(3);
+    unsigned acmod = bits.getBits(3);
+    unsigned cmixlev = 0;
+    unsigned surmixlev = 0;
+    unsigned dsurmod = 0;
+
+    if ((acmod & 1) > 0 && acmod != 1) {
+        if (bits.numBitsLeft() < 2) {
+            return 0;
+        }
+        cmixlev = bits.getBits(2);
+    }
+    if ((acmod & 4) > 0) {
+        if (bits.numBitsLeft() < 2) {
+            return 0;
+        }
+        surmixlev = bits.getBits(2);
+    }
+    if (acmod == 2) {
+        if (bits.numBitsLeft() < 2) {
+            return 0;
+        }
+        dsurmod = bits.getBits(2);
+    }
+
+    if (bits.numBitsLeft() < 1) {
+        return 0;
+    }
+    unsigned lfeon = bits.getBits(1);
+
+    unsigned samplingRate = samplingRateTable[fscod];
+    unsigned payloadSize = frameSizeTable[frmsizecod >> 1][fscod];
+    if (fscod == 1) {
+        payloadSize += frmsizecod & 1;
+    }
+    payloadSize <<= 1;  // convert from 16-bit words to bytes
+
+    unsigned channelCount = channelCountTable[acmod] + lfeon;
+
+    if (metaData != NULL) {
+        (*metaData)->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AC3);
+        (*metaData)->setInt32(kKeyChannelCount, channelCount);
+        (*metaData)->setInt32(kKeySampleRate, samplingRate);
+    }
+
+    return payloadSize;
+}
+
+static bool IsSeeminglyValidAC3Header(const uint8_t *ptr, size_t size) {
+    return parseAC3SyncFrame(ptr, size, NULL) > 0;
+}
+
 static bool IsSeeminglyValidADTSHeader(const uint8_t *ptr, size_t size) {
     if (size < 3) {
         // Not enough data to verify header.
@@ -225,6 +341,33 @@
                 break;
             }
 
+            case AC3:
+            {
+                uint8_t *ptr = (uint8_t *)data;
+
+                ssize_t startOffset = -1;
+                for (size_t i = 0; i < size; ++i) {
+                    if (IsSeeminglyValidAC3Header(&ptr[i], size - i)) {
+                        startOffset = i;
+                        break;
+                    }
+                }
+
+                if (startOffset < 0) {
+                    return ERROR_MALFORMED;
+                }
+
+                if (startOffset > 0) {
+                    ALOGI("found something resembling an AC3 syncword at "
+                          "offset %d",
+                          startOffset);
+                }
+
+                data = &ptr[startOffset];
+                size -= startOffset;
+                break;
+            }
+
             case MPEG_AUDIO:
             {
                 uint8_t *ptr = (uint8_t *)data;
@@ -329,6 +472,8 @@
             return dequeueAccessUnitH264();
         case AAC:
             return dequeueAccessUnitAAC();
+        case AC3:
+            return dequeueAccessUnitAC3();
         case MPEG_VIDEO:
             return dequeueAccessUnitMPEGVideo();
         case MPEG4_VIDEO:
@@ -341,6 +486,51 @@
     }
 }
 
+sp<ABuffer> ElementaryStreamQueue::dequeueAccessUnitAC3() {
+    unsigned syncStartPos = 0;  // in bytes
+    unsigned payloadSize = 0;
+    sp<MetaData> format = new MetaData;
+    while (true) {
+        if (syncStartPos + 2 >= mBuffer->size()) {
+            return NULL;
+        }
+
+        payloadSize = parseAC3SyncFrame(
+                mBuffer->data() + syncStartPos,
+                mBuffer->size() - syncStartPos,
+                &format);
+        if (payloadSize > 0) {
+            break;
+        }
+        ++syncStartPos;
+    }
+
+    if (mBuffer->size() < syncStartPos + payloadSize) {
+        ALOGV("Not enough buffer size for AC3");
+        return NULL;
+    }
+
+    if (mFormat == NULL) {
+        mFormat = format;
+    }
+
+    sp<ABuffer> accessUnit = new ABuffer(syncStartPos + payloadSize);
+    memcpy(accessUnit->data(), mBuffer->data(), syncStartPos + payloadSize);
+
+    int64_t timeUs = fetchTimestamp(syncStartPos + payloadSize);
+    CHECK_GE(timeUs, 0ll);
+    accessUnit->meta()->setInt64("timeUs", timeUs);
+
+    memmove(
+            mBuffer->data(),
+            mBuffer->data() + syncStartPos + payloadSize,
+            mBuffer->size() - syncStartPos - payloadSize);
+
+    mBuffer->setRange(0, mBuffer->size() - syncStartPos - payloadSize);
+
+    return accessUnit;
+}
+
 sp<ABuffer> ElementaryStreamQueue::dequeueAccessUnitPCMAudio() {
     if (mBuffer->size() < 4) {
         return NULL;
diff --git a/media/libstagefright/mpeg2ts/ESQueue.h b/media/libstagefright/mpeg2ts/ESQueue.h
index 66a8087..a2cca77 100644
--- a/media/libstagefright/mpeg2ts/ESQueue.h
+++ b/media/libstagefright/mpeg2ts/ESQueue.h
@@ -32,6 +32,7 @@
     enum Mode {
         H264,
         AAC,
+        AC3,
         MPEG_AUDIO,
         MPEG_VIDEO,
         MPEG4_VIDEO,
@@ -67,6 +68,7 @@
 
     sp<ABuffer> dequeueAccessUnitH264();
     sp<ABuffer> dequeueAccessUnitAAC();
+    sp<ABuffer> dequeueAccessUnitAC3();
     sp<ABuffer> dequeueAccessUnitMPEGAudio();
     sp<ABuffer> dequeueAccessUnitMPEGVideo();
     sp<ABuffer> dequeueAccessUnitMPEG4Video();