am 9e57a4df: am 7b445dd7: am 49b49f8f: Added include/private/hwui/DrawGlInfo.h

* commit '9e57a4df48558f4d4c12a98b9720f7603803faca':
  Added include/private/hwui/DrawGlInfo.h
diff --git a/camera/Android.mk b/camera/Android.mk
index 2f16923..b17b3d2 100644
--- a/camera/Android.mk
+++ b/camera/Android.mk
@@ -13,7 +13,6 @@
 	libutils \
 	libbinder \
 	libhardware \
-	libsurfaceflinger_client \
 	libui \
 	libgui
 
diff --git a/camera/Camera.cpp b/camera/Camera.cpp
index e288312..5eb48da 100644
--- a/camera/Camera.cpp
+++ b/camera/Camera.cpp
@@ -205,22 +205,6 @@
     return c->startPreview();
 }
 
-int32_t Camera::getNumberOfVideoBuffers() const
-{
-    LOGV("getNumberOfVideoBuffers");
-    sp <ICamera> c = mCamera;
-    if (c == 0) return 0;
-    return c->getNumberOfVideoBuffers();
-}
-
-sp<IMemory> Camera::getVideoBuffer(int32_t index) const
-{
-    LOGV("getVideoBuffer: %d", index);
-    sp <ICamera> c = mCamera;
-    if (c == 0) return 0;
-    return c->getVideoBuffer(index);
-}
-
 status_t Camera::storeMetaDataInBuffers(bool enabled)
 {
     LOGV("storeMetaDataInBuffers: %s",
diff --git a/camera/ICamera.cpp b/camera/ICamera.cpp
index 931b57d..5f6e5ef 100644
--- a/camera/ICamera.cpp
+++ b/camera/ICamera.cpp
@@ -46,8 +46,6 @@
     STOP_RECORDING,
     RECORDING_ENABLED,
     RELEASE_RECORDING_FRAME,
-    GET_NUM_VIDEO_BUFFERS,
-    GET_VIDEO_BUFFER,
     STORE_META_DATA_IN_BUFFERS,
 };
 
@@ -149,27 +147,6 @@
         remote()->transact(RELEASE_RECORDING_FRAME, data, &reply);
     }
 
-    int32_t getNumberOfVideoBuffers() const
-    {
-        LOGV("getNumberOfVideoBuffers");
-        Parcel data, reply;
-        data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
-        remote()->transact(GET_NUM_VIDEO_BUFFERS, data, &reply);
-        return reply.readInt32();
-    }
-
-    sp<IMemory> getVideoBuffer(int32_t index) const
-    {
-        LOGV("getVideoBuffer: %d", index);
-        Parcel data, reply;
-        data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
-        data.writeInt32(index);
-        remote()->transact(GET_VIDEO_BUFFER, data, &reply);
-        sp<IMemory> mem = interface_cast<IMemory>(
-                            reply.readStrongBinder());
-        return mem;
-    }
-
     status_t storeMetaDataInBuffers(bool enabled)
     {
         LOGV("storeMetaDataInBuffers: %s", enabled? "true": "false");
@@ -355,19 +332,6 @@
             releaseRecordingFrame(mem);
             return NO_ERROR;
         } break;
-        case GET_NUM_VIDEO_BUFFERS: {
-            LOGV("GET_NUM_VIDEO_BUFFERS");
-            CHECK_INTERFACE(ICamera, data, reply);
-            reply->writeInt32(getNumberOfVideoBuffers());
-            return NO_ERROR;
-        } break;
-        case GET_VIDEO_BUFFER: {
-            LOGV("GET_VIDEO_BUFFER");
-            CHECK_INTERFACE(ICamera, data, reply);
-            int32_t index = data.readInt32();
-            reply->writeStrongBinder(getVideoBuffer(index)->asBinder());
-            return NO_ERROR;
-        } break;
         case STORE_META_DATA_IN_BUFFERS: {
             LOGV("STORE_META_DATA_IN_BUFFERS");
             CHECK_INTERFACE(ICamera, data, reply);
diff --git a/cmds/stagefright/Android.mk b/cmds/stagefright/Android.mk
index 1b13dd9..e9642f7 100644
--- a/cmds/stagefright/Android.mk
+++ b/cmds/stagefright/Android.mk
@@ -8,7 +8,7 @@
 
 LOCAL_SHARED_LIBRARIES := \
 	libstagefright libmedia libutils libbinder libstagefright_foundation \
-        libskia libsurfaceflinger_client libgui
+        libskia libgui
 
 LOCAL_C_INCLUDES:= \
 	$(JNI_H_INCLUDE) \
@@ -107,7 +107,7 @@
         stream.cpp    \
 
 LOCAL_SHARED_LIBRARIES := \
-	libstagefright liblog libutils libbinder libsurfaceflinger_client \
+	libstagefright liblog libutils libbinder libgui \
         libstagefright_foundation libmedia
 
 LOCAL_C_INCLUDES:= \
@@ -132,7 +132,7 @@
 
 LOCAL_SHARED_LIBRARIES := \
 	libstagefright liblog libutils libbinder libstagefright_foundation \
-        libmedia libsurfaceflinger_client libcutils libui
+        libmedia libgui libcutils libui
 
 LOCAL_C_INCLUDES:= \
 	$(JNI_H_INCLUDE) \
diff --git a/drm/common/DrmInfoEvent.cpp b/drm/common/DrmInfoEvent.cpp
index 8d115a8..27a5a2d 100644
--- a/drm/common/DrmInfoEvent.cpp
+++ b/drm/common/DrmInfoEvent.cpp
@@ -19,7 +19,7 @@
 
 using namespace android;
 
-DrmInfoEvent::DrmInfoEvent(int uniqueId, int infoType, const String8& message)
+DrmInfoEvent::DrmInfoEvent(int uniqueId, int infoType, const String8 message)
     : mUniqueId(uniqueId),
       mInfoType(infoType),
       mMessage(message) {
@@ -34,7 +34,7 @@
     return mInfoType;
 }
 
-const String8& DrmInfoEvent::getMessage() const {
+const String8 DrmInfoEvent::getMessage() const {
     return mMessage;
 }
 
diff --git a/drm/common/DrmSupportInfo.cpp b/drm/common/DrmSupportInfo.cpp
index c0bff0e..3dee435 100644
--- a/drm/common/DrmSupportInfo.cpp
+++ b/drm/common/DrmSupportInfo.cpp
@@ -15,6 +15,7 @@
  */
 
 #include <drm/DrmSupportInfo.h>
+#include <strings.h>
 
 using namespace android;
 
@@ -152,4 +153,3 @@
     mIndex++;
     return value;
 }
-
diff --git a/drm/common/IDrmManagerService.cpp b/drm/common/IDrmManagerService.cpp
index 346934b..c37b4f8 100644
--- a/drm/common/IDrmManagerService.cpp
+++ b/drm/common/IDrmManagerService.cpp
@@ -650,11 +650,6 @@
 
     remote()->transact(CLOSE_DECRYPT_SESSION, data, &reply);
 
-    if (NULL != decryptHandle->decryptInfo) {
-        LOGV("deleting decryptInfo");
-        delete decryptHandle->decryptInfo; decryptHandle->decryptInfo = NULL;
-    }
-    delete decryptHandle; decryptHandle = NULL;
     return reply.readInt32();
 }
 
diff --git a/drm/drmserver/Android.mk b/drm/drmserver/Android.mk
index f94f9a3..e3cd44f 100644
--- a/drm/drmserver/Android.mk
+++ b/drm/drmserver/Android.mk
@@ -22,6 +22,7 @@
     DrmManagerService.cpp
 
 LOCAL_SHARED_LIBRARIES := \
+    libmedia \
     libutils \
     libbinder
 
diff --git a/drm/drmserver/DrmManager.cpp b/drm/drmserver/DrmManager.cpp
index 1eee5f2..2fee59c 100644
--- a/drm/drmserver/DrmManager.cpp
+++ b/drm/drmserver/DrmManager.cpp
@@ -37,7 +37,6 @@
 
 using namespace android;
 
-Vector<int> DrmManager::mUniqueIdVector;
 const String8 DrmManager::EMPTY_STRING("");
 
 DrmManager::DrmManager() :
diff --git a/drm/drmserver/DrmManagerService.cpp b/drm/drmserver/DrmManagerService.cpp
index 0901a44..583669e 100644
--- a/drm/drmserver/DrmManagerService.cpp
+++ b/drm/drmserver/DrmManagerService.cpp
@@ -19,6 +19,7 @@
 #include <utils/Log.h>
 
 #include <private/android_filesystem_config.h>
+#include <media/MemoryLeakTrackUtil.h>
 
 #include <errno.h>
 #include <utils/threads.h>
@@ -256,3 +257,31 @@
     return mDrmManager->pread(uniqueId, decryptHandle, buffer, numBytes, offset);
 }
 
+status_t DrmManagerService::dump(int fd, const Vector<String16>& args)
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+    if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
+        snprintf(buffer, SIZE, "Permission Denial: "
+                "can't dump DrmManagerService from pid=%d, uid=%d\n",
+                IPCThreadState::self()->getCallingPid(),
+                IPCThreadState::self()->getCallingUid());
+        result.append(buffer);
+    } else {
+#if DRM_MEMORY_LEAK_TRACK
+        bool dumpMem = false;
+        for (size_t i = 0; i < args.size(); i++) {
+            if (args[i] == String16("-m")) {
+                dumpMem = true;
+            }
+        }
+        if (dumpMem) {
+            dumpMemoryAddresses(fd);
+        }
+#endif
+    }
+    write(fd, result.string(), result.size());
+    return NO_ERROR;
+}
+
diff --git a/drm/libdrmframework/Android.mk b/drm/libdrmframework/Android.mk
index 99133ba..f1526a4 100644
--- a/drm/libdrmframework/Android.mk
+++ b/drm/libdrmframework/Android.mk
@@ -40,7 +40,7 @@
     $(TOP)/frameworks/base/drm/libdrmframework/include \
     $(TOP)/frameworks/base/include
 
-LOCAL_PRELINK_MODULE := false
+
 
 LOCAL_MODULE_TAGS := optional
 
diff --git a/drm/libdrmframework/DrmManagerClient.cpp b/drm/libdrmframework/DrmManagerClient.cpp
index c1f382a..b50199f 100644
--- a/drm/libdrmframework/DrmManagerClient.cpp
+++ b/drm/libdrmframework/DrmManagerClient.cpp
@@ -76,12 +76,13 @@
     return mDrmManagerClientImpl->checkRightsStatus(mUniqueId, path, action);
 }
 
-status_t DrmManagerClient::consumeRights(DecryptHandle* decryptHandle, int action, bool reserve) {
+status_t DrmManagerClient::consumeRights(
+            sp<DecryptHandle> &decryptHandle, int action, bool reserve) {
     return mDrmManagerClientImpl->consumeRights(mUniqueId, decryptHandle, action, reserve);
 }
 
 status_t DrmManagerClient::setPlaybackStatus(
-            DecryptHandle* decryptHandle, int playbackStatus, int64_t position) {
+            sp<DecryptHandle> &decryptHandle, int playbackStatus, int64_t position) {
     return mDrmManagerClientImpl
             ->setPlaybackStatus(mUniqueId, decryptHandle, playbackStatus, position);
 }
@@ -115,37 +116,39 @@
     return mDrmManagerClientImpl->getAllSupportInfo(mUniqueId, length, drmSupportInfoArray);
 }
 
-DecryptHandle* DrmManagerClient::openDecryptSession(int fd, off64_t offset, off64_t length) {
+sp<DecryptHandle> DrmManagerClient::openDecryptSession(int fd, off64_t offset, off64_t length) {
     return mDrmManagerClientImpl->openDecryptSession(mUniqueId, fd, offset, length);
 }
 
-DecryptHandle* DrmManagerClient::openDecryptSession(const char* uri) {
+sp<DecryptHandle> DrmManagerClient::openDecryptSession(const char* uri) {
     return mDrmManagerClientImpl->openDecryptSession(mUniqueId, uri);
 }
 
-status_t DrmManagerClient::closeDecryptSession(DecryptHandle* decryptHandle) {
+status_t DrmManagerClient::closeDecryptSession(sp<DecryptHandle> &decryptHandle) {
     return mDrmManagerClientImpl->closeDecryptSession(mUniqueId, decryptHandle);
 }
 
 status_t DrmManagerClient::initializeDecryptUnit(
-            DecryptHandle* decryptHandle, int decryptUnitId, const DrmBuffer* headerInfo) {
+            sp<DecryptHandle> &decryptHandle, int decryptUnitId, const DrmBuffer* headerInfo) {
     return mDrmManagerClientImpl->initializeDecryptUnit(
             mUniqueId, decryptHandle, decryptUnitId, headerInfo);
 }
 
 status_t DrmManagerClient::decrypt(
-    DecryptHandle* decryptHandle, int decryptUnitId,
-    const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) {
+            sp<DecryptHandle> &decryptHandle, int decryptUnitId,
+            const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) {
     return mDrmManagerClientImpl->decrypt(
             mUniqueId, decryptHandle, decryptUnitId, encBuffer, decBuffer, IV);
 }
 
-status_t DrmManagerClient::finalizeDecryptUnit(DecryptHandle* decryptHandle, int decryptUnitId) {
-    return mDrmManagerClientImpl->finalizeDecryptUnit(mUniqueId, decryptHandle, decryptUnitId);
+status_t DrmManagerClient::finalizeDecryptUnit(
+            sp<DecryptHandle> &decryptHandle, int decryptUnitId) {
+    return mDrmManagerClientImpl->finalizeDecryptUnit(mUniqueId,
+            decryptHandle, decryptUnitId);
 }
 
 ssize_t DrmManagerClient::pread(
-            DecryptHandle* decryptHandle, void* buffer, ssize_t numBytes, off64_t offset) {
+            sp<DecryptHandle> &decryptHandle, void* buffer, ssize_t numBytes, off64_t offset) {
     return mDrmManagerClientImpl->pread(mUniqueId, decryptHandle, buffer, numBytes, offset);
 }
 
diff --git a/drm/libdrmframework/DrmManagerClientImpl.cpp b/drm/libdrmframework/DrmManagerClientImpl.cpp
index 9c7fed3..a57dd98 100644
--- a/drm/libdrmframework/DrmManagerClientImpl.cpp
+++ b/drm/libdrmframework/DrmManagerClientImpl.cpp
@@ -81,14 +81,16 @@
 }
 
 status_t DrmManagerClientImpl::setOnInfoListener(
-            int uniqueId, const sp<DrmManagerClient::OnInfoListener>& infoListener) {
+            int uniqueId,
+            const sp<DrmManagerClient::OnInfoListener>& infoListener) {
     Mutex::Autolock _l(mLock);
     mOnInfoListener = infoListener;
     return getDrmManagerService()->setDrmServiceListener(uniqueId,
             (NULL != infoListener.get()) ? this : NULL);
 }
 
-status_t DrmManagerClientImpl::installDrmEngine(int uniqueId, const String8& drmEngineFile) {
+status_t DrmManagerClientImpl::installDrmEngine(
+        int uniqueId, const String8& drmEngineFile) {
     status_t status = DRM_ERROR_UNKNOWN;
     if (EMPTY_STRING != drmEngineFile) {
         status = getDrmManagerService()->installDrmEngine(uniqueId, drmEngineFile);
@@ -100,7 +102,8 @@
         int uniqueId, const String8* path, const int action) {
     DrmConstraints *drmConstraints = NULL;
     if ((NULL != path) && (EMPTY_STRING != *path)) {
-        drmConstraints = getDrmManagerService()->getConstraints(uniqueId, path, action);
+        drmConstraints =
+            getDrmManagerService()->getConstraints(uniqueId, path, action);
     }
     return drmConstraints;
 }
@@ -113,7 +116,8 @@
     return drmMetadata;
 }
 
-bool DrmManagerClientImpl::canHandle(int uniqueId, const String8& path, const String8& mimeType) {
+bool DrmManagerClientImpl::canHandle(
+        int uniqueId, const String8& path, const String8& mimeType) {
     bool retCode = false;
     if ((EMPTY_STRING != path) || (EMPTY_STRING != mimeType)) {
         retCode = getDrmManagerService()->canHandle(uniqueId, path, mimeType);
@@ -121,7 +125,8 @@
     return retCode;
 }
 
-DrmInfoStatus* DrmManagerClientImpl::processDrmInfo(int uniqueId, const DrmInfo* drmInfo) {
+DrmInfoStatus* DrmManagerClientImpl::processDrmInfo(
+        int uniqueId, const DrmInfo* drmInfo) {
     DrmInfoStatus *drmInfoStatus = NULL;
     if (NULL != drmInfo) {
         drmInfoStatus = getDrmManagerService()->processDrmInfo(uniqueId, drmInfo);
@@ -129,7 +134,8 @@
     return drmInfoStatus;
 }
 
-DrmInfo* DrmManagerClientImpl::acquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInfoRequest) {
+DrmInfo* DrmManagerClientImpl::acquireDrmInfo(
+        int uniqueId, const DrmInfoRequest* drmInfoRequest) {
     DrmInfo* drmInfo = NULL;
     if (NULL != drmInfoRequest) {
         drmInfo = getDrmManagerService()->acquireDrmInfo(uniqueId, drmInfoRequest);
@@ -140,13 +146,12 @@
 status_t DrmManagerClientImpl::saveRights(int uniqueId, const DrmRights& drmRights,
             const String8& rightsPath, const String8& contentPath) {
     status_t status = DRM_ERROR_UNKNOWN;
-    if (EMPTY_STRING != contentPath) {
-        status = getDrmManagerService()->saveRights(uniqueId, drmRights, rightsPath, contentPath);
-    }
-    return status;
+    return getDrmManagerService()->saveRights(
+                uniqueId, drmRights, rightsPath, contentPath);
 }
 
-String8 DrmManagerClientImpl::getOriginalMimeType(int uniqueId, const String8& path) {
+String8 DrmManagerClientImpl::getOriginalMimeType(
+        int uniqueId, const String8& path) {
     String8 mimeType = EMPTY_STRING;
     if (EMPTY_STRING != path) {
         mimeType = getDrmManagerService()->getOriginalMimeType(uniqueId, path);
@@ -158,7 +163,8 @@
             int uniqueId, const String8& path, const String8& mimeType) {
     int drmOjectType = DrmObjectType::UNKNOWN;
     if ((EMPTY_STRING != path) || (EMPTY_STRING != mimeType)) {
-         drmOjectType = getDrmManagerService()->getDrmObjectType(uniqueId, path, mimeType);
+         drmOjectType =
+             getDrmManagerService()->getDrmObjectType(uniqueId, path, mimeType);
     }
     return drmOjectType;
 }
@@ -167,35 +173,41 @@
             int uniqueId, const String8& path, int action) {
     int rightsStatus = RightsStatus::RIGHTS_INVALID;
     if (EMPTY_STRING != path) {
-        rightsStatus = getDrmManagerService()->checkRightsStatus(uniqueId, path, action);
+        rightsStatus =
+            getDrmManagerService()->checkRightsStatus(uniqueId, path, action);
     }
     return rightsStatus;
 }
 
 status_t DrmManagerClientImpl::consumeRights(
-            int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve) {
+            int uniqueId, sp<DecryptHandle> &decryptHandle,
+            int action, bool reserve) {
     status_t status = DRM_ERROR_UNKNOWN;
-    if (NULL != decryptHandle) {
-        status = getDrmManagerService()->consumeRights(uniqueId, decryptHandle, action, reserve);
+    if (NULL != decryptHandle.get()) {
+        status = getDrmManagerService()->consumeRights(
+                uniqueId, decryptHandle.get(), action, reserve);
     }
     return status;
 }
 
 status_t DrmManagerClientImpl::setPlaybackStatus(
-            int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int64_t position) {
+            int uniqueId, sp<DecryptHandle> &decryptHandle,
+            int playbackStatus, int64_t position) {
     status_t status = DRM_ERROR_UNKNOWN;
-    if (NULL != decryptHandle) {
+    if (NULL != decryptHandle.get()) {
         status = getDrmManagerService()->setPlaybackStatus(
-                uniqueId, decryptHandle, playbackStatus, position);
+                uniqueId, decryptHandle.get(), playbackStatus, position);
     }
     return status;
 }
 
 bool DrmManagerClientImpl::validateAction(
-            int uniqueId, const String8& path, int action, const ActionDescription& description) {
+            int uniqueId, const String8& path,
+            int action, const ActionDescription& description) {
     bool retCode = false;
     if (EMPTY_STRING != path) {
-        retCode = getDrmManagerService()->validateAction(uniqueId, path, action, description);
+        retCode = getDrmManagerService()->validateAction(
+                uniqueId, path, action, description);
     }
     return retCode;
 }
@@ -212,7 +224,8 @@
     return getDrmManagerService()->removeAllRights(uniqueId);
 }
 
-int DrmManagerClientImpl::openConvertSession(int uniqueId, const String8& mimeType) {
+int DrmManagerClientImpl::openConvertSession(
+        int uniqueId, const String8& mimeType) {
     int retCode = INVALID_VALUE;
     if (EMPTY_STRING != mimeType) {
         retCode = getDrmManagerService()->openConvertSession(uniqueId, mimeType);
@@ -224,12 +237,14 @@
             int uniqueId, int convertId, const DrmBuffer* inputData) {
     DrmConvertedStatus* drmConvertedStatus = NULL;
     if (NULL != inputData) {
-         drmConvertedStatus = getDrmManagerService()->convertData(uniqueId, convertId, inputData);
+         drmConvertedStatus =
+             getDrmManagerService()->convertData(uniqueId, convertId, inputData);
     }
     return drmConvertedStatus;
 }
 
-DrmConvertedStatus* DrmManagerClientImpl::closeConvertSession(int uniqueId, int convertId) {
+DrmConvertedStatus* DrmManagerClientImpl::closeConvertSession(
+        int uniqueId, int convertId) {
     return getDrmManagerService()->closeConvertSession(uniqueId, convertId);
 }
 
@@ -237,17 +252,19 @@
             int uniqueId, int* length, DrmSupportInfo** drmSupportInfoArray) {
     status_t status = DRM_ERROR_UNKNOWN;
     if ((NULL != drmSupportInfoArray) && (NULL != length)) {
-        status = getDrmManagerService()->getAllSupportInfo(uniqueId, length, drmSupportInfoArray);
+        status = getDrmManagerService()->getAllSupportInfo(
+                uniqueId, length, drmSupportInfoArray);
     }
     return status;
 }
 
-DecryptHandle* DrmManagerClientImpl::openDecryptSession(
+sp<DecryptHandle> DrmManagerClientImpl::openDecryptSession(
             int uniqueId, int fd, off64_t offset, off64_t length) {
     return getDrmManagerService()->openDecryptSession(uniqueId, fd, offset, length);
 }
 
-DecryptHandle* DrmManagerClientImpl::openDecryptSession(int uniqueId, const char* uri) {
+sp<DecryptHandle> DrmManagerClientImpl::openDecryptSession(
+        int uniqueId, const char* uri) {
     DecryptHandle* handle = NULL;
     if (NULL != uri) {
         handle = getDrmManagerService()->openDecryptSession(uniqueId, uri);
@@ -255,50 +272,57 @@
     return handle;
 }
 
-status_t DrmManagerClientImpl::closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle) {
+status_t DrmManagerClientImpl::closeDecryptSession(
+        int uniqueId, sp<DecryptHandle> &decryptHandle) {
     status_t status = DRM_ERROR_UNKNOWN;
-    if (NULL != decryptHandle) {
-        status = getDrmManagerService()->closeDecryptSession( uniqueId, decryptHandle);
+    if (NULL != decryptHandle.get()) {
+        status = getDrmManagerService()->closeDecryptSession(
+                uniqueId, decryptHandle.get());
     }
     return status;
 }
 
-status_t DrmManagerClientImpl::initializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle,
-            int decryptUnitId, const DrmBuffer* headerInfo) {
+status_t DrmManagerClientImpl::initializeDecryptUnit(
+        int uniqueId, sp<DecryptHandle> &decryptHandle,
+        int decryptUnitId, const DrmBuffer* headerInfo) {
     status_t status = DRM_ERROR_UNKNOWN;
-    if ((NULL != decryptHandle) && (NULL != headerInfo)) {
+    if ((NULL != decryptHandle.get()) && (NULL != headerInfo)) {
         status = getDrmManagerService()->initializeDecryptUnit(
-                uniqueId, decryptHandle, decryptUnitId, headerInfo);
+                uniqueId, decryptHandle.get(), decryptUnitId, headerInfo);
     }
     return status;
 }
 
-status_t DrmManagerClientImpl::decrypt(int uniqueId, DecryptHandle* decryptHandle,
-            int decryptUnitId, const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) {
+status_t DrmManagerClientImpl::decrypt(
+        int uniqueId, sp<DecryptHandle> &decryptHandle,
+        int decryptUnitId, const DrmBuffer* encBuffer,
+        DrmBuffer** decBuffer, DrmBuffer* IV) {
     status_t status = DRM_ERROR_UNKNOWN;
-    if ((NULL != decryptHandle) && (NULL != encBuffer)
+    if ((NULL != decryptHandle.get()) && (NULL != encBuffer)
         && (NULL != decBuffer) && (NULL != *decBuffer)) {
         status = getDrmManagerService()->decrypt(
-                uniqueId, decryptHandle, decryptUnitId, encBuffer, decBuffer, IV);
+                uniqueId, decryptHandle.get(), decryptUnitId,
+                encBuffer, decBuffer, IV);
     }
     return status;
 }
 
 status_t DrmManagerClientImpl::finalizeDecryptUnit(
-            int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId) {
+            int uniqueId, sp<DecryptHandle> &decryptHandle, int decryptUnitId) {
     status_t status = DRM_ERROR_UNKNOWN;
-    if (NULL != decryptHandle) {
-        status
-            = getDrmManagerService()->finalizeDecryptUnit(uniqueId, decryptHandle, decryptUnitId);
+    if (NULL != decryptHandle.get()) {
+        status = getDrmManagerService()->finalizeDecryptUnit(
+                    uniqueId, decryptHandle.get(), decryptUnitId);
     }
     return status;
 }
 
-ssize_t DrmManagerClientImpl::pread(int uniqueId, DecryptHandle* decryptHandle,
+ssize_t DrmManagerClientImpl::pread(int uniqueId, sp<DecryptHandle> &decryptHandle,
             void* buffer, ssize_t numBytes, off64_t offset) {
     ssize_t retCode = INVALID_VALUE;
-    if ((NULL != decryptHandle) && (NULL != buffer) && (0 < numBytes)) {
-        retCode = getDrmManagerService()->pread(uniqueId, decryptHandle, buffer, numBytes, offset);
+    if ((NULL != decryptHandle.get()) && (NULL != buffer) && (0 < numBytes)) {
+        retCode = getDrmManagerService()->pread(
+                uniqueId, decryptHandle.get(), buffer, numBytes, offset);
     }
     return retCode;
 }
diff --git a/drm/libdrmframework/include/DrmManager.h b/drm/libdrmframework/include/DrmManager.h
index c7276f9..af2c2a8 100644
--- a/drm/libdrmframework/include/DrmManager.h
+++ b/drm/libdrmframework/include/DrmManager.h
@@ -30,7 +30,6 @@
 class DrmRegistrationInfo;
 class DrmUnregistrationInfo;
 class DrmRightsAcquisitionInfo;
-class DrmContentIds;
 class DrmConstraints;
 class DrmMetadata;
 class DrmRights;
@@ -141,7 +140,7 @@
     bool canHandle(int uniqueId, const String8& path);
 
 private:
-    static Vector<int> mUniqueIdVector;
+    Vector<int> mUniqueIdVector;
     static const String8 EMPTY_STRING;
 
     int mDecryptSessionId;
diff --git a/drm/libdrmframework/include/DrmManagerClientImpl.h b/drm/libdrmframework/include/DrmManagerClientImpl.h
index 429e4c3..564896b 100644
--- a/drm/libdrmframework/include/DrmManagerClientImpl.h
+++ b/drm/libdrmframework/include/DrmManagerClientImpl.h
@@ -189,7 +189,7 @@
      * @return status_t
      *     Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
      */
-    status_t consumeRights(int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve);
+    status_t consumeRights(int uniqueId, sp<DecryptHandle> &decryptHandle, int action, bool reserve);
 
     /**
      * Informs the DRM engine about the playback actions performed on the DRM files.
@@ -203,7 +203,7 @@
      *     Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
      */
     status_t setPlaybackStatus(
-            int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int64_t position);
+            int uniqueId, sp<DecryptHandle> &decryptHandle, int playbackStatus, int64_t position);
 
     /**
      * Validates whether an action on the DRM content is allowed or not.
@@ -303,7 +303,7 @@
      * @return
      *     Handle for the decryption session
      */
-    DecryptHandle* openDecryptSession(int uniqueId, int fd, off64_t offset, off64_t length);
+    sp<DecryptHandle> openDecryptSession(int uniqueId, int fd, off64_t offset, off64_t length);
 
     /**
      * Open the decrypt session to decrypt the given protected content
@@ -313,7 +313,7 @@
      * @return
      *     Handle for the decryption session
      */
-    DecryptHandle* openDecryptSession(int uniqueId, const char* uri);
+    sp<DecryptHandle> openDecryptSession(int uniqueId, const char* uri);
 
     /**
      * Close the decrypt session for the given handle
@@ -323,7 +323,7 @@
      * @return status_t
      *     Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
      */
-    status_t closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle);
+    status_t closeDecryptSession(int uniqueId, sp<DecryptHandle> &decryptHandle);
 
     /**
      * Initialize decryption for the given unit of the protected content
@@ -335,7 +335,7 @@
      * @return status_t
      *     Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
      */
-    status_t initializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle,
+    status_t initializeDecryptUnit(int uniqueId, sp<DecryptHandle> &decryptHandle,
             int decryptUnitId, const DrmBuffer* headerInfo);
 
     /**
@@ -355,7 +355,7 @@
      *     DRM_ERROR_SESSION_NOT_OPENED, DRM_ERROR_DECRYPT_UNIT_NOT_INITIALIZED,
      *     DRM_ERROR_DECRYPT for failure.
      */
-    status_t decrypt(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId,
+    status_t decrypt(int uniqueId, sp<DecryptHandle> &decryptHandle, int decryptUnitId,
             const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV);
 
     /**
@@ -367,7 +367,7 @@
      * @return status_t
      *     Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
      */
-    status_t finalizeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId);
+    status_t finalizeDecryptUnit(int uniqueId, sp<DecryptHandle> &decryptHandle, int decryptUnitId);
 
     /**
      * Reads the specified number of bytes from an open DRM file.
@@ -380,7 +380,7 @@
      *
      * @return Number of bytes read. Returns -1 for Failure.
      */
-    ssize_t pread(int uniqueId, DecryptHandle* decryptHandle,
+    ssize_t pread(int uniqueId, sp<DecryptHandle> &decryptHandle,
             void* buffer, ssize_t numBytes, off64_t offset);
 
     /**
diff --git a/drm/libdrmframework/include/DrmManagerService.h b/drm/libdrmframework/include/DrmManagerService.h
index d0a0db7..227496a 100644
--- a/drm/libdrmframework/include/DrmManagerService.h
+++ b/drm/libdrmframework/include/DrmManagerService.h
@@ -115,6 +115,8 @@
     ssize_t pread(int uniqueId, DecryptHandle* decryptHandle,
             void* buffer, ssize_t numBytes, off64_t offset);
 
+    virtual status_t dump(int fd, const Vector<String16>& args);
+
 private:
     DrmManager* mDrmManager;
 };
diff --git a/drm/libdrmframework/include/IDrmManagerService.h b/drm/libdrmframework/include/IDrmManagerService.h
index 2424ea5..7727e55 100644
--- a/drm/libdrmframework/include/IDrmManagerService.h
+++ b/drm/libdrmframework/include/IDrmManagerService.h
@@ -25,7 +25,6 @@
 
 namespace android {
 
-class DrmContentIds;
 class DrmConstraints;
 class DrmMetadata;
 class DrmRights;
diff --git a/drm/libdrmframework/plugins/common/include/IDrmEngine.h b/drm/libdrmframework/plugins/common/include/IDrmEngine.h
index d05c24f..77460f6 100644
--- a/drm/libdrmframework/plugins/common/include/IDrmEngine.h
+++ b/drm/libdrmframework/plugins/common/include/IDrmEngine.h
@@ -21,7 +21,6 @@
 
 namespace android {
 
-class DrmContentIds;
 class DrmConstraints;
 class DrmMetadata;
 class DrmRights;
diff --git a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.mk b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.mk
index af67aa3..9805a40 100644
--- a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.mk
+++ b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.mk
@@ -47,7 +47,7 @@
     libfwdlock-converter \
     libfwdlock-decoder
 
-LOCAL_PRELINK_MODULE := false
+
 
 LOCAL_C_INCLUDES += \
     $(JNI_H_INCLUDE) \
diff --git a/drm/libdrmframework/plugins/passthru/Android.mk b/drm/libdrmframework/plugins/passthru/Android.mk
index 7856d37..be18b64 100644
--- a/drm/libdrmframework/plugins/passthru/Android.mk
+++ b/drm/libdrmframework/plugins/passthru/Android.mk
@@ -32,7 +32,7 @@
  LOCAL_SHARED_LIBRARIES += libdl
 endif
 
-LOCAL_PRELINK_MODULE := false
+
 
 LOCAL_C_INCLUDES += \
     $(TOP)/frameworks/base/drm/libdrmframework/include \
diff --git a/include/camera/Camera.h b/include/camera/Camera.h
index f3c8f64..3c6dccc 100644
--- a/include/camera/Camera.h
+++ b/include/camera/Camera.h
@@ -219,12 +219,6 @@
             // send command to camera driver
             status_t    sendCommand(int32_t cmd, int32_t arg1, int32_t arg2);
 
-            // return the total number of available video buffers.
-            int32_t     getNumberOfVideoBuffers() const;
-
-            // return the individual video buffer corresponding to the given index.
-            sp<IMemory> getVideoBuffer(int32_t index) const;
-
             // tell camera hal to store meta data or real YUV in video buffers.
             status_t    storeMetaDataInBuffers(bool enabled);
 
diff --git a/include/camera/CameraHardwareInterface.h b/include/camera/CameraHardwareInterface.h
index 86bd849..3f34120 100644
--- a/include/camera/CameraHardwareInterface.h
+++ b/include/camera/CameraHardwareInterface.h
@@ -28,16 +28,6 @@
 
 namespace android {
 
-/**
- *  The size of image for display.
- */
-typedef struct image_rect_struct
-{
-  uint32_t width;      /* Image width */
-  uint32_t height;     /* Image height */
-} image_rect_type;
-
-
 typedef void (*notify_callback)(int32_t msgType,
                                 int32_t ext1,
                                 int32_t ext2,
@@ -90,9 +80,6 @@
     /** Set the ANativeWindow to which preview frames are sent */
     virtual status_t setPreviewWindow(const sp<ANativeWindow>& buf) = 0;
 
-    /** Return the IMemoryHeap for the raw image heap */
-    virtual sp<IMemoryHeap>         getRawHeap() const = 0;
-
     /** Set the notification and data callbacks */
     virtual void setCallbacks(notify_callback notify_cb,
                               data_callback data_cb,
@@ -145,47 +132,6 @@
     virtual bool        previewEnabled() = 0;
 
     /**
-     * Retrieve the total number of available buffers from camera hal for passing
-     * video frame data in a recording session. Must be called again if a new
-     * recording session is started.
-     *
-     * This method should be called after startRecording(), since
-     * the some camera hal may choose to allocate the video buffers only after
-     * recording is started.
-     *
-     * Some camera hal may not implement this method, and 0 can be returned to
-     * indicate that this feature is not available.
-     *
-     * @return the number of video buffers that camera hal makes available.
-     *      Zero (0) is returned to indicate that camera hal does not support
-     *      this feature.
-     */
-    virtual int32_t     getNumberOfVideoBuffers() const { return 0; }
-
-    /**
-     * Retrieve the video buffer corresponding to the given index in a
-     * recording session. Must be called again if a new recording session
-     * is started.
-     *
-     * It allows a client to retrieve all video buffers that camera hal makes
-     * available to passing video frame data by calling this method with all
-     * valid index values. The valid index value ranges from 0 to n, where
-     * n = getNumberOfVideoBuffers() - 1. With an index outside of the valid
-     * range, 0 must be returned. This method should be called after
-     * startRecording().
-     *
-     * The video buffers should NOT be modified/released by camera hal
-     * until stopRecording() is called and all outstanding video buffers
-     * previously sent out via CAMERA_MSG_VIDEO_FRAME have been released
-     * via releaseVideoBuffer().
-     *
-     * @param index an index to retrieve the corresponding video buffer.
-     *
-     * @return the video buffer corresponding to the given index.
-     */
-    virtual sp<IMemory> getVideoBuffer(int32_t index) const { return 0; }
-
-    /**
      * Request the camera hal to store meta data or real YUV data in
      * the video buffers send out via CAMERA_MSG_VIDEO_FRRAME for a
      * recording session. If it is not called, the default camera
diff --git a/include/camera/ICamera.h b/include/camera/ICamera.h
index 2344b3f..400d7f4 100644
--- a/include/camera/ICamera.h
+++ b/include/camera/ICamera.h
@@ -102,12 +102,6 @@
     // send command to camera driver
     virtual status_t        sendCommand(int32_t cmd, int32_t arg1, int32_t arg2) = 0;
 
-    // return the total number of available video buffers
-    virtual int32_t         getNumberOfVideoBuffers() const  = 0;
-
-    // return the individual video buffer corresponding to the given index.
-    virtual sp<IMemory>     getVideoBuffer(int32_t index) const = 0;
-
     // tell the camera hal to store meta data or real YUV data in video buffers.
     virtual status_t        storeMetaDataInBuffers(bool enabled) = 0;
 };
diff --git a/include/drm/DrmInfoEvent.h b/include/drm/DrmInfoEvent.h
index add33d3..dfca228 100644
--- a/include/drm/DrmInfoEvent.h
+++ b/include/drm/DrmInfoEvent.h
@@ -77,7 +77,7 @@
      * @param[in] infoType Type of information
      * @param[in] message Message description
      */
-    DrmInfoEvent(int uniqueId, int infoType, const String8& message);
+    DrmInfoEvent(int uniqueId, int infoType, const String8 message);
 
     /**
      * Destructor for DrmInfoEvent
@@ -104,12 +104,12 @@
      *
      * @return Message description
      */
-    const String8& getMessage() const;
+    const String8 getMessage() const;
 
 private:
     int mUniqueId;
     int mInfoType;
-    const String8& mMessage;
+    const String8 mMessage;
 };
 
 };
diff --git a/include/drm/DrmManagerClient.h b/include/drm/DrmManagerClient.h
index 7a0bf4f..b8fe46d 100644
--- a/include/drm/DrmManagerClient.h
+++ b/include/drm/DrmManagerClient.h
@@ -69,7 +69,7 @@
      * @return
      *     Handle for the decryption session
      */
-    DecryptHandle* openDecryptSession(int fd, off64_t offset, off64_t length);
+    sp<DecryptHandle> openDecryptSession(int fd, off64_t offset, off64_t length);
 
     /**
      * Open the decrypt session to decrypt the given protected content
@@ -78,7 +78,7 @@
      * @return
      *     Handle for the decryption session
      */
-    DecryptHandle* openDecryptSession(const char* uri);
+    sp<DecryptHandle> openDecryptSession(const char* uri);
 
     /**
      * Close the decrypt session for the given handle
@@ -87,7 +87,7 @@
      * @return status_t
      *     Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
      */
-    status_t closeDecryptSession(DecryptHandle* decryptHandle);
+    status_t closeDecryptSession(sp<DecryptHandle> &decryptHandle);
 
     /**
      * Consumes the rights for a content.
@@ -101,7 +101,7 @@
      *     Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure.
      *     In case license has been expired, DRM_ERROR_LICENSE_EXPIRED will be returned.
      */
-    status_t consumeRights(DecryptHandle* decryptHandle, int action, bool reserve);
+    status_t consumeRights(sp<DecryptHandle> &decryptHandle, int action, bool reserve);
 
     /**
      * Informs the DRM engine about the playback actions performed on the DRM files.
@@ -113,7 +113,8 @@
      * @return status_t
      *     Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
      */
-    status_t setPlaybackStatus(DecryptHandle* decryptHandle, int playbackStatus, int64_t position);
+    status_t setPlaybackStatus(
+            sp<DecryptHandle> &decryptHandle, int playbackStatus, int64_t position);
 
     /**
      * Initialize decryption for the given unit of the protected content
@@ -125,7 +126,7 @@
      *     Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
      */
     status_t initializeDecryptUnit(
-            DecryptHandle* decryptHandle, int decryptUnitId, const DrmBuffer* headerInfo);
+            sp<DecryptHandle> &decryptHandle, int decryptUnitId, const DrmBuffer* headerInfo);
 
     /**
      * Decrypt the protected content buffers for the given unit
@@ -144,7 +145,7 @@
      *     DRM_ERROR_DECRYPT for failure.
      */
     status_t decrypt(
-            DecryptHandle* decryptHandle, int decryptUnitId,
+            sp<DecryptHandle> &decryptHandle, int decryptUnitId,
             const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV = NULL);
 
     /**
@@ -155,7 +156,8 @@
      * @return status_t
      *     Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
      */
-    status_t finalizeDecryptUnit(DecryptHandle* decryptHandle, int decryptUnitId);
+    status_t finalizeDecryptUnit(
+            sp<DecryptHandle> &decryptHandle, int decryptUnitId);
 
     /**
      * Reads the specified number of bytes from an open DRM file.
@@ -167,7 +169,8 @@
      *
      * @return Number of bytes read. Returns -1 for Failure.
      */
-    ssize_t pread(DecryptHandle* decryptHandle, void* buffer, ssize_t numBytes, off64_t offset);
+    ssize_t pread(sp<DecryptHandle> &decryptHandle,
+            void* buffer, ssize_t numBytes, off64_t offset);
 
     /**
      * Validates whether an action on the DRM content is allowed or not.
diff --git a/include/drm/drm_framework_common.h b/include/drm/drm_framework_common.h
index 454fc99..d2d1d7e 100644
--- a/include/drm/drm_framework_common.h
+++ b/include/drm/drm_framework_common.h
@@ -19,6 +19,7 @@
 
 #include <utils/Vector.h>
 #include <utils/KeyedVector.h>
+#include <utils/RefBase.h>
 #include <utils/String8.h>
 #include <utils/Errors.h>
 
@@ -251,7 +252,7 @@
 /**
  * Defines decryption handle
  */
-class DecryptHandle {
+class DecryptHandle : public RefBase {
 public:
     /**
      * Decryption session Handle
@@ -307,10 +308,15 @@
             decryptId(INVALID_VALUE),
             mimeType(""),
             decryptApiType(INVALID_VALUE),
-            status(INVALID_VALUE) {
+            status(INVALID_VALUE),
+            decryptInfo(NULL) {
 
     }
 
+    ~DecryptHandle() {
+        delete decryptInfo; decryptInfo = NULL;
+    }
+
     bool operator<(const DecryptHandle& handle) const {
         return (decryptId < handle.decryptId);
     }
diff --git a/include/media/IMediaMetadataRetriever.h b/include/media/IMediaMetadataRetriever.h
index 8e3cdbb..1c1c268 100644
--- a/include/media/IMediaMetadataRetriever.h
+++ b/include/media/IMediaMetadataRetriever.h
@@ -18,10 +18,11 @@
 #ifndef ANDROID_IMEDIAMETADATARETRIEVER_H
 #define ANDROID_IMEDIAMETADATARETRIEVER_H
 
-#include <utils/RefBase.h>
 #include <binder/IInterface.h>
 #include <binder/Parcel.h>
 #include <binder/IMemory.h>
+#include <utils/KeyedVector.h>
+#include <utils/RefBase.h>
 
 namespace android {
 
@@ -30,7 +31,11 @@
 public:
     DECLARE_META_INTERFACE(MediaMetadataRetriever);
     virtual void            disconnect() = 0;
-    virtual status_t        setDataSource(const char* srcUrl) = 0;
+
+    virtual status_t        setDataSource(
+            const char *srcUrl,
+            const KeyedVector<String8, String8> *headers = NULL) = 0;
+
     virtual status_t        setDataSource(int fd, int64_t offset, int64_t length) = 0;
     virtual sp<IMemory>     getFrameAtTime(int64_t timeUs, int option) = 0;
     virtual sp<IMemory>     extractAlbumArt() = 0;
diff --git a/include/media/MediaMetadataRetrieverInterface.h b/include/media/MediaMetadataRetrieverInterface.h
index 0449122..27b7e4d 100644
--- a/include/media/MediaMetadataRetrieverInterface.h
+++ b/include/media/MediaMetadataRetrieverInterface.h
@@ -30,7 +30,11 @@
 public:
                         MediaMetadataRetrieverBase() {}
     virtual             ~MediaMetadataRetrieverBase() {}
-    virtual status_t    setDataSource(const char *url) = 0;
+
+    virtual status_t    setDataSource(
+            const char *url,
+            const KeyedVector<String8, String8> *headers = NULL) = 0;
+
     virtual status_t    setDataSource(int fd, int64_t offset, int64_t length) = 0;
     virtual VideoFrame* getFrameAtTime(int64_t timeUs, int option) = 0;
     virtual MediaAlbumArt* extractAlbumArt() = 0;
diff --git a/include/media/MemoryLeakTrackUtil.h b/include/media/MemoryLeakTrackUtil.h
new file mode 100644
index 0000000..290b748
--- /dev/null
+++ b/include/media/MemoryLeakTrackUtil.h
@@ -0,0 +1,28 @@
+
+/*
+ * Copyright 2011, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef MEMORY_LEAK_TRACK_UTIL_H
+#define MEMORY_LEAK_TRACK_UTIL_H
+
+namespace android {
+/*
+ * Dump the memory adddress of the calling process to the given fd.
+ */
+extern void dumpMemoryAddresses(int fd);
+
+};
+
+#endif  // MEMORY_LEAK_TRACK_UTIL_H
diff --git a/include/media/mediametadataretriever.h b/include/media/mediametadataretriever.h
index e905006..3e343e0 100644
--- a/include/media/mediametadataretriever.h
+++ b/include/media/mediametadataretriever.h
@@ -47,6 +47,12 @@
     METADATA_KEY_ALBUMARTIST     = 13,
     METADATA_KEY_DISC_NUMBER     = 14,
     METADATA_KEY_COMPILATION     = 15,
+    METADATA_KEY_HAS_AUDIO       = 16,
+    METADATA_KEY_HAS_VIDEO       = 17,
+    METADATA_KEY_VIDEO_WIDTH     = 18,
+    METADATA_KEY_VIDEO_HEIGHT    = 19,
+    METADATA_KEY_BITRATE         = 20,
+
     // Add more here...
 };
 
@@ -56,7 +62,11 @@
     MediaMetadataRetriever();
     ~MediaMetadataRetriever();
     void disconnect();
-    status_t setDataSource(const char* dataSourceUrl);
+
+    status_t setDataSource(
+            const char *dataSourceUrl,
+            const KeyedVector<String8, String8> *headers = NULL);
+
     status_t setDataSource(int fd, int64_t offset, int64_t length);
     sp<IMemory> getFrameAtTime(int64_t timeUs, int option);
     sp<IMemory> extractAlbumArt();
diff --git a/include/media/mediarecorder.h b/include/media/mediarecorder.h
index a710546..67d940b 100644
--- a/include/media/mediarecorder.h
+++ b/include/media/mediarecorder.h
@@ -104,35 +104,62 @@
 };
 
 /*
- * The state machine of the media_recorder uses a set of different state names.
- * The mapping between the media_recorder and the pvauthorengine is shown below:
- *
- *    mediarecorder                        pvauthorengine
- * ----------------------------------------------------------------
- *    MEDIA_RECORDER_ERROR                 ERROR
- *    MEDIA_RECORDER_IDLE                  IDLE
- *    MEDIA_RECORDER_INITIALIZED           OPENED
- *    MEDIA_RECORDER_DATASOURCE_CONFIGURED
- *    MEDIA_RECORDER_PREPARED              INITIALIZED
- *    MEDIA_RECORDER_RECORDING             RECORDING
+ * The state machine of the media_recorder.
  */
 enum media_recorder_states {
+    // Error state.
     MEDIA_RECORDER_ERROR                 =      0,
+
+    // Recorder was just created.
     MEDIA_RECORDER_IDLE                  = 1 << 0,
+
+    // Recorder has been initialized.
     MEDIA_RECORDER_INITIALIZED           = 1 << 1,
+
+    // Configuration of the recorder has been completed.
     MEDIA_RECORDER_DATASOURCE_CONFIGURED = 1 << 2,
+
+    // Recorder is ready to start.
     MEDIA_RECORDER_PREPARED              = 1 << 3,
+
+    // Recording is in progress.
     MEDIA_RECORDER_RECORDING             = 1 << 4,
 };
 
 // The "msg" code passed to the listener in notify.
 enum media_recorder_event_type {
+    MEDIA_RECORDER_EVENT_LIST_START               = 1,
     MEDIA_RECORDER_EVENT_ERROR                    = 1,
-    MEDIA_RECORDER_EVENT_INFO                     = 2
+    MEDIA_RECORDER_EVENT_INFO                     = 2,
+    MEDIA_RECORDER_EVENT_LIST_END                 = 99,
+
+    // Track related event types
+    MEDIA_RECORDER_TRACK_EVENT_LIST_START         = 100,
+    MEDIA_RECORDER_TRACK_EVENT_ERROR              = 100,
+    MEDIA_RECORDER_TRACK_EVENT_INFO               = 101,
+    MEDIA_RECORDER_TRACK_EVENT_LIST_END           = 1000,
 };
 
+/*
+ * The (part of) "what" code passed to the listener in notify.
+ * When the error or info type is track specific, the what has
+ * the following layout:
+ * the left-most 16-bit is meant for error or info type.
+ * the right-most 4-bit is meant for track id.
+ * the rest is reserved.
+ *
+ * | track id | reserved |     error or info type     |
+ * 31         28         16                           0
+ *
+ */
 enum media_recorder_error_type {
-    MEDIA_RECORDER_ERROR_UNKNOWN                  = 1
+    MEDIA_RECORDER_ERROR_UNKNOWN                   = 1,
+
+    // Track related error type
+    MEDIA_RECORDER_TRACK_ERROR_LIST_START          = 100,
+    MEDIA_RECORDER_TRACK_ERROR_GENERAL             = 100,
+    MEDIA_RECORDER_ERROR_VIDEO_NO_SYNC_FRAME       = 200,
+    MEDIA_RECORDER_TRACK_ERROR_LIST_END            = 1000,
 };
 
 // The codes are distributed as follow:
@@ -141,11 +168,15 @@
 //
 enum media_recorder_info_type {
     MEDIA_RECORDER_INFO_UNKNOWN                   = 1,
+
     MEDIA_RECORDER_INFO_MAX_DURATION_REACHED      = 800,
     MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED      = 801,
-    MEDIA_RECORDER_INFO_COMPLETION_STATUS         = 802,
-    MEDIA_RECORDER_INFO_PROGRESS_FRAME_STATUS     = 803,
-    MEDIA_RECORDER_INFO_PROGRESS_TIME_STATUS      = 804,
+
+    // All track related informtional events start here
+    MEDIA_RECORDER_TRACK_INFO_LIST_START           = 1000,
+    MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS    = 1000,
+    MEDIA_RECORDER_TRACK_INFO_PROGRESS_IN_TIME     = 1001,
+    MEDIA_RECORDER_TRACK_INFO_LIST_END             = 2000,
 };
 
 // ----------------------------------------------------------------------------
diff --git a/include/media/stagefright/AudioPlayer.h b/include/media/stagefright/AudioPlayer.h
index d12ee9c..0b79324 100644
--- a/include/media/stagefright/AudioPlayer.h
+++ b/include/media/stagefright/AudioPlayer.h
@@ -108,6 +108,8 @@
 
     void reset();
 
+    uint32_t getNumFramesPendingPlayout() const;
+
     AudioPlayer(const AudioPlayer &);
     AudioPlayer &operator=(const AudioPlayer &);
 };
diff --git a/include/media/stagefright/CameraSource.h b/include/media/stagefright/CameraSource.h
index 4a39fbf..bb25bae 100644
--- a/include/media/stagefright/CameraSource.h
+++ b/include/media/stagefright/CameraSource.h
@@ -99,34 +99,6 @@
     virtual sp<MetaData> getFormat();
 
     /**
-     * Retrieve the total number of video buffers available from
-     * this source.
-     *
-     * This method is useful if these video buffers are used
-     * for passing video frame data to other media components,
-     * such as OMX video encoders, in order to eliminate the
-     * memcpy of the data.
-     *
-     * @return the total numbner of video buffers. Returns 0 to
-     *      indicate that this source does not make the video
-     *      buffer information availalble.
-     */
-    size_t getNumberOfVideoBuffers() const;
-
-    /**
-     * Retrieve the individual video buffer available from
-     * this source.
-     *
-     * @param index the index corresponding to the video buffer.
-     *      Valid range of the index is [0, n], where n =
-     *      getNumberOfVideoBuffers() - 1.
-     *
-     * @return the video buffer corresponding to the given index.
-     *      If index is out of range, 0 should be returned.
-     */
-    sp<IMemory> getVideoBuffer(size_t index) const;
-
-    /**
      * Tell whether this camera source stores meta data or real YUV
      * frame data in video buffers.
      *
diff --git a/include/media/stagefright/DataSource.h b/include/media/stagefright/DataSource.h
index f95e56a..6b6fcdf 100644
--- a/include/media/stagefright/DataSource.h
+++ b/include/media/stagefright/DataSource.h
@@ -75,15 +75,17 @@
     static void RegisterDefaultSniffers();
 
     // for DRM
-    virtual DecryptHandle* DrmInitialization() {
+    virtual sp<DecryptHandle> DrmInitialization() {
         return NULL;
     }
-    virtual void getDrmInfo(DecryptHandle **handle, DrmManagerClient **client) {};
+    virtual void getDrmInfo(sp<DecryptHandle> &handle, DrmManagerClient **client) {};
 
     virtual String8 getUri() {
         return String8();
     }
 
+    virtual String8 getMIMEType() const;
+
 protected:
     virtual ~DataSource() {}
 
diff --git a/include/media/stagefright/FileSource.h b/include/media/stagefright/FileSource.h
index 51a4343..6cf86dc 100644
--- a/include/media/stagefright/FileSource.h
+++ b/include/media/stagefright/FileSource.h
@@ -38,9 +38,9 @@
 
     virtual status_t getSize(off64_t *size);
 
-    virtual DecryptHandle* DrmInitialization();
+    virtual sp<DecryptHandle> DrmInitialization();
 
-    virtual void getDrmInfo(DecryptHandle **handle, DrmManagerClient **client);
+    virtual void getDrmInfo(sp<DecryptHandle> &handle, DrmManagerClient **client);
 
 protected:
     virtual ~FileSource();
@@ -52,7 +52,7 @@
     Mutex mLock;
 
     /*for DRM*/
-    DecryptHandle *mDecryptHandle;
+    sp<DecryptHandle> mDecryptHandle;
     DrmManagerClient *mDrmManagerClient;
     int64_t mDrmBufOffset;
     int64_t mDrmBufSize;
diff --git a/include/media/stagefright/MPEG4Writer.h b/include/media/stagefright/MPEG4Writer.h
index 5c5229d..15f86ea 100644
--- a/include/media/stagefright/MPEG4Writer.h
+++ b/include/media/stagefright/MPEG4Writer.h
@@ -157,7 +157,7 @@
     bool use32BitFileOffset() const;
     bool exceedsFileDurationLimit();
     bool isFileStreamable() const;
-    void trackProgressStatus(const Track* track, int64_t timeUs, status_t err = OK);
+    void trackProgressStatus(size_t trackId, int64_t timeUs, status_t err = OK);
     void writeCompositionMatrix(int32_t degrees);
 
     MPEG4Writer(const MPEG4Writer &);
diff --git a/include/media/stagefright/MediaDefs.h b/include/media/stagefright/MediaDefs.h
index 66dfff6..6a21627 100644
--- a/include/media/stagefright/MediaDefs.h
+++ b/include/media/stagefright/MediaDefs.h
@@ -45,6 +45,7 @@
 extern const char *MEDIA_MIMETYPE_CONTAINER_OGG;
 extern const char *MEDIA_MIMETYPE_CONTAINER_MATROSKA;
 extern const char *MEDIA_MIMETYPE_CONTAINER_MPEG2TS;
+extern const char *MEDIA_MIMETYPE_CONTAINER_AVI;
 
 extern const char *MEDIA_MIMETYPE_CONTAINER_WVM;
 
diff --git a/media/libeffects/lvm/lib/Android.mk b/media/libeffects/lvm/lib/Android.mk
index ff34707..f49267e 100644
--- a/media/libeffects/lvm/lib/Android.mk
+++ b/media/libeffects/lvm/lib/Android.mk
@@ -105,7 +105,7 @@
 
 LOCAL_MODULE:= libmusicbundle
 
-LOCAL_PRELINK_MODULE := false
+
 
 LOCAL_C_INCLUDES += \
     $(LOCAL_PATH)/Eq/lib \
@@ -168,7 +168,7 @@
 
 LOCAL_MODULE:= libreverb
 
-LOCAL_PRELINK_MODULE := false
+
 
 LOCAL_C_INCLUDES += \
     $(LOCAL_PATH)/Reverb/lib \
diff --git a/media/libeffects/lvm/wrapper/Android.mk b/media/libeffects/lvm/wrapper/Android.mk
index 2e9b9b4..99cfdfa 100644
--- a/media/libeffects/lvm/wrapper/Android.mk
+++ b/media/libeffects/lvm/wrapper/Android.mk
@@ -13,7 +13,7 @@
 
 LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/soundfx
 
-LOCAL_PRELINK_MODULE := false
+
 
 LOCAL_STATIC_LIBRARIES += libmusicbundle
 
@@ -47,7 +47,7 @@
 
 LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/soundfx
 
-LOCAL_PRELINK_MODULE := false
+
 
 LOCAL_STATIC_LIBRARIES += libreverb
 
diff --git a/media/libeffects/visualizer/Android.mk b/media/libeffects/visualizer/Android.mk
index e6ff654..3a0f438 100644
--- a/media/libeffects/visualizer/Android.mk
+++ b/media/libeffects/visualizer/Android.mk
@@ -25,6 +25,6 @@
 LOCAL_C_INCLUDES := \
 	$(call include-path-for, graphics corecg)
 
-LOCAL_PRELINK_MODULE := false
+
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk
index fd4c6c6..ca7441a 100644
--- a/media/libmedia/Android.mk
+++ b/media/libmedia/Android.mk
@@ -33,11 +33,12 @@
     IEffectClient.cpp \
     AudioEffect.cpp \
     Visualizer.cpp \
+    MemoryLeakTrackUtil.cpp \
     fixedfft.cpp.arm
 
 LOCAL_SHARED_LIBRARIES := \
 	libui libcutils libutils libbinder libsonivox libicuuc libexpat \
-        libsurfaceflinger_client libcamera_client libstagefright_foundation \
+        libcamera_client libstagefright_foundation \
         libgui
 
 LOCAL_MODULE:= libmedia
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index a18bedb..cee1c75 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -722,9 +722,12 @@
     // Manage overrun callback
     if (mActive && (cblk->framesAvailable() == 0)) {
         LOGV("Overrun user: %x, server: %x, flags %04x", cblk->user, cblk->server, cblk->flags);
+        AutoMutex _l(cblk->lock);
         if ((cblk->flags & CBLK_UNDERRUN_MSK) == CBLK_UNDERRUN_OFF) {
-            mCbf(EVENT_OVERRUN, mUserData, 0);
             cblk->flags |= CBLK_UNDERRUN_ON;
+            cblk->lock.unlock();
+            mCbf(EVENT_OVERRUN, mUserData, 0);
+            cblk->lock.lock();
         }
     }
 
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 8d8f67b..fb2ee0f 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -329,6 +329,7 @@
     if (mActive == 0) {
         mActive = 1;
         mNewPosition = cblk->server + mUpdatePeriod;
+        cblk->lock.lock();
         cblk->bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS;
         cblk->waitTimeMs = 0;
         cblk->flags &= ~CBLK_DISABLED_ON;
@@ -339,7 +340,6 @@
         }
 
         LOGV("start %p before lock cblk %p", this, mCblk);
-        cblk->lock.lock();
         if (!(cblk->flags & CBLK_INVALID_MSK)) {
             cblk->lock.unlock();
             status = mAudioTrack->start();
@@ -546,12 +546,13 @@
     }
 
     if (loopStart >= loopEnd ||
-        loopEnd - loopStart > cblk->frameCount) {
+        loopEnd - loopStart > cblk->frameCount ||
+        cblk->server > loopStart) {
         LOGE("setLoop invalid value: loopStart %d, loopEnd %d, loopCount %d, framecount %d, user %d", loopStart, loopEnd, loopCount, cblk->frameCount, cblk->user);
         return BAD_VALUE;
     }
 
-    if ((mSharedBuffer != 0) && (loopEnd   > cblk->frameCount)) {
+    if ((mSharedBuffer != 0) && (loopEnd > cblk->frameCount)) {
         LOGE("setLoop invalid value: loop markers beyond data: loopStart %d, loopEnd %d, framecount %d",
             loopStart, loopEnd, cblk->frameCount);
         return BAD_VALUE;
@@ -825,6 +826,12 @@
 
     uint32_t framesAvail = cblk->framesAvailable();
 
+    cblk->lock.lock();
+    if (cblk->flags & CBLK_INVALID_MSK) {
+        goto create_new_track;
+    }
+    cblk->lock.unlock();
+
     if (framesAvail == 0) {
         cblk->lock.lock();
         goto start_loop_here;
@@ -893,9 +900,14 @@
 
     // restart track if it was disabled by audioflinger due to previous underrun
     if (mActive && (cblk->flags & CBLK_DISABLED_MSK)) {
-        cblk->flags &= ~CBLK_DISABLED_ON;
-        LOGW("obtainBuffer() track %p disabled, restarting", this);
-        mAudioTrack->start();
+        AutoMutex _l(cblk->lock);
+        if (mActive && (cblk->flags & CBLK_DISABLED_MSK)) {
+            cblk->flags &= ~CBLK_DISABLED_ON;
+            cblk->lock.unlock();
+            LOGW("obtainBuffer() track %p disabled, restarting", this);
+            mAudioTrack->start();
+            cblk->lock.lock();
+        }
     }
 
     cblk->waitTimeMs = 0;
@@ -957,9 +969,10 @@
     ssize_t written = 0;
     const int8_t *src = (const int8_t *)buffer;
     Buffer audioBuffer;
+    size_t frameSz = (size_t)frameSize();
 
     do {
-        audioBuffer.frameCount = userSize/frameSize();
+        audioBuffer.frameCount = userSize/frameSz;
 
         // Calling obtainBuffer() with a negative wait count causes
         // an (almost) infinite wait time.
@@ -991,7 +1004,7 @@
         written += toWrite;
 
         releaseBuffer(&audioBuffer);
-    } while (userSize);
+    } while (userSize >= frameSz);
 
     return written;
 }
@@ -1015,12 +1028,15 @@
     // Manage underrun callback
     if (mActive && (cblk->framesReady() == 0)) {
         LOGV("Underrun user: %x, server: %x, flags %04x", cblk->user, cblk->server, cblk->flags);
+        AutoMutex _l(cblk->lock);
         if ((cblk->flags & CBLK_UNDERRUN_MSK) == CBLK_UNDERRUN_OFF) {
+            cblk->flags |= CBLK_UNDERRUN_ON;
+            cblk->lock.unlock();
             mCbf(EVENT_UNDERRUN, mUserData, 0);
             if (cblk->server == cblk->frameCount) {
                 mCbf(EVENT_BUFFER_END, mUserData, 0);
             }
-            cblk->flags |= CBLK_UNDERRUN_ON;
+            cblk->lock.lock();
             if (mSharedBuffer != 0) return false;
         }
     }
@@ -1139,6 +1155,7 @@
              fromStart ? "start()" : "obtainBuffer()");
 
         cblk->flags |= CBLK_RESTORING_ON;
+
         // signal old cblk condition so that other threads waiting for available buffers stop
         // waiting now
         cblk->cv.broadcast();
@@ -1158,10 +1175,20 @@
                                false);
 
         if (result == NO_ERROR) {
+            // restore write index and set other indexes to reflect empty buffer status
+            mCblk->user = cblk->user;
+            mCblk->server = cblk->user;
+            mCblk->userBase = cblk->user;
+            mCblk->serverBase = cblk->user;
+            // restore loop: this is not guaranteed to succeed if new frame count is not
+            // compatible with loop length
+            setLoop_l(cblk->loopStart, cblk->loopEnd, cblk->loopCount);
             if (!fromStart) {
                 mCblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
             }
-            result = mAudioTrack->start();
+            if (mActive) {
+                result = mAudioTrack->start();
+            }
             if (fromStart && result == NO_ERROR) {
                 mNewPosition = mCblk->server + mUpdatePeriod;
             }
@@ -1279,7 +1306,12 @@
     this->user = u;
 
     // Clear flow control error condition as new data has been written/read to/from buffer.
-    flags &= ~CBLK_UNDERRUN_MSK;
+    if (flags & CBLK_UNDERRUN_MSK) {
+        AutoMutex _l(lock);
+        if (flags & CBLK_UNDERRUN_MSK) {
+            flags &= ~CBLK_UNDERRUN_MSK;
+        }
+    }
 
     return u;
 }
diff --git a/media/libmedia/IMediaMetadataRetriever.cpp b/media/libmedia/IMediaMetadataRetriever.cpp
index d5298c9..ebe821f 100644
--- a/media/libmedia/IMediaMetadataRetriever.cpp
+++ b/media/libmedia/IMediaMetadataRetriever.cpp
@@ -20,6 +20,7 @@
 #include <binder/Parcel.h>
 #include <SkBitmap.h>
 #include <media/IMediaMetadataRetriever.h>
+#include <utils/String8.h>
 
 // The binder is supposed to propagate the scheduler group across
 // the binder interface so that remote calls are executed with
@@ -102,11 +103,24 @@
         remote()->transact(DISCONNECT, data, &reply);
     }
 
-    status_t setDataSource(const char* srcUrl)
+    status_t setDataSource(
+            const char *srcUrl, const KeyedVector<String8, String8> *headers)
     {
         Parcel data, reply;
         data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
         data.writeCString(srcUrl);
+
+        if (headers == NULL) {
+            data.writeInt32(0);
+        } else {
+            // serialize the headers
+            data.writeInt32(headers->size());
+            for (size_t i = 0; i < headers->size(); ++i) {
+                data.writeString8(headers->keyAt(i));
+                data.writeString8(headers->valueAt(i));
+            }
+        }
+
         remote()->transact(SET_DATA_SOURCE_URL, data, &reply);
         return reply.readInt32();
     }
@@ -188,7 +202,18 @@
         case SET_DATA_SOURCE_URL: {
             CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
             const char* srcUrl = data.readCString();
-            reply->writeInt32(setDataSource(srcUrl));
+
+            KeyedVector<String8, String8> headers;
+            int32_t numHeaders = data.readInt32();
+            for (int i = 0; i < numHeaders; ++i) {
+                String8 key = data.readString8();
+                String8 value = data.readString8();
+                headers.add(key, value);
+            }
+
+            reply->writeInt32(
+                    setDataSource(srcUrl, numHeaders > 0 ? &headers : NULL));
+
             return NO_ERROR;
         } break;
         case SET_DATA_SOURCE_FD: {
diff --git a/media/libmedia/MemoryLeakTrackUtil.cpp b/media/libmedia/MemoryLeakTrackUtil.cpp
new file mode 100644
index 0000000..6a108ae
--- /dev/null
+++ b/media/libmedia/MemoryLeakTrackUtil.cpp
@@ -0,0 +1,169 @@
+/*
+ * Copyright 2011, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <media/MemoryLeakTrackUtil.h>
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+/*
+ * The code here originally resided in MediaPlayerService.cpp and was
+ * shamelessly copied over to support memory leak tracking from
+ * multiple places.
+ */
+namespace android {
+
+#if defined(__arm__)
+
+extern "C" void get_malloc_leak_info(uint8_t** info, size_t* overallSize,
+        size_t* infoSize, size_t* totalMemory, size_t* backtraceSize);
+
+extern "C" void free_malloc_leak_info(uint8_t* info);
+
+// Use the String-class below instead of String8 to allocate all memory
+// beforehand and not reenter the heap while we are examining it...
+struct MyString8 {
+    static const size_t MAX_SIZE = 256 * 1024;
+
+    MyString8()
+        : mPtr((char *)malloc(MAX_SIZE)) {
+        *mPtr = '\0';
+    }
+
+    ~MyString8() {
+        free(mPtr);
+    }
+
+    void append(const char *s) {
+        strcat(mPtr, s);
+    }
+
+    const char *string() const {
+        return mPtr;
+    }
+
+    size_t size() const {
+        return strlen(mPtr);
+    }
+
+private:
+    char *mPtr;
+
+    MyString8(const MyString8 &);
+    MyString8 &operator=(const MyString8 &);
+};
+
+void dumpMemoryAddresses(int fd)
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    MyString8 result;
+
+    typedef struct {
+        size_t size;
+        size_t dups;
+        intptr_t * backtrace;
+    } AllocEntry;
+
+    uint8_t *info = NULL;
+    size_t overallSize = 0;
+    size_t infoSize = 0;
+    size_t totalMemory = 0;
+    size_t backtraceSize = 0;
+
+    get_malloc_leak_info(&info, &overallSize, &infoSize, &totalMemory, &backtraceSize);
+    if (info) {
+        uint8_t *ptr = info;
+        size_t count = overallSize / infoSize;
+
+        snprintf(buffer, SIZE, " Allocation count %i\n", count);
+        result.append(buffer);
+        snprintf(buffer, SIZE, " Total memory %i\n", totalMemory);
+        result.append(buffer);
+
+        AllocEntry * entries = new AllocEntry[count];
+
+        for (size_t i = 0; i < count; i++) {
+            // Each entry should be size_t, size_t, intptr_t[backtraceSize]
+            AllocEntry *e = &entries[i];
+
+            e->size = *reinterpret_cast<size_t *>(ptr);
+            ptr += sizeof(size_t);
+
+            e->dups = *reinterpret_cast<size_t *>(ptr);
+            ptr += sizeof(size_t);
+
+            e->backtrace = reinterpret_cast<intptr_t *>(ptr);
+            ptr += sizeof(intptr_t) * backtraceSize;
+        }
+
+        // Now we need to sort the entries.  They come sorted by size but
+        // not by stack trace which causes problems using diff.
+        bool moved;
+        do {
+            moved = false;
+            for (size_t i = 0; i < (count - 1); i++) {
+                AllocEntry *e1 = &entries[i];
+                AllocEntry *e2 = &entries[i+1];
+
+                bool swap = e1->size < e2->size;
+                if (e1->size == e2->size) {
+                    for(size_t j = 0; j < backtraceSize; j++) {
+                        if (e1->backtrace[j] == e2->backtrace[j]) {
+                            continue;
+                        }
+                        swap = e1->backtrace[j] < e2->backtrace[j];
+                        break;
+                    }
+                }
+                if (swap) {
+                    AllocEntry t = entries[i];
+                    entries[i] = entries[i+1];
+                    entries[i+1] = t;
+                    moved = true;
+                }
+            }
+        } while (moved);
+
+        for (size_t i = 0; i < count; i++) {
+            AllocEntry *e = &entries[i];
+
+            snprintf(buffer, SIZE, "size %8i, dup %4i, ", e->size, e->dups);
+            result.append(buffer);
+            for (size_t ct = 0; (ct < backtraceSize) && e->backtrace[ct]; ct++) {
+                if (ct) {
+                    result.append(", ");
+                }
+                snprintf(buffer, SIZE, "0x%08x", e->backtrace[ct]);
+                result.append(buffer);
+            }
+            result.append("\n");
+        }
+
+        delete[] entries;
+        free_malloc_leak_info(info);
+    }
+
+    write(fd, result.string(), result.size());
+}
+
+#else
+// Does nothing
+void dumpMemoryAddresses(int fd) {}
+
+#endif
+}  // namespace android
diff --git a/media/libmedia/mediametadataretriever.cpp b/media/libmedia/mediametadataretriever.cpp
index 8dfcb3b..cee06ab 100644
--- a/media/libmedia/mediametadataretriever.cpp
+++ b/media/libmedia/mediametadataretriever.cpp
@@ -92,7 +92,8 @@
     }
 }
 
-status_t MediaMetadataRetriever::setDataSource(const char* srcUrl)
+status_t MediaMetadataRetriever::setDataSource(
+        const char *srcUrl, const KeyedVector<String8, String8> *headers)
 {
     LOGV("setDataSource");
     Mutex::Autolock _l(mLock);
@@ -105,7 +106,7 @@
         return UNKNOWN_ERROR;
     }
     LOGV("data source (%s)", srcUrl);
-    return mRetriever->setDataSource(srcUrl);
+    return mRetriever->setDataSource(srcUrl, headers);
 }
 
 status_t MediaMetadataRetriever::setDataSource(int fd, int64_t offset, int64_t length)
diff --git a/media/libmediaplayerservice/Android.mk b/media/libmediaplayerservice/Android.mk
index e65f6d8..fadad28 100644
--- a/media/libmediaplayerservice/Android.mk
+++ b/media/libmediaplayerservice/Android.mk
@@ -31,8 +31,7 @@
 	libandroid_runtime    			\
 	libstagefright        			\
 	libstagefright_omx    			\
-	libstagefright_foundation               \
-	libsurfaceflinger_client                \
+	libstagefright_foundation       \
 	libgui
 
 LOCAL_STATIC_LIBRARIES := \
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 0156634..5eecbde 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -51,6 +51,7 @@
 #include <media/MediaMetadataRetrieverInterface.h>
 #include <media/Metadata.h>
 #include <media/AudioTrack.h>
+#include <media/MemoryLeakTrackUtil.h>
 
 #include <private/android_filesystem_config.h>
 
@@ -392,139 +393,6 @@
 #endif
 }
 
-#if defined(__arm__)
-extern "C" void get_malloc_leak_info(uint8_t** info, size_t* overallSize,
-        size_t* infoSize, size_t* totalMemory, size_t* backtraceSize);
-extern "C" void free_malloc_leak_info(uint8_t* info);
-
-// Use the String-class below instead of String8 to allocate all memory
-// beforehand and not reenter the heap while we are examining it...
-struct MyString8 {
-    static const size_t MAX_SIZE = 256 * 1024;
-
-    MyString8()
-        : mPtr((char *)malloc(MAX_SIZE)) {
-        *mPtr = '\0';
-    }
-
-    ~MyString8() {
-        free(mPtr);
-    }
-
-    void append(const char *s) {
-        strcat(mPtr, s);
-    }
-
-    const char *string() const {
-        return mPtr;
-    }
-
-    size_t size() const {
-        return strlen(mPtr);
-    }
-
-private:
-    char *mPtr;
-
-    MyString8(const MyString8 &);
-    MyString8 &operator=(const MyString8 &);
-};
-
-void memStatus(int fd, const Vector<String16>& args)
-{
-    const size_t SIZE = 256;
-    char buffer[SIZE];
-    MyString8 result;
-
-    typedef struct {
-        size_t size;
-        size_t dups;
-        intptr_t * backtrace;
-    } AllocEntry;
-
-    uint8_t *info = NULL;
-    size_t overallSize = 0;
-    size_t infoSize = 0;
-    size_t totalMemory = 0;
-    size_t backtraceSize = 0;
-
-    get_malloc_leak_info(&info, &overallSize, &infoSize, &totalMemory, &backtraceSize);
-    if (info) {
-        uint8_t *ptr = info;
-        size_t count = overallSize / infoSize;
-
-        snprintf(buffer, SIZE, " Allocation count %i\n", count);
-        result.append(buffer);
-        snprintf(buffer, SIZE, " Total memory %i\n", totalMemory);
-        result.append(buffer);
-
-        AllocEntry * entries = new AllocEntry[count];
-
-        for (size_t i = 0; i < count; i++) {
-            // Each entry should be size_t, size_t, intptr_t[backtraceSize]
-            AllocEntry *e = &entries[i];
-
-            e->size = *reinterpret_cast<size_t *>(ptr);
-            ptr += sizeof(size_t);
-
-            e->dups = *reinterpret_cast<size_t *>(ptr);
-            ptr += sizeof(size_t);
-
-            e->backtrace = reinterpret_cast<intptr_t *>(ptr);
-            ptr += sizeof(intptr_t) * backtraceSize;
-        }
-
-        // Now we need to sort the entries.  They come sorted by size but
-        // not by stack trace which causes problems using diff.
-        bool moved;
-        do {
-            moved = false;
-            for (size_t i = 0; i < (count - 1); i++) {
-                AllocEntry *e1 = &entries[i];
-                AllocEntry *e2 = &entries[i+1];
-
-                bool swap = e1->size < e2->size;
-                if (e1->size == e2->size) {
-                    for(size_t j = 0; j < backtraceSize; j++) {
-                        if (e1->backtrace[j] == e2->backtrace[j]) {
-                            continue;
-                        }
-                        swap = e1->backtrace[j] < e2->backtrace[j];
-                        break;
-                    }
-                }
-                if (swap) {
-                    AllocEntry t = entries[i];
-                    entries[i] = entries[i+1];
-                    entries[i+1] = t;
-                    moved = true;
-                }
-            }
-        } while (moved);
-
-        for (size_t i = 0; i < count; i++) {
-            AllocEntry *e = &entries[i];
-
-            snprintf(buffer, SIZE, "size %8i, dup %4i, ", e->size, e->dups);
-            result.append(buffer);
-            for (size_t ct = 0; (ct < backtraceSize) && e->backtrace[ct]; ct++) {
-                if (ct) {
-                    result.append(", ");
-                }
-                snprintf(buffer, SIZE, "0x%08x", e->backtrace[ct]);
-                result.append(buffer);
-            }
-            result.append("\n");
-        }
-
-        delete[] entries;
-        free_malloc_leak_info(info);
-    }
-
-    write(fd, result.string(), result.size());
-}
-#endif
-
 status_t MediaPlayerService::dump(int fd, const Vector<String16>& args)
 {
     const size_t SIZE = 256;
@@ -623,7 +491,6 @@
             result.append("\n");
         }
 
-#if defined(__arm__)
         bool dumpMem = false;
         for (size_t i = 0; i < args.size(); i++) {
             if (args[i] == String16("-m")) {
@@ -631,9 +498,8 @@
             }
         }
         if (dumpMem) {
-            memStatus(fd, args);
+            dumpMemoryAddresses(fd);
         }
-#endif
     }
     write(fd, result.string(), result.size());
     return NO_ERROR;
diff --git a/media/libmediaplayerservice/MetadataRetrieverClient.cpp b/media/libmediaplayerservice/MetadataRetrieverClient.cpp
index 5fcf2a7..8f776b4 100644
--- a/media/libmediaplayerservice/MetadataRetrieverClient.cpp
+++ b/media/libmediaplayerservice/MetadataRetrieverClient.cpp
@@ -120,7 +120,8 @@
     return p;
 }
 
-status_t MetadataRetrieverClient::setDataSource(const char *url)
+status_t MetadataRetrieverClient::setDataSource(
+        const char *url, const KeyedVector<String8, String8> *headers)
 {
     LOGV("setDataSource(%s)", url);
     Mutex::Autolock lock(mLock);
@@ -131,7 +132,7 @@
     LOGV("player type = %d", playerType);
     sp<MediaMetadataRetrieverBase> p = createRetriever(playerType);
     if (p == NULL) return NO_INIT;
-    status_t ret = p->setDataSource(url);
+    status_t ret = p->setDataSource(url, headers);
     if (ret == NO_ERROR) mRetriever = p;
     return ret;
 }
diff --git a/media/libmediaplayerservice/MetadataRetrieverClient.h b/media/libmediaplayerservice/MetadataRetrieverClient.h
index b834715..f08f933 100644
--- a/media/libmediaplayerservice/MetadataRetrieverClient.h
+++ b/media/libmediaplayerservice/MetadataRetrieverClient.h
@@ -41,7 +41,10 @@
     // Implements IMediaMetadataRetriever interface
     // These methods are called in IMediaMetadataRetriever.cpp?
     virtual void                    disconnect();
-    virtual status_t                setDataSource(const char *url);
+
+    virtual status_t                setDataSource(
+            const char *url, const KeyedVector<String8, String8> *headers);
+
     virtual status_t                setDataSource(int fd, int64_t offset, int64_t length);
     virtual sp<IMemory>             getFrameAtTime(int64_t timeUs, int option);
     virtual sp<IMemory>             extractAlbumArt();
diff --git a/media/libmediaplayerservice/MidiMetadataRetriever.cpp b/media/libmediaplayerservice/MidiMetadataRetriever.cpp
index ad95fac..aaf2d18 100644
--- a/media/libmediaplayerservice/MidiMetadataRetriever.cpp
+++ b/media/libmediaplayerservice/MidiMetadataRetriever.cpp
@@ -35,7 +35,8 @@
     mMetadataValues[0][0] = '\0';
 }
 
-status_t MidiMetadataRetriever::setDataSource(const char *url)
+status_t MidiMetadataRetriever::setDataSource(
+        const char *url, const KeyedVector<String8, String8> *headers)
 {
     LOGV("setDataSource: %s", url? url: "NULL pointer");
     Mutex::Autolock lock(mLock);
@@ -43,8 +44,7 @@
     if (mMidiPlayer == 0) {
         mMidiPlayer = new MidiFile();
     }
-    // TODO: support headers in MetadataRetriever interface!
-    return mMidiPlayer->setDataSource(url, NULL /* headers */);
+    return mMidiPlayer->setDataSource(url, headers);
 }
 
 status_t MidiMetadataRetriever::setDataSource(int fd, int64_t offset, int64_t length)
diff --git a/media/libmediaplayerservice/MidiMetadataRetriever.h b/media/libmediaplayerservice/MidiMetadataRetriever.h
index 73ff347..4cee42d 100644
--- a/media/libmediaplayerservice/MidiMetadataRetriever.h
+++ b/media/libmediaplayerservice/MidiMetadataRetriever.h
@@ -31,7 +31,9 @@
                                    MidiMetadataRetriever() {}
                                    ~MidiMetadataRetriever() {}
 
-    virtual status_t                setDataSource(const char *url);
+    virtual status_t                setDataSource(
+            const char *url, const KeyedVector<String8, String8> *headers);
+
     virtual status_t                setDataSource(int fd, int64_t offset, int64_t length);
     virtual const char*             extractMetadata(int keyCode);
 
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
index 369a3a8..828e008 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -198,18 +198,21 @@
 }
 
 void NuPlayer::Renderer::onDrainAudioQueue() {
-    uint32_t numFramesPlayed;
-    CHECK_EQ(mAudioSink->getPosition(&numFramesPlayed), (status_t)OK);
 
-    ssize_t numFramesAvailableToWrite =
-        mAudioSink->frameCount() - (mNumFramesWritten - numFramesPlayed);
+    for (;;) {
+        uint32_t numFramesPlayed;
+        CHECK_EQ(mAudioSink->getPosition(&numFramesPlayed), (status_t)OK);
 
-    CHECK_GE(numFramesAvailableToWrite, 0);
+        ssize_t numFramesAvailableToWrite =
+            mAudioSink->frameCount() - (mNumFramesWritten - numFramesPlayed);
 
-    size_t numBytesAvailableToWrite =
-        numFramesAvailableToWrite * mAudioSink->frameSize();
+        size_t numBytesAvailableToWrite =
+            numFramesAvailableToWrite * mAudioSink->frameSize();
 
-    while (numBytesAvailableToWrite > 0) {
+        if (numBytesAvailableToWrite == 0) {
+            break;
+        }
+
         if (mAudioQueue.empty()) {
             break;
         }
@@ -264,10 +267,10 @@
         if (entry->mOffset == entry->mBuffer->size()) {
             entry->mNotifyConsumed->post();
             mAudioQueue.erase(mAudioQueue.begin());
+
             entry = NULL;
         }
 
-        numBytesAvailableToWrite -= copy;
         mNumFramesWritten += copy / mAudioSink->frameSize();
     }
 
diff --git a/media/libstagefright/AMRWriter.cpp b/media/libstagefright/AMRWriter.cpp
index 0db3d1d..b10d52c 100644
--- a/media/libstagefright/AMRWriter.cpp
+++ b/media/libstagefright/AMRWriter.cpp
@@ -37,7 +37,7 @@
       mPaused(false),
       mResumed(false) {
 
-    mFd = open(filename, O_CREAT | O_LARGEFILE | O_TRUNC);
+    mFd = open(filename, O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR);
     if (mFd >= 0) {
         mInitCheck = OK;
     }
@@ -269,7 +269,7 @@
     }
 
     if (stoppedPrematurely) {
-        notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_COMPLETION_STATUS, UNKNOWN_ERROR);
+        notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS, UNKNOWN_ERROR);
     }
 
     close(mFd);
diff --git a/media/libstagefright/AVIExtractor.cpp b/media/libstagefright/AVIExtractor.cpp
new file mode 100644
index 0000000..6313ca3
--- /dev/null
+++ b/media/libstagefright/AVIExtractor.cpp
@@ -0,0 +1,922 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "AVIExtractor"
+#include <utils/Log.h>
+
+#include "include/AVIExtractor.h"
+
+#include <binder/ProcessState.h>
+#include <media/stagefright/foundation/hexdump.h>
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/DataSource.h>
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MediaBufferGroup.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/Utils.h>
+
+namespace android {
+
+struct AVIExtractor::AVISource : public MediaSource {
+    AVISource(const sp<AVIExtractor> &extractor, size_t trackIndex);
+
+    virtual status_t start(MetaData *params);
+    virtual status_t stop();
+
+    virtual sp<MetaData> getFormat();
+
+    virtual status_t read(
+            MediaBuffer **buffer, const ReadOptions *options);
+
+protected:
+    virtual ~AVISource();
+
+private:
+    sp<AVIExtractor> mExtractor;
+    size_t mTrackIndex;
+    const AVIExtractor::Track &mTrack;
+    MediaBufferGroup *mBufferGroup;
+    size_t mSampleIndex;
+
+    DISALLOW_EVIL_CONSTRUCTORS(AVISource);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+AVIExtractor::AVISource::AVISource(
+        const sp<AVIExtractor> &extractor, size_t trackIndex)
+    : mExtractor(extractor),
+      mTrackIndex(trackIndex),
+      mTrack(mExtractor->mTracks.itemAt(trackIndex)),
+      mBufferGroup(NULL) {
+}
+
+AVIExtractor::AVISource::~AVISource() {
+    if (mBufferGroup) {
+        stop();
+    }
+}
+
+status_t AVIExtractor::AVISource::start(MetaData *params) {
+    CHECK(!mBufferGroup);
+
+    mBufferGroup = new MediaBufferGroup;
+
+    mBufferGroup->add_buffer(new MediaBuffer(mTrack.mMaxSampleSize));
+    mBufferGroup->add_buffer(new MediaBuffer(mTrack.mMaxSampleSize));
+    mSampleIndex = 0;
+
+    return OK;
+}
+
+status_t AVIExtractor::AVISource::stop() {
+    CHECK(mBufferGroup);
+
+    delete mBufferGroup;
+    mBufferGroup = NULL;
+
+    return OK;
+}
+
+sp<MetaData> AVIExtractor::AVISource::getFormat() {
+    return mTrack.mMeta;
+}
+
+status_t AVIExtractor::AVISource::read(
+        MediaBuffer **buffer, const ReadOptions *options) {
+    CHECK(mBufferGroup);
+
+    *buffer = NULL;
+
+    int64_t seekTimeUs;
+    ReadOptions::SeekMode seekMode;
+    if (options && options->getSeekTo(&seekTimeUs, &seekMode)) {
+        status_t err =
+            mExtractor->getSampleIndexAtTime(
+                    mTrackIndex, seekTimeUs, seekMode, &mSampleIndex);
+
+        if (err != OK) {
+            return ERROR_END_OF_STREAM;
+        }
+    }
+
+    int64_t timeUs =
+        (mSampleIndex * 1000000ll * mTrack.mRate) / mTrack.mScale;
+
+    off64_t offset;
+    size_t size;
+    bool isKey;
+    status_t err = mExtractor->getSampleInfo(
+            mTrackIndex, mSampleIndex, &offset, &size, &isKey);
+
+    ++mSampleIndex;
+
+    if (err != OK) {
+        return ERROR_END_OF_STREAM;
+    }
+
+    MediaBuffer *out;
+    CHECK_EQ(mBufferGroup->acquire_buffer(&out), (status_t)OK);
+
+    ssize_t n = mExtractor->mDataSource->readAt(offset, out->data(), size);
+
+    if (n < (ssize_t)size) {
+        return n < 0 ? (status_t)n : (status_t)ERROR_MALFORMED;
+    }
+
+    out->set_range(0, size);
+
+    out->meta_data()->setInt64(kKeyTime, timeUs);
+
+    if (isKey) {
+        out->meta_data()->setInt32(kKeyIsSyncFrame, 1);
+    }
+
+    *buffer = out;
+
+    return OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+AVIExtractor::AVIExtractor(const sp<DataSource> &dataSource)
+    : mDataSource(dataSource) {
+    mInitCheck = parseHeaders();
+
+    if (mInitCheck != OK) {
+        mTracks.clear();
+    }
+}
+
+AVIExtractor::~AVIExtractor() {
+}
+
+size_t AVIExtractor::countTracks() {
+    return mTracks.size();
+}
+
+sp<MediaSource> AVIExtractor::getTrack(size_t index) {
+    return index < mTracks.size() ? new AVISource(this, index) : NULL;
+}
+
+sp<MetaData> AVIExtractor::getTrackMetaData(
+        size_t index, uint32_t flags) {
+    return index < mTracks.size() ? mTracks.editItemAt(index).mMeta : NULL;
+}
+
+sp<MetaData> AVIExtractor::getMetaData() {
+    sp<MetaData> meta = new MetaData;
+
+    if (mInitCheck == OK) {
+        meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_AVI);
+    }
+
+    return meta;
+}
+
+status_t AVIExtractor::parseHeaders() {
+    mTracks.clear();
+    mMovieOffset = 0;
+    mFoundIndex = false;
+    mOffsetsAreAbsolute = false;
+
+    ssize_t res = parseChunk(0ll, -1ll);
+
+    if (res < 0) {
+        return (status_t)res;
+    }
+
+    if (mMovieOffset == 0ll || !mFoundIndex) {
+        return ERROR_MALFORMED;
+    }
+
+    return OK;
+}
+
+ssize_t AVIExtractor::parseChunk(off64_t offset, off64_t size, int depth) {
+    if (size >= 0 && size < 8) {
+        return ERROR_MALFORMED;
+    }
+
+    uint8_t tmp[12];
+    ssize_t n = mDataSource->readAt(offset, tmp, 8);
+
+    if (n < 8) {
+        return (n < 0) ? n : (ssize_t)ERROR_MALFORMED;
+    }
+
+    uint32_t fourcc = U32_AT(tmp);
+    uint32_t chunkSize = U32LE_AT(&tmp[4]);
+
+    if (size >= 0 && chunkSize + 8 > size) {
+        return ERROR_MALFORMED;
+    }
+
+    static const char kPrefix[] = "                              ";
+    const char *prefix = &kPrefix[strlen(kPrefix) - 2 * depth];
+
+    if (fourcc == FOURCC('L', 'I', 'S', 'T')
+            || fourcc == FOURCC('R', 'I', 'F', 'F')) {
+        // It's a list of chunks
+
+        if (size >= 0 && size < 12) {
+            return ERROR_MALFORMED;
+        }
+
+        n = mDataSource->readAt(offset + 8, &tmp[8], 4);
+
+        if (n < 4) {
+            return (n < 0) ? n : (ssize_t)ERROR_MALFORMED;
+        }
+
+        uint32_t subFourcc = U32_AT(&tmp[8]);
+
+        LOGV("%s offset 0x%08llx LIST of '%c%c%c%c', size %d",
+             prefix,
+             offset,
+             (char)(subFourcc >> 24),
+             (char)((subFourcc >> 16) & 0xff),
+             (char)((subFourcc >> 8) & 0xff),
+             (char)(subFourcc & 0xff),
+             chunkSize - 4);
+
+        if (subFourcc == FOURCC('m', 'o', 'v', 'i')) {
+            // We're not going to parse this, but will take note of the
+            // offset.
+
+            mMovieOffset = offset;
+        } else {
+            off64_t subOffset = offset + 12;
+            off64_t subOffsetLimit = subOffset + chunkSize - 4;
+            while (subOffset < subOffsetLimit) {
+                ssize_t res =
+                    parseChunk(subOffset, subOffsetLimit - subOffset, depth + 1);
+
+                if (res < 0) {
+                    return res;
+                }
+
+                subOffset += res;
+            }
+        }
+    } else {
+        LOGV("%s offset 0x%08llx CHUNK '%c%c%c%c'",
+             prefix,
+             offset,
+             (char)(fourcc >> 24),
+             (char)((fourcc >> 16) & 0xff),
+             (char)((fourcc >> 8) & 0xff),
+             (char)(fourcc & 0xff));
+
+        status_t err = OK;
+
+        switch (fourcc) {
+            case FOURCC('s', 't', 'r', 'h'):
+            {
+                err = parseStreamHeader(offset + 8, chunkSize);
+                break;
+            }
+
+            case FOURCC('s', 't', 'r', 'f'):
+            {
+                err = parseStreamFormat(offset + 8, chunkSize);
+                break;
+            }
+
+            case FOURCC('i', 'd', 'x', '1'):
+            {
+                err = parseIndex(offset + 8, chunkSize);
+                break;
+            }
+
+            default:
+                break;
+        }
+
+        if (err != OK) {
+            return err;
+        }
+    }
+
+    if (chunkSize & 1) {
+        ++chunkSize;
+    }
+
+    return chunkSize + 8;
+}
+
+static const char *GetMIMETypeForHandler(uint32_t handler) {
+    switch (handler) {
+        // Wow... shamelessly copied from
+        // http://wiki.multimedia.cx/index.php?title=ISO_MPEG-4
+
+        case FOURCC('3', 'I', 'V', '2'):
+        case FOURCC('3', 'i', 'v', '2'):
+        case FOURCC('B', 'L', 'Z', '0'):
+        case FOURCC('D', 'I', 'G', 'I'):
+        case FOURCC('D', 'I', 'V', '1'):
+        case FOURCC('d', 'i', 'v', '1'):
+        case FOURCC('D', 'I', 'V', 'X'):
+        case FOURCC('d', 'i', 'v', 'x'):
+        case FOURCC('D', 'X', '5', '0'):
+        case FOURCC('d', 'x', '5', '0'):
+        case FOURCC('D', 'X', 'G', 'M'):
+        case FOURCC('E', 'M', '4', 'A'):
+        case FOURCC('E', 'P', 'H', 'V'):
+        case FOURCC('F', 'M', 'P', '4'):
+        case FOURCC('f', 'm', 'p', '4'):
+        case FOURCC('F', 'V', 'F', 'W'):
+        case FOURCC('H', 'D', 'X', '4'):
+        case FOURCC('h', 'd', 'x', '4'):
+        case FOURCC('M', '4', 'C', 'C'):
+        case FOURCC('M', '4', 'S', '2'):
+        case FOURCC('m', '4', 's', '2'):
+        case FOURCC('M', 'P', '4', 'S'):
+        case FOURCC('m', 'p', '4', 's'):
+        case FOURCC('M', 'P', '4', 'V'):
+        case FOURCC('m', 'p', '4', 'v'):
+        case FOURCC('M', 'V', 'X', 'M'):
+        case FOURCC('R', 'M', 'P', '4'):
+        case FOURCC('S', 'E', 'D', 'G'):
+        case FOURCC('S', 'M', 'P', '4'):
+        case FOURCC('U', 'M', 'P', '4'):
+        case FOURCC('W', 'V', '1', 'F'):
+        case FOURCC('X', 'V', 'I', 'D'):
+        case FOURCC('X', 'v', 'i', 'D'):
+        case FOURCC('x', 'v', 'i', 'd'):
+        case FOURCC('X', 'V', 'I', 'X'):
+            return MEDIA_MIMETYPE_VIDEO_MPEG4;
+
+        default:
+            return NULL;
+    }
+}
+
+status_t AVIExtractor::parseStreamHeader(off64_t offset, size_t size) {
+    if (size != 56) {
+        return ERROR_MALFORMED;
+    }
+
+    if (mTracks.size() > 99) {
+        return -ERANGE;
+    }
+
+    sp<ABuffer> buffer = new ABuffer(size);
+    ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size());
+
+    if (n < (ssize_t)size) {
+        return n < 0 ? (status_t)n : ERROR_MALFORMED;
+    }
+
+    const uint8_t *data = buffer->data();
+
+    uint32_t type = U32_AT(data);
+    uint32_t handler = U32_AT(&data[4]);
+    uint32_t flags = U32LE_AT(&data[8]);
+
+    sp<MetaData> meta = new MetaData;
+
+    uint32_t rate = U32LE_AT(&data[20]);
+    uint32_t scale = U32LE_AT(&data[24]);
+
+    const char *mime = NULL;
+    Track::Kind kind = Track::OTHER;
+
+    if (type == FOURCC('v', 'i', 'd', 's')) {
+        mime = GetMIMETypeForHandler(handler);
+
+        if (mime && strncasecmp(mime, "video/", 6)) {
+            return ERROR_MALFORMED;
+        }
+
+        kind = Track::VIDEO;
+    } else if (type == FOURCC('a', 'u', 'd', 's')) {
+        if (mime && strncasecmp(mime, "audio/", 6)) {
+            return ERROR_MALFORMED;
+        }
+
+        kind = Track::AUDIO;
+    }
+
+    if (!mime) {
+        mime = "application/octet-stream";
+    }
+
+    meta->setCString(kKeyMIMEType, mime);
+
+    mTracks.push();
+    Track *track = &mTracks.editItemAt(mTracks.size() - 1);
+
+    track->mMeta = meta;
+    track->mRate = rate;
+    track->mScale = scale;
+    track->mKind = kind;
+    track->mNumSyncSamples = 0;
+    track->mThumbnailSampleSize = 0;
+    track->mThumbnailSampleIndex = -1;
+    track->mMaxSampleSize = 0;
+
+    return OK;
+}
+
+status_t AVIExtractor::parseStreamFormat(off64_t offset, size_t size) {
+    if (mTracks.isEmpty()) {
+        return ERROR_MALFORMED;
+    }
+
+    Track *track = &mTracks.editItemAt(mTracks.size() - 1);
+
+    if (track->mKind == Track::OTHER) {
+        // We don't support this content, but that's not a parsing error.
+        return OK;
+    }
+
+    bool isVideo = (track->mKind == Track::VIDEO);
+
+    if ((isVideo && size < 40) || (!isVideo && size < 18)) {
+        // Expected a BITMAPINFO or WAVEFORMATEX structure, respectively.
+        return ERROR_MALFORMED;
+    }
+
+    sp<ABuffer> buffer = new ABuffer(size);
+    ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size());
+
+    if (n < (ssize_t)size) {
+        return n < 0 ? (status_t)n : ERROR_MALFORMED;
+    }
+
+    const uint8_t *data = buffer->data();
+
+    if (isVideo) {
+        uint32_t width = U32LE_AT(&data[4]);
+        uint32_t height = U32LE_AT(&data[8]);
+
+        track->mMeta->setInt32(kKeyWidth, width);
+        track->mMeta->setInt32(kKeyHeight, height);
+    } else {
+        uint32_t format = U16LE_AT(data);
+        if (format == 0x55) {
+            track->mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG);
+        }
+
+        uint32_t numChannels = U16LE_AT(&data[2]);
+        uint32_t sampleRate = U32LE_AT(&data[4]);
+
+        track->mMeta->setInt32(kKeyChannelCount, numChannels);
+        track->mMeta->setInt32(kKeySampleRate, sampleRate);
+    }
+
+    return OK;
+}
+
+// static
+bool AVIExtractor::IsCorrectChunkType(
+        ssize_t trackIndex, Track::Kind kind, uint32_t chunkType) {
+    uint32_t chunkBase = chunkType & 0xffff;
+
+    switch (kind) {
+        case Track::VIDEO:
+        {
+            if (chunkBase != FOURCC(0, 0, 'd', 'c')
+                    && chunkBase != FOURCC(0, 0, 'd', 'b')) {
+                return false;
+            }
+            break;
+        }
+
+        case Track::AUDIO:
+        {
+            if (chunkBase != FOURCC(0, 0, 'w', 'b')) {
+                return false;
+            }
+            break;
+        }
+
+        default:
+            break;
+    }
+
+    if (trackIndex < 0) {
+        return true;
+    }
+
+    uint8_t hi = chunkType >> 24;
+    uint8_t lo = (chunkType >> 16) & 0xff;
+
+    if (hi < '0' || hi > '9' || lo < '0' || lo > '9') {
+        return false;
+    }
+
+    if (trackIndex != (10 * (hi - '0') + (lo - '0'))) {
+        return false;
+    }
+
+    return true;
+}
+
+status_t AVIExtractor::parseIndex(off64_t offset, size_t size) {
+    if ((size % 16) != 0) {
+        return ERROR_MALFORMED;
+    }
+
+    sp<ABuffer> buffer = new ABuffer(size);
+    ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size());
+
+    if (n < (ssize_t)size) {
+        return n < 0 ? (status_t)n : ERROR_MALFORMED;
+    }
+
+    const uint8_t *data = buffer->data();
+
+    while (size > 0) {
+        uint32_t chunkType = U32_AT(data);
+
+        uint8_t hi = chunkType >> 24;
+        uint8_t lo = (chunkType >> 16) & 0xff;
+
+        if (hi < '0' || hi > '9' || lo < '0' || lo > '9') {
+            return ERROR_MALFORMED;
+        }
+
+        size_t trackIndex = 10 * (hi - '0') + (lo - '0');
+
+        if (trackIndex >= mTracks.size()) {
+            return ERROR_MALFORMED;
+        }
+
+        Track *track = &mTracks.editItemAt(trackIndex);
+
+        if (!IsCorrectChunkType(-1, track->mKind, chunkType)) {
+            return ERROR_MALFORMED;
+        }
+
+        if (track->mKind == Track::OTHER) {
+            data += 16;
+            size -= 16;
+            continue;
+        }
+
+        uint32_t flags = U32LE_AT(&data[4]);
+        uint32_t offset = U32LE_AT(&data[8]);
+        uint32_t chunkSize = U32LE_AT(&data[12]);
+
+        if (chunkSize > track->mMaxSampleSize) {
+            track->mMaxSampleSize = chunkSize;
+        }
+
+        track->mSamples.push();
+
+        SampleInfo *info =
+            &track->mSamples.editItemAt(track->mSamples.size() - 1);
+
+        info->mOffset = offset;
+        info->mIsKey = (flags & 0x10) != 0;
+
+        if (info->mIsKey) {
+            static const size_t kMaxNumSyncSamplesToScan = 20;
+
+            if (track->mNumSyncSamples < kMaxNumSyncSamplesToScan) {
+                if (chunkSize > track->mThumbnailSampleSize) {
+                    track->mThumbnailSampleSize = chunkSize;
+
+                    track->mThumbnailSampleIndex =
+                        track->mSamples.size() - 1;
+                }
+            }
+
+            ++track->mNumSyncSamples;
+        }
+
+        data += 16;
+        size -= 16;
+    }
+
+    if (!mTracks.isEmpty()) {
+        off64_t offset;
+        size_t size;
+        bool isKey;
+        status_t err = getSampleInfo(0, 0, &offset, &size, &isKey);
+
+        if (err != OK) {
+            mOffsetsAreAbsolute = !mOffsetsAreAbsolute;
+            err = getSampleInfo(0, 0, &offset, &size, &isKey);
+
+            if (err != OK) {
+                return err;
+            }
+        }
+
+        LOGV("Chunk offsets are %s",
+             mOffsetsAreAbsolute ? "absolute" : "movie-chunk relative");
+    }
+
+    for (size_t i = 0; i < mTracks.size(); ++i) {
+        Track *track = &mTracks.editItemAt(i);
+
+        int64_t durationUs =
+            (track->mSamples.size() * 1000000ll * track->mRate) / track->mScale;
+
+        LOGV("track %d duration = %.2f secs", i, durationUs / 1E6);
+
+        track->mMeta->setInt64(kKeyDuration, durationUs);
+        track->mMeta->setInt32(kKeyMaxInputSize, track->mMaxSampleSize);
+
+        const char *tmp;
+        CHECK(track->mMeta->findCString(kKeyMIMEType, &tmp));
+
+        AString mime = tmp;
+
+        if (!strncasecmp("video/", mime.c_str(), 6)
+                && track->mThumbnailSampleIndex >= 0) {
+            int64_t thumbnailTimeUs =
+                (track->mThumbnailSampleIndex * 1000000ll * track->mRate)
+                    / track->mScale;
+
+            track->mMeta->setInt64(kKeyThumbnailTime, thumbnailTimeUs);
+
+            if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_MPEG4)) {
+                status_t err = addMPEG4CodecSpecificData(i);
+
+                if (err != OK) {
+                    return err;
+                }
+            }
+        }
+    }
+
+    mFoundIndex = true;
+
+    return OK;
+}
+
+static size_t GetSizeWidth(size_t x) {
+    size_t n = 1;
+    while (x > 127) {
+        ++n;
+        x >>= 7;
+    }
+    return n;
+}
+
+static uint8_t *EncodeSize(uint8_t *dst, size_t x) {
+    while (x > 127) {
+        *dst++ = (x & 0x7f) | 0x80;
+        x >>= 7;
+    }
+    *dst++ = x;
+    return dst;
+}
+
+sp<ABuffer> MakeMPEG4VideoCodecSpecificData(const sp<ABuffer> &config) {
+    size_t len1 = config->size() + GetSizeWidth(config->size()) + 1;
+    size_t len2 = len1 + GetSizeWidth(len1) + 1 + 13;
+    size_t len3 = len2 + GetSizeWidth(len2) + 1 + 3;
+
+    sp<ABuffer> csd = new ABuffer(len3);
+    uint8_t *dst = csd->data();
+    *dst++ = 0x03;
+    dst = EncodeSize(dst, len2 + 3);
+    *dst++ = 0x00;  // ES_ID
+    *dst++ = 0x00;
+    *dst++ = 0x00;  // streamDependenceFlag, URL_Flag, OCRstreamFlag
+
+    *dst++ = 0x04;
+    dst = EncodeSize(dst, len1 + 13);
+    *dst++ = 0x01;  // Video ISO/IEC 14496-2 Simple Profile
+    for (size_t i = 0; i < 12; ++i) {
+        *dst++ = 0x00;
+    }
+
+    *dst++ = 0x05;
+    dst = EncodeSize(dst, config->size());
+    memcpy(dst, config->data(), config->size());
+    dst += config->size();
+
+    // hexdump(csd->data(), csd->size());
+
+    return csd;
+}
+
+status_t AVIExtractor::addMPEG4CodecSpecificData(size_t trackIndex) {
+    Track *track = &mTracks.editItemAt(trackIndex);
+
+    off64_t offset;
+    size_t size;
+    bool isKey;
+    status_t err = getSampleInfo(trackIndex, 0, &offset, &size, &isKey);
+
+    if (err != OK) {
+        return err;
+    }
+
+    sp<ABuffer> buffer = new ABuffer(size);
+    ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size());
+
+    if (n < (ssize_t)size) {
+        return n < 0 ? (status_t)n : ERROR_MALFORMED;
+    }
+
+    // Extract everything up to the first VOP start code from the first
+    // frame's encoded data and use it to construct an ESDS with the
+    // codec specific data.
+
+    size_t i = 0;
+    bool found = false;
+    while (i + 3 < buffer->size()) {
+        if (!memcmp("\x00\x00\x01\xb6", &buffer->data()[i], 4)) {
+            found = true;
+            break;
+        }
+
+        ++i;
+    }
+
+    if (!found) {
+        return ERROR_MALFORMED;
+    }
+
+    buffer->setRange(0, i);
+
+    sp<ABuffer> csd = MakeMPEG4VideoCodecSpecificData(buffer);
+    track->mMeta->setData(kKeyESDS, kTypeESDS, csd->data(), csd->size());
+
+    return OK;
+}
+
+status_t AVIExtractor::getSampleInfo(
+        size_t trackIndex, size_t sampleIndex,
+        off64_t *offset, size_t *size, bool *isKey) {
+    if (trackIndex >= mTracks.size()) {
+        return -ERANGE;
+    }
+
+    const Track &track = mTracks.itemAt(trackIndex);
+
+    if (sampleIndex >= track.mSamples.size()) {
+        return -ERANGE;
+    }
+
+    const SampleInfo &info = track.mSamples.itemAt(sampleIndex);
+
+    if (!mOffsetsAreAbsolute) {
+        *offset = info.mOffset + mMovieOffset + 8;
+    } else {
+        *offset = info.mOffset;
+    }
+
+    *size = 0;
+
+    uint8_t tmp[8];
+    ssize_t n = mDataSource->readAt(*offset, tmp, 8);
+
+    if (n < 8) {
+        return n < 0 ? (status_t)n : (status_t)ERROR_MALFORMED;
+    }
+
+    uint32_t chunkType = U32_AT(tmp);
+
+    if (!IsCorrectChunkType(trackIndex, track.mKind, chunkType)) {
+        return ERROR_MALFORMED;
+    }
+
+    *offset += 8;
+    *size = U32LE_AT(&tmp[4]);
+
+    *isKey = info.mIsKey;
+
+    return OK;
+}
+
+status_t AVIExtractor::getSampleIndexAtTime(
+        size_t trackIndex,
+        int64_t timeUs, MediaSource::ReadOptions::SeekMode mode,
+        size_t *sampleIndex) const {
+    if (trackIndex >= mTracks.size()) {
+        return -ERANGE;
+    }
+
+    const Track &track = mTracks.itemAt(trackIndex);
+
+    ssize_t closestSampleIndex =
+        timeUs / track.mRate * track.mScale / 1000000ll;
+
+    ssize_t numSamples = track.mSamples.size();
+
+    if (closestSampleIndex < 0) {
+        closestSampleIndex = 0;
+    } else if (closestSampleIndex >= numSamples) {
+        closestSampleIndex = numSamples - 1;
+    }
+
+    if (mode == MediaSource::ReadOptions::SEEK_CLOSEST) {
+        *sampleIndex = closestSampleIndex;
+
+        return OK;
+    }
+
+    ssize_t prevSyncSampleIndex = closestSampleIndex;
+    while (prevSyncSampleIndex >= 0) {
+        const SampleInfo &info =
+            track.mSamples.itemAt(prevSyncSampleIndex);
+
+        if (info.mIsKey) {
+            break;
+        }
+
+        --prevSyncSampleIndex;
+    }
+
+    ssize_t nextSyncSampleIndex = closestSampleIndex;
+    while (nextSyncSampleIndex < numSamples) {
+        const SampleInfo &info =
+            track.mSamples.itemAt(nextSyncSampleIndex);
+
+        if (info.mIsKey) {
+            break;
+        }
+
+        ++nextSyncSampleIndex;
+    }
+
+    switch (mode) {
+        case MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC:
+        {
+            *sampleIndex = prevSyncSampleIndex;
+
+            return prevSyncSampleIndex >= 0 ? OK : UNKNOWN_ERROR;
+        }
+
+        case MediaSource::ReadOptions::SEEK_NEXT_SYNC:
+        {
+            *sampleIndex = nextSyncSampleIndex;
+
+            return nextSyncSampleIndex < numSamples ? OK : UNKNOWN_ERROR;
+        }
+
+        case MediaSource::ReadOptions::SEEK_CLOSEST_SYNC:
+        {
+            if (prevSyncSampleIndex < 0 && nextSyncSampleIndex >= numSamples) {
+                return UNKNOWN_ERROR;
+            }
+
+            if (prevSyncSampleIndex < 0) {
+                *sampleIndex = nextSyncSampleIndex;
+                return OK;
+            }
+
+            if (nextSyncSampleIndex >= numSamples) {
+                *sampleIndex = prevSyncSampleIndex;
+                return OK;
+            }
+
+            size_t dist1 = closestSampleIndex - prevSyncSampleIndex;
+            size_t dist2 = nextSyncSampleIndex - closestSampleIndex;
+
+            *sampleIndex =
+                (dist1 < dist2) ? prevSyncSampleIndex : nextSyncSampleIndex;
+
+            return OK;
+        }
+
+        default:
+            TRESPASS();
+            break;
+    }
+}
+
+bool SniffAVI(
+        const sp<DataSource> &source, String8 *mimeType, float *confidence,
+        sp<AMessage> *) {
+    char tmp[12];
+    if (source->readAt(0, tmp, 12) < 12) {
+        return false;
+    }
+
+    if (!memcmp(tmp, "RIFF", 4) && !memcmp(&tmp[8], "AVI ", 4)) {
+        mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_AVI);
+        *confidence = 0.2;
+
+        return true;
+    }
+
+    return false;
+}
+
+}  // namespace android
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index 88069e9..2f3e141 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -8,6 +8,7 @@
         AACExtractor.cpp                  \
         AMRExtractor.cpp                  \
         AMRWriter.cpp                     \
+        AVIExtractor.cpp                  \
         AudioPlayer.cpp                   \
         AudioSource.cpp                   \
         AwesomePlayer.cpp                 \
@@ -19,6 +20,7 @@
         ESDS.cpp                          \
         FileSource.cpp                    \
         FLACExtractor.cpp                 \
+        HTTPBase.cpp                      \
         HTTPStream.cpp                    \
         JPEGSource.cpp                    \
         MP3Extractor.cpp                  \
@@ -69,13 +71,12 @@
         libui             \
         libsonivox        \
         libvorbisidec     \
-        libsurfaceflinger_client \
         libstagefright_yuv \
         libcamera_client \
         libdrmframework  \
         libcrypto        \
         libssl           \
-        libgui
+        libgui           \
 
 LOCAL_STATIC_LIBRARIES := \
         libstagefright_color_conversion \
@@ -101,6 +102,60 @@
         libstagefright_g711dec \
         libFLAC \
 
+################################################################################
+
+# The following was shamelessly copied from external/webkit/Android.mk and
+# currently must follow the same logic to determine how webkit was built and
+# if it's safe to link against libchromium.net
+
+# V8 also requires an ARMv7 CPU, and since we must use jsc, we cannot
+# use the Chrome http stack either.
+ifneq ($(strip $(ARCH_ARM_HAVE_ARMV7A)),true)
+  USE_ALT_HTTP := true
+endif
+
+# See if the user has specified a stack they want to use
+HTTP_STACK = $(HTTP)
+# We default to the Chrome HTTP stack.
+DEFAULT_HTTP = chrome
+ALT_HTTP = android
+
+ifneq ($(HTTP_STACK),chrome)
+  ifneq ($(HTTP_STACK),android)
+    # No HTTP stack is specified, pickup the one we want as default.
+    ifeq ($(USE_ALT_HTTP),true)
+      HTTP_STACK = $(ALT_HTTP)
+    else
+      HTTP_STACK = $(DEFAULT_HTTP)
+    endif
+  endif
+endif
+
+ifeq ($(HTTP_STACK),chrome)
+
+LOCAL_SHARED_LIBRARIES += \
+        liblog           \
+        libicuuc         \
+        libicui18n       \
+        libz             \
+        libdl            \
+
+LOCAL_STATIC_LIBRARIES += \
+        libstagefright_chromium_http \
+        libchromium_net         \
+        libwebcore              \
+
+ifneq ($(TARGET_SIMULATOR),true)
+LOCAL_SHARED_LIBRARIES += libstlport
+include external/stlport/libstlport.mk
+endif
+
+LOCAL_CPPFLAGS += -DCHROMIUM_AVAILABLE=1
+
+endif  # ifeq ($(HTTP_STACK),chrome)
+
+################################################################################
+
 LOCAL_SHARED_LIBRARIES += \
         libstagefright_amrnb_common \
         libstagefright_enc_common \
diff --git a/media/libstagefright/AudioPlayer.cpp b/media/libstagefright/AudioPlayer.cpp
index bd04a26..162d2e6 100644
--- a/media/libstagefright/AudioPlayer.cpp
+++ b/media/libstagefright/AudioPlayer.cpp
@@ -280,6 +280,26 @@
     buffer->size = numBytesWritten;
 }
 
+uint32_t AudioPlayer::getNumFramesPendingPlayout() const {
+    uint32_t numFramesPlayedOut;
+    status_t err;
+
+    if (mAudioSink != NULL) {
+        err = mAudioSink->getPosition(&numFramesPlayedOut);
+    } else {
+        err = mAudioTrack->getPosition(&numFramesPlayedOut);
+    }
+
+    if (err != OK || mNumFramesPlayed < numFramesPlayedOut) {
+        return 0;
+    }
+
+    // mNumFramesPlayed is the number of frames submitted
+    // to the audio sink for playback, but not all of them
+    // may have played out by now.
+    return mNumFramesPlayed - numFramesPlayedOut;
+}
+
 size_t AudioPlayer::fillBuffer(void *data, size_t size) {
     if (mNumFramesPlayed == 0) {
         LOGV("AudioCallback");
@@ -342,7 +362,34 @@
 
             if (err != OK) {
                 if (mObserver && !mReachedEOS) {
-                    mObserver->postAudioEOS();
+                    // We don't want to post EOS right away but only
+                    // after all frames have actually been played out.
+
+                    // These are the number of frames submitted to the
+                    // AudioTrack that you haven't heard yet.
+                    uint32_t numFramesPendingPlayout =
+                        getNumFramesPendingPlayout();
+
+                    // These are the number of frames we're going to
+                    // submit to the AudioTrack by returning from this
+                    // callback.
+                    uint32_t numAdditionalFrames = size_done / mFrameSize;
+
+                    numFramesPendingPlayout += numAdditionalFrames;
+
+                    int64_t timeToCompletionUs =
+                        (1000000ll * numFramesPendingPlayout) / mSampleRate;
+
+                    LOGV("total number of frames played: %lld (%lld us)",
+                            (mNumFramesPlayed + numAdditionalFrames),
+                            1000000ll * (mNumFramesPlayed + numAdditionalFrames)
+                                / mSampleRate);
+
+                    LOGV("%d frames left to play, %lld us (%.2f secs)",
+                         numFramesPendingPlayout,
+                         timeToCompletionUs, timeToCompletionUs / 1E6);
+
+                    mObserver->postAudioEOS(timeToCompletionUs + mLatencyUs);
                 }
 
                 mReachedEOS = true;
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 027a1ce..6b0b1b9 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -308,7 +308,7 @@
         return UNKNOWN_ERROR;
     }
 
-    dataSource->getDrmInfo(&mDecryptHandle, &mDrmManagerClient);
+    dataSource->getDrmInfo(mDecryptHandle, &mDrmManagerClient);
     if (mDecryptHandle != NULL) {
         CHECK(mDrmManagerClient);
         if (RightsStatus::RIGHTS_VALID != mDecryptHandle->status) {
@@ -880,6 +880,17 @@
              cropLeft, cropTop, cropRight, cropBottom);
     }
 
+    int32_t displayWidth;
+    if (meta->findInt32(kKeyDisplayWidth, &displayWidth)) {
+        LOGV("Display width changed (%d=>%d)", mDisplayWidth, displayWidth);
+        mDisplayWidth = displayWidth;
+    }
+    int32_t displayHeight;
+    if (meta->findInt32(kKeyDisplayHeight, &displayHeight)) {
+        LOGV("Display height changed (%d=>%d)", mDisplayHeight, displayHeight);
+        mDisplayHeight = displayHeight;
+    }
+
     int32_t usableWidth = cropRight - cropLeft + 1;
     int32_t usableHeight = cropBottom - cropTop + 1;
     if (mDisplayWidth != 0) {
@@ -1132,7 +1143,6 @@
 
         mWatchForAudioSeekComplete = true;
         mWatchForAudioEOS = true;
-        mSeekNotificationSent = false;
 
         if (mDecryptHandle != NULL) {
             mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
@@ -1291,11 +1301,11 @@
         // If we're playing video only, report seek complete now,
         // otherwise audio player will notify us later.
         notifyListener_l(MEDIA_SEEK_COMPLETE);
+        mSeekNotificationSent = true;
     }
 
     mFlags |= FIRST_FRAME;
     mSeeking = NO_SEEK;
-    mSeekNotificationSent = false;
 
     if (mDecryptHandle != NULL) {
         mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
@@ -1555,12 +1565,12 @@
     mQueue.postEventWithDelay(mVideoLagEvent, 1000000ll);
 }
 
-void AwesomePlayer::postCheckAudioStatusEvent_l() {
+void AwesomePlayer::postCheckAudioStatusEvent_l(int64_t delayUs) {
     if (mAudioStatusEventPending) {
         return;
     }
     mAudioStatusEventPending = true;
-    mQueue.postEvent(mCheckAudioStatusEvent);
+    mQueue.postEventWithDelay(mCheckAudioStatusEvent, delayUs);
 }
 
 void AwesomePlayer::onCheckAudioStatus() {
@@ -1656,8 +1666,10 @@
 
     if (!strncasecmp("http://", mUri.string(), 7)
             || !strncasecmp("https://", mUri.string(), 8)) {
-        mConnectingDataSource = new NuHTTPDataSource(
-                (mFlags & INCOGNITO) ? NuHTTPDataSource::kFlagIncognito : 0);
+        mConnectingDataSource = HTTPBase::Create(
+                (mFlags & INCOGNITO)
+                    ? HTTPBase::kFlagIncognito
+                    : 0);
 
         mLock.unlock();
         status_t err = mConnectingDataSource->connect(mUri, &mUriHeaders);
@@ -1681,29 +1693,37 @@
 
         dataSource = mCachedSource;
 
-        // We're going to prefill the cache before trying to instantiate
-        // the extractor below, as the latter is an operation that otherwise
-        // could block on the datasource for a significant amount of time.
-        // During that time we'd be unable to abort the preparation phase
-        // without this prefill.
+        String8 contentType = dataSource->getMIMEType();
 
-        mLock.unlock();
+        if (strncasecmp(contentType.string(), "audio/", 6)) {
+            // We're not doing this for streams that appear to be audio-only
+            // streams to ensure that even low bandwidth streams start
+            // playing back fairly instantly.
 
-        for (;;) {
-            status_t finalStatus;
-            size_t cachedDataRemaining =
-                mCachedSource->approxDataRemaining(&finalStatus);
+            // We're going to prefill the cache before trying to instantiate
+            // the extractor below, as the latter is an operation that otherwise
+            // could block on the datasource for a significant amount of time.
+            // During that time we'd be unable to abort the preparation phase
+            // without this prefill.
 
-            if (finalStatus != OK || cachedDataRemaining >= kHighWaterMarkBytes
-                    || (mFlags & PREPARE_CANCELLED)) {
-                break;
+            mLock.unlock();
+
+            for (;;) {
+                status_t finalStatus;
+                size_t cachedDataRemaining =
+                    mCachedSource->approxDataRemaining(&finalStatus);
+
+                if (finalStatus != OK || cachedDataRemaining >= kHighWaterMarkBytes
+                        || (mFlags & PREPARE_CANCELLED)) {
+                    break;
+                }
+
+                usleep(200000);
             }
 
-            usleep(200000);
+            mLock.lock();
         }
 
-        mLock.lock();
-
         if (mFlags & PREPARE_CANCELLED) {
             LOGI("Prepare cancelled while waiting for initial cache fill.");
             return UNKNOWN_ERROR;
@@ -1746,7 +1766,8 @@
         return UNKNOWN_ERROR;
     }
 
-    dataSource->getDrmInfo(&mDecryptHandle, &mDrmManagerClient);
+    dataSource->getDrmInfo(mDecryptHandle, &mDrmManagerClient);
+
     if (mDecryptHandle != NULL) {
         CHECK(mDrmManagerClient);
         if (RightsStatus::RIGHTS_VALID != mDecryptHandle->status) {
@@ -1844,12 +1865,12 @@
     return mExtractorFlags;
 }
 
-void AwesomePlayer::postAudioEOS() {
-    postCheckAudioStatusEvent_l();
+void AwesomePlayer::postAudioEOS(int64_t delayUs) {
+    postCheckAudioStatusEvent_l(delayUs);
 }
 
 void AwesomePlayer::postAudioSeekComplete() {
-    postCheckAudioStatusEvent_l();
+    postCheckAudioStatusEvent_l(0 /* delayUs */);
 }
 
 }  // namespace android
diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp
index 8a24bc4..a1f04d3 100644
--- a/media/libstagefright/CameraSource.cpp
+++ b/media/libstagefright/CameraSource.cpp
@@ -740,28 +740,6 @@
     mFrameAvailableCondition.signal();
 }
 
-size_t CameraSource::getNumberOfVideoBuffers() const {
-    LOGV("getNumberOfVideoBuffers");
-    size_t nBuffers = 0;
-    int64_t token = IPCThreadState::self()->clearCallingIdentity();
-    if (mInitCheck == OK && mCamera != 0) {
-        nBuffers = mCamera->getNumberOfVideoBuffers();
-    }
-    IPCThreadState::self()->restoreCallingIdentity(token);
-    return nBuffers;
-}
-
-sp<IMemory> CameraSource::getVideoBuffer(size_t index) const {
-    LOGV("getVideoBuffer: %d", index);
-    sp<IMemory> buffer = 0;
-    int64_t token = IPCThreadState::self()->clearCallingIdentity();
-    if (mInitCheck == OK && mCamera != 0) {
-        buffer = mCamera->getVideoBuffer(index);
-    }
-    IPCThreadState::self()->restoreCallingIdentity(token);
-    return buffer;
-}
-
 bool CameraSource::isMetaDataStoredInVideoBuffers() const {
     LOGV("isMetaDataStoredInVideoBuffers");
     return mIsMetaDataStoredInVideoBuffers;
diff --git a/media/libstagefright/DRMExtractor.cpp b/media/libstagefright/DRMExtractor.cpp
index 2809df5..c4ed516 100644
--- a/media/libstagefright/DRMExtractor.cpp
+++ b/media/libstagefright/DRMExtractor.cpp
@@ -41,7 +41,7 @@
 class DRMSource : public MediaSource {
 public:
     DRMSource(const sp<MediaSource> &mediaSource,
-            DecryptHandle *decryptHandle,
+            const sp<DecryptHandle> &decryptHandle,
             DrmManagerClient *managerClient,
             int32_t trackId, DrmBuffer *ipmpBox);
 
@@ -56,7 +56,7 @@
 
 private:
     sp<MediaSource> mOriginalMediaSource;
-    DecryptHandle* mDecryptHandle;
+    sp<DecryptHandle> mDecryptHandle;
     DrmManagerClient* mDrmManagerClient;
     size_t mTrackId;
     mutable Mutex mDRMLock;
@@ -70,7 +70,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 DRMSource::DRMSource(const sp<MediaSource> &mediaSource,
-        DecryptHandle *decryptHandle,
+        const sp<DecryptHandle> &decryptHandle,
         DrmManagerClient *managerClient,
         int32_t trackId, DrmBuffer *ipmpBox)
     : mOriginalMediaSource(mediaSource),
@@ -245,7 +245,7 @@
     mOriginalExtractor->setDrmFlag(true);
     mOriginalExtractor->getMetaData()->setInt32(kKeyIsDRM, 1);
 
-    source->getDrmInfo(&mDecryptHandle, &mDrmManagerClient);
+    source->getDrmInfo(mDecryptHandle, &mDrmManagerClient);
 }
 
 DRMExtractor::~DRMExtractor() {
@@ -281,7 +281,7 @@
 bool SniffDRM(
     const sp<DataSource> &source, String8 *mimeType, float *confidence,
         sp<AMessage> *) {
-    DecryptHandle *decryptHandle = source->DrmInitialization();
+    sp<DecryptHandle> decryptHandle = source->DrmInitialization();
 
     if (decryptHandle != NULL) {
         if (decryptHandle->decryptApiType == DecryptApiType::CONTAINER_BASED) {
diff --git a/media/libstagefright/DataSource.cpp b/media/libstagefright/DataSource.cpp
index 3b38208..c16b3b5 100644
--- a/media/libstagefright/DataSource.cpp
+++ b/media/libstagefright/DataSource.cpp
@@ -15,13 +15,14 @@
  */
 
 #include "include/AMRExtractor.h"
+#include "include/AVIExtractor.h"
 #include "include/MP3Extractor.h"
 #include "include/MPEG4Extractor.h"
 #include "include/WAVExtractor.h"
 #include "include/OggExtractor.h"
 #include "include/MPEG2TSExtractor.h"
 #include "include/NuCachedSource2.h"
-#include "include/NuHTTPDataSource.h"
+#include "include/HTTPBase.h"
 #include "include/DRMExtractor.h"
 #include "include/FLACExtractor.h"
 #include "include/AACExtractor.h"
@@ -111,6 +112,7 @@
     RegisterSniffer(SniffMPEG2TS);
     RegisterSniffer(SniffMP3);
     RegisterSniffer(SniffAAC);
+    RegisterSniffer(SniffAVI);
 
     char value[PROPERTY_VALUE_MAX];
     if (property_get("drm.service.enabled", value, NULL)
@@ -127,7 +129,7 @@
         source = new FileSource(uri + 7);
     } else if (!strncasecmp("http://", uri, 7)
             || !strncasecmp("https://", uri, 8)) {
-        sp<NuHTTPDataSource> httpSource = new NuHTTPDataSource;
+        sp<HTTPBase> httpSource = HTTPBase::Create();
         if (httpSource->connect(uri, headers) != OK) {
             return NULL;
         }
@@ -144,4 +146,8 @@
     return source;
 }
 
+String8 DataSource::getMIMEType() const {
+    return String8("application/octet-stream");
+}
+
 }  // namespace android
diff --git a/media/libstagefright/FileSource.cpp b/media/libstagefright/FileSource.cpp
index 02a78c9..f2f3500 100644
--- a/media/libstagefright/FileSource.cpp
+++ b/media/libstagefright/FileSource.cpp
@@ -125,7 +125,7 @@
     return OK;
 }
 
-DecryptHandle* FileSource::DrmInitialization() {
+sp<DecryptHandle> FileSource::DrmInitialization() {
     if (mDrmManagerClient == NULL) {
         mDrmManagerClient = new DrmManagerClient();
     }
@@ -147,8 +147,8 @@
     return mDecryptHandle;
 }
 
-void FileSource::getDrmInfo(DecryptHandle **handle, DrmManagerClient **client) {
-    *handle = mDecryptHandle;
+void FileSource::getDrmInfo(sp<DecryptHandle> &handle, DrmManagerClient **client) {
+    handle = mDecryptHandle;
 
     *client = mDrmManagerClient;
 }
diff --git a/media/libstagefright/HTTPBase.cpp b/media/libstagefright/HTTPBase.cpp
new file mode 100644
index 0000000..58b17a7
--- /dev/null
+++ b/media/libstagefright/HTTPBase.cpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "include/HTTPBase.h"
+
+#if CHROMIUM_AVAILABLE
+#include "include/ChromiumHTTPDataSource.h"
+#endif
+
+#include "include/NuHTTPDataSource.h"
+
+#include <cutils/properties.h>
+
+namespace android {
+
+HTTPBase::HTTPBase() {}
+
+// static
+sp<HTTPBase> HTTPBase::Create(uint32_t flags) {
+#if CHROMIUM_AVAILABLE
+    char value[PROPERTY_VALUE_MAX];
+    if (!property_get("media.stagefright.use-chromium", value, NULL)
+            || (strcasecmp("false", value) && strcmp("0", value))) {
+        return new ChromiumHTTPDataSource(flags);
+    } else
+#endif
+    {
+        return new NuHTTPDataSource(flags);
+    }
+}
+
+}  // namespace android
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index 7b96d01..1ca2d6d 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -262,7 +262,7 @@
 
 MPEG4Extractor::MPEG4Extractor(const sp<DataSource> &source)
     : mDataSource(source),
-      mHaveMetadata(false),
+      mInitCheck(NO_INIT),
       mHasVideo(false),
       mFirstTrack(NULL),
       mLastTrack(NULL),
@@ -361,8 +361,8 @@
 }
 
 status_t MPEG4Extractor::readMetaData() {
-    if (mHaveMetadata) {
-        return OK;
+    if (mInitCheck != NO_INIT) {
+        return mInitCheck;
     }
 
     off64_t offset = 0;
@@ -370,17 +370,20 @@
     while ((err = parseChunk(&offset, 0)) == OK) {
     }
 
-    if (mHaveMetadata) {
+    if (mInitCheck == OK) {
         if (mHasVideo) {
             mFileMetaData->setCString(kKeyMIMEType, "video/mp4");
         } else {
             mFileMetaData->setCString(kKeyMIMEType, "audio/mp4");
         }
 
-        return OK;
+        mInitCheck = verifyIfStreamable();
+    } else {
+        mInitCheck = err;
     }
 
-    return err;
+    CHECK_NE(err, (status_t)NO_INIT);
+    return mInitCheck;
 }
 
 void MPEG4Extractor::setDrmFlag(bool flag) {
@@ -755,7 +758,7 @@
                     return err;
                 }
             } else if (chunk_type == FOURCC('m', 'o', 'o', 'v')) {
-                mHaveMetadata = true;
+                mInitCheck = OK;
 
                 if (!mIsDrm) {
                     return UNKNOWN_ERROR;  // Return a dummy error.
@@ -2077,6 +2080,101 @@
     }
 }
 
+MPEG4Extractor::Track *MPEG4Extractor::findTrackByMimePrefix(
+        const char *mimePrefix) {
+    for (Track *track = mFirstTrack; track != NULL; track = track->next) {
+        const char *mime;
+        if (track->meta != NULL
+                && track->meta->findCString(kKeyMIMEType, &mime)
+                && !strncasecmp(mime, mimePrefix, strlen(mimePrefix))) {
+            return track;
+        }
+    }
+
+    return NULL;
+}
+
+status_t MPEG4Extractor::verifyIfStreamable() {
+    if (!(mDataSource->flags() & DataSource::kIsCachingDataSource)) {
+        return OK;
+    }
+
+    Track *audio = findTrackByMimePrefix("audio/");
+    Track *video = findTrackByMimePrefix("video/");
+
+    if (audio == NULL || video == NULL) {
+        return OK;
+    }
+
+    sp<SampleTable> audioSamples = audio->sampleTable;
+    sp<SampleTable> videoSamples = video->sampleTable;
+
+    off64_t maxOffsetDiff = 0;
+    int64_t maxOffsetTimeUs = -1;
+
+    for (uint32_t i = 0; i < videoSamples->countSamples(); ++i) {
+        off64_t videoOffset;
+        uint32_t videoTime;
+        bool isSync;
+        CHECK_EQ((status_t)OK, videoSamples->getMetaDataForSample(
+                    i, &videoOffset, NULL, &videoTime, &isSync));
+
+        int64_t videoTimeUs = (int64_t)(videoTime * 1E6 / video->timescale);
+
+        uint32_t reqAudioTime = (videoTimeUs * audio->timescale) / 1000000;
+        uint32_t j;
+        if (audioSamples->findSampleAtTime(
+            reqAudioTime, &j, SampleTable::kFlagClosest) != OK) {
+            continue;
+        }
+
+        off64_t audioOffset;
+        uint32_t audioTime;
+        CHECK_EQ((status_t)OK, audioSamples->getMetaDataForSample(
+                    j, &audioOffset, NULL, &audioTime));
+
+        int64_t audioTimeUs = (int64_t)(audioTime * 1E6 / audio->timescale);
+
+        off64_t offsetDiff = videoOffset - audioOffset;
+        if (offsetDiff < 0) {
+            offsetDiff = -offsetDiff;
+        }
+
+#if 0
+        printf("%s%d/%d videoTime %.2f secs audioTime %.2f secs "
+               "videoOffset %lld audioOffset %lld offsetDiff %lld\n",
+               isSync ? "*" : " ",
+               i,
+               j,
+               videoTimeUs / 1E6,
+               audioTimeUs / 1E6,
+               videoOffset,
+               audioOffset,
+               offsetDiff);
+#endif
+
+        if (offsetDiff > maxOffsetDiff) {
+            maxOffsetDiff = offsetDiff;
+            maxOffsetTimeUs = videoTimeUs;
+        }
+    }
+
+#if 0
+    printf("max offset diff: %lld at video time: %.2f secs\n",
+           maxOffsetDiff, maxOffsetTimeUs / 1E6);
+#endif
+
+    if (maxOffsetDiff < 1024 * 1024) {
+        return OK;
+    }
+
+    LOGE("This content is not streamable, "
+         "max offset diff: %lld at video time: %.2f secs",
+         maxOffsetDiff, maxOffsetTimeUs / 1E6);
+
+    return ERROR_UNSUPPORTED;
+}
+
 static bool LegacySniffMPEG4(
         const sp<DataSource> &source, String8 *mimeType, float *confidence) {
     uint8_t header[8];
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 5d6ea7c..e13b67e 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -52,7 +52,7 @@
 
 class MPEG4Writer::Track {
 public:
-    Track(MPEG4Writer *owner, const sp<MediaSource> &source);
+    Track(MPEG4Writer *owner, const sp<MediaSource> &source, size_t trackId);
 
     ~Track();
 
@@ -82,6 +82,7 @@
     bool mIsAvc;
     bool mIsAudio;
     bool mIsMPEG4;
+    int32_t mTrackId;
     int64_t mTrackDurationUs;
 
     // For realtime applications, we need to adjust the media clock
@@ -231,7 +232,7 @@
       mEstimatedMoovBoxSize(0),
       mInterleaveDurationUs(1000000) {
 
-    mFd = open(filename, O_CREAT | O_LARGEFILE | O_TRUNC);
+    mFd = open(filename, O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR);
     if (mFd >= 0) {
         mInitCheck = OK;
     }
@@ -295,7 +296,12 @@
 }
 
 status_t MPEG4Writer::addSource(const sp<MediaSource> &source) {
-    Track *track = new Track(this, source);
+    Mutex::Autolock l(mLock);
+    if (mStarted) {
+        LOGE("Attempt to add source AFTER recording is started");
+        return UNKNOWN_ERROR;
+    }
+    Track *track = new Track(this, source, mTracks.size());
     mTracks.push_back(track);
 
     return OK;
@@ -945,7 +951,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 MPEG4Writer::Track::Track(
-        MPEG4Writer *owner, const sp<MediaSource> &source)
+        MPEG4Writer *owner, const sp<MediaSource> &source, size_t trackId)
     : mOwner(owner),
       mMeta(source->getFormat()),
       mSource(source),
@@ -953,6 +959,7 @@
       mPaused(false),
       mResumed(false),
       mStarted(false),
+      mTrackId(trackId),
       mTrackDurationUs(0),
       mEstimatedTrackSizeBytes(0),
       mSamplesHaveSameSize(true),
@@ -2030,7 +2037,7 @@
         (OK != checkCodecSpecificData())) {          // no codec specific data
         err = ERROR_MALFORMED;
     }
-    mOwner->trackProgressStatus(this, -1, err);
+    mOwner->trackProgressStatus(mTrackId, -1, err);
 
     // Last chunk
     if (mOwner->numTracks() == 1) {
@@ -2077,41 +2084,34 @@
     if (mTrackEveryTimeDurationUs > 0 &&
         timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) {
         LOGV("Fire time tracking progress status at %lld us", timeUs);
-        mOwner->trackProgressStatus(this, timeUs - mPreviousTrackTimeUs, err);
+        mOwner->trackProgressStatus(mTrackId, timeUs - mPreviousTrackTimeUs, err);
         mPreviousTrackTimeUs = timeUs;
     }
 }
 
 void MPEG4Writer::trackProgressStatus(
-        const MPEG4Writer::Track* track, int64_t timeUs, status_t err) {
+        size_t trackId, int64_t timeUs, status_t err) {
     Mutex::Autolock lock(mLock);
-    int32_t nTracks = mTracks.size();
-    CHECK(nTracks >= 1);
-    CHECK(nTracks < 64);  // Arbitrary number
-
-    int32_t trackNum = 0;
-    CHECK(trackNum < nTracks);
-    trackNum <<= 16;
+    int32_t trackNum = (trackId << 28);
 
     // Error notification
     // Do not consider ERROR_END_OF_STREAM an error
     if (err != OK && err != ERROR_END_OF_STREAM) {
-        notify(MEDIA_RECORDER_EVENT_ERROR,
-               trackNum | MEDIA_RECORDER_ERROR_UNKNOWN,
+        notify(MEDIA_RECORDER_TRACK_EVENT_ERROR,
+               trackNum | MEDIA_RECORDER_TRACK_ERROR_GENERAL,
                err);
         return;
     }
 
     if (timeUs == -1) {
         // Send completion notification
-        notify(MEDIA_RECORDER_EVENT_INFO,
-               trackNum | MEDIA_RECORDER_INFO_COMPLETION_STATUS,
+        notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
+               trackNum | MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS,
                err);
-        return;
     } else {
         // Send progress status
-        notify(MEDIA_RECORDER_EVENT_INFO,
-               trackNum | MEDIA_RECORDER_INFO_PROGRESS_TIME_STATUS,
+        notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
+               trackNum | MEDIA_RECORDER_TRACK_INFO_PROGRESS_IN_TIME,
                timeUs / 1000);
     }
 }
diff --git a/media/libstagefright/MediaDefs.cpp b/media/libstagefright/MediaDefs.cpp
index 0be7261..8ca6ee8 100644
--- a/media/libstagefright/MediaDefs.cpp
+++ b/media/libstagefright/MediaDefs.cpp
@@ -43,6 +43,7 @@
 const char *MEDIA_MIMETYPE_CONTAINER_OGG = "application/ogg";
 const char *MEDIA_MIMETYPE_CONTAINER_MATROSKA = "video/x-matroska";
 const char *MEDIA_MIMETYPE_CONTAINER_MPEG2TS = "video/mp2ts";
+const char *MEDIA_MIMETYPE_CONTAINER_AVI = "video/avi";
 
 const char *MEDIA_MIMETYPE_CONTAINER_WVM = "video/wvm";
 
diff --git a/media/libstagefright/MediaExtractor.cpp b/media/libstagefright/MediaExtractor.cpp
index 23bad5b..af0131e 100644
--- a/media/libstagefright/MediaExtractor.cpp
+++ b/media/libstagefright/MediaExtractor.cpp
@@ -19,6 +19,7 @@
 #include <utils/Log.h>
 
 #include "include/AMRExtractor.h"
+#include "include/AVIExtractor.h"
 #include "include/MP3Extractor.h"
 #include "include/MPEG4Extractor.h"
 #include "include/WAVExtractor.h"
@@ -108,6 +109,8 @@
         ret = new MatroskaExtractor(source);
     } else if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MPEG2TS)) {
         ret = new MPEG2TSExtractor(source);
+    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_AVI)) {
+        ret = new AVIExtractor(source);
     } else if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_WVM)) {
         ret = new WVMExtractor(source);
     } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC_ADTS)) {
diff --git a/media/libstagefright/NuCachedSource2.cpp b/media/libstagefright/NuCachedSource2.cpp
index 248b678..c1aa46e 100644
--- a/media/libstagefright/NuCachedSource2.cpp
+++ b/media/libstagefright/NuCachedSource2.cpp
@@ -481,11 +481,11 @@
     restartPrefetcherIfNecessary_l(true /* ignore low water threshold */);
 }
 
-DecryptHandle* NuCachedSource2::DrmInitialization() {
+sp<DecryptHandle> NuCachedSource2::DrmInitialization() {
     return mSource->DrmInitialization();
 }
 
-void NuCachedSource2::getDrmInfo(DecryptHandle **handle, DrmManagerClient **client) {
+void NuCachedSource2::getDrmInfo(sp<DecryptHandle> &handle, DrmManagerClient **client) {
     mSource->getDrmInfo(handle, client);
 }
 
@@ -493,4 +493,8 @@
     return mSource->getUri();
 }
 
+String8 NuCachedSource2::getMIMEType() const {
+    return mSource->getMIMEType();
+}
+
 }  // namespace android
diff --git a/media/libstagefright/NuHTTPDataSource.cpp b/media/libstagefright/NuHTTPDataSource.cpp
index bee0d5e..821ba9b 100644
--- a/media/libstagefright/NuHTTPDataSource.cpp
+++ b/media/libstagefright/NuHTTPDataSource.cpp
@@ -136,6 +136,7 @@
     unsigned port;
 
     mUri = uri;
+    mContentType = String8("application/octet-stream");
 
     bool https;
     if (!ParseURL(uri, &host, &port, &path, &https)) {
@@ -265,6 +266,15 @@
             }
         }
 
+        {
+            AString value;
+            if (mHTTP.find_header_value("Content-Type", &value)) {
+                mContentType = String8(value.c_str());
+            } else {
+                mContentType = String8("application/octet-stream");
+            }
+        }
+
         applyTimeoutResponse();
 
         if (offset == 0) {
@@ -537,7 +547,7 @@
     }
 }
 
-DecryptHandle* NuHTTPDataSource::DrmInitialization() {
+sp<DecryptHandle> NuHTTPDataSource::DrmInitialization() {
     if (mDrmManagerClient == NULL) {
         mDrmManagerClient = new DrmManagerClient();
     }
@@ -561,8 +571,8 @@
     return mDecryptHandle;
 }
 
-void NuHTTPDataSource::getDrmInfo(DecryptHandle **handle, DrmManagerClient **client) {
-    *handle = mDecryptHandle;
+void NuHTTPDataSource::getDrmInfo(sp<DecryptHandle> &handle, DrmManagerClient **client) {
+    handle = mDecryptHandle;
 
     *client = mDrmManagerClient;
 }
@@ -571,4 +581,8 @@
     return mUri;
 }
 
+String8 NuHTTPDataSource::getMIMEType() const {
+    return mContentType;
+}
+
 }  // namespace android
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index a70f868..c278992 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -1912,6 +1912,11 @@
 }
 
 void OMXCodec::on_message(const omx_message &msg) {
+    if (mState == ERROR) {
+        LOGW("Dropping OMX message - we're in ERROR state.");
+        return;
+    }
+
     switch (msg.type) {
         case omx_message::EVENT:
         {
@@ -2215,13 +2220,15 @@
 
             if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) {
                 onPortSettingsChanged(data1);
-            } else if (data1 == kPortIndexOutput
-                    && data2 == OMX_IndexConfigCommonOutputCrop) {
+            } else if (data1 == kPortIndexOutput &&
+                        (data2 == OMX_IndexConfigCommonOutputCrop ||
+                         data2 == OMX_IndexConfigCommonScale)) {
 
                 sp<MetaData> oldOutputFormat = mOutputFormat;
                 initOutputFormat(mSource->getFormat());
 
-                if (formatHasNotablyChanged(oldOutputFormat, mOutputFormat)) {
+                if (data2 == OMX_IndexConfigCommonOutputCrop &&
+                    formatHasNotablyChanged(oldOutputFormat, mOutputFormat)) {
                     mOutputPortSettingsHaveChanged = true;
 
                     if (mNativeWindow != NULL) {
@@ -2240,6 +2247,39 @@
                         // already invalid, we'll know soon enough.
                         native_window_set_crop(mNativeWindow.get(), &crop);
                     }
+                } else if (data2 == OMX_IndexConfigCommonScale) {
+                    OMX_CONFIG_SCALEFACTORTYPE scale;
+                    InitOMXParams(&scale);
+                    scale.nPortIndex = kPortIndexOutput;
+
+                    // Change display dimension only when necessary.
+                    if (OK == mOMX->getConfig(
+                                        mNode,
+                                        OMX_IndexConfigCommonScale,
+                                        &scale, sizeof(scale))) {
+                        int32_t left, top, right, bottom;
+                        CHECK(mOutputFormat->findRect(kKeyCropRect,
+                                                      &left, &top,
+                                                      &right, &bottom));
+
+                        // The scale is in 16.16 format.
+                        // scale 1.0 = 0x010000. When there is no
+                        // need to change the display, skip it.
+                        LOGV("Get OMX_IndexConfigScale: 0x%lx/0x%lx",
+                                scale.xWidth, scale.xHeight);
+
+                        if (scale.xWidth != 0x010000) {
+                            mOutputFormat->setInt32(kKeyDisplayWidth,
+                                    ((right - left +  1) * scale.xWidth)  >> 16);
+                            mOutputPortSettingsHaveChanged = true;
+                        }
+
+                        if (scale.xHeight != 0x010000) {
+                            mOutputFormat->setInt32(kKeyDisplayHeight,
+                                    ((bottom  - top + 1) * scale.xHeight) >> 16);
+                            mOutputPortSettingsHaveChanged = true;
+                        }
+                    }
                 }
             }
             break;
diff --git a/media/libstagefright/StagefrightMediaScanner.cpp b/media/libstagefright/StagefrightMediaScanner.cpp
index 84f65ff..f82ff32 100644
--- a/media/libstagefright/StagefrightMediaScanner.cpp
+++ b/media/libstagefright/StagefrightMediaScanner.cpp
@@ -37,7 +37,8 @@
         ".mp3", ".mp4", ".m4a", ".3gp", ".3gpp", ".3g2", ".3gpp2",
         ".mpeg", ".ogg", ".mid", ".smf", ".imy", ".wma", ".aac",
         ".wav", ".amr", ".midi", ".xmf", ".rtttl", ".rtx", ".ota",
-        ".mkv", ".mka", ".webm", ".ts", ".fl", ".flac"
+        ".mkv", ".mka", ".webm", ".ts", ".fl", ".flac", ".mxmf",
+        ".avi",
     };
     static const size_t kNumValidExtensions =
         sizeof(kValidExtensions) / sizeof(kValidExtensions[0]);
@@ -124,7 +125,8 @@
             || !strcasecmp(extension, ".xmf")
             || !strcasecmp(extension, ".rtttl")
             || !strcasecmp(extension, ".rtx")
-            || !strcasecmp(extension, ".ota")) {
+            || !strcasecmp(extension, ".ota")
+            || !strcasecmp(extension, ".mxmf")) {
         status_t status = HandleMIDI(path, &client);
         if (status != OK) {
             return status;
diff --git a/media/libstagefright/StagefrightMetadataRetriever.cpp b/media/libstagefright/StagefrightMetadataRetriever.cpp
index ea3b801..4095fbf 100644
--- a/media/libstagefright/StagefrightMetadataRetriever.cpp
+++ b/media/libstagefright/StagefrightMetadataRetriever.cpp
@@ -48,7 +48,8 @@
     mClient.disconnect();
 }
 
-status_t StagefrightMetadataRetriever::setDataSource(const char *uri) {
+status_t StagefrightMetadataRetriever::setDataSource(
+        const char *uri, const KeyedVector<String8, String8> *headers) {
     LOGV("setDataSource(%s)", uri);
 
     mParsedMetaData = false;
@@ -56,7 +57,7 @@
     delete mAlbumArt;
     mAlbumArt = NULL;
 
-    mSource = DataSource::CreateFromURI(uri);
+    mSource = DataSource::CreateFromURI(uri, headers);
 
     if (mSource == NULL) {
         return UNKNOWN_ERROR;
@@ -231,6 +232,14 @@
     frame->mData = new uint8_t[frame->mSize];
     frame->mRotationAngle = rotationAngle;
 
+    int32_t displayWidth, displayHeight;
+    if (meta->findInt32(kKeyDisplayWidth, &displayWidth)) {
+        frame->mDisplayWidth = displayWidth;
+    }
+    if (meta->findInt32(kKeyDisplayHeight, &displayHeight)) {
+        frame->mDisplayHeight = displayHeight;
+    }
+
     int32_t srcFormat;
     CHECK(meta->findInt32(kKeyColorFormat, &srcFormat));
 
@@ -411,6 +420,12 @@
 
     mMetaData.add(METADATA_KEY_NUM_TRACKS, String8(tmp));
 
+    bool hasAudio = false;
+    bool hasVideo = false;
+    int32_t videoWidth = -1;
+    int32_t videoHeight = -1;
+    int32_t audioBitrate = -1;
+
     // The overall duration is the duration of the longest track.
     int64_t maxDurationUs = 0;
     for (size_t i = 0; i < numTracks; ++i) {
@@ -422,12 +437,55 @@
                 maxDurationUs = durationUs;
             }
         }
+
+        const char *mime;
+        if (trackMeta->findCString(kKeyMIMEType, &mime)) {
+            if (!hasAudio && !strncasecmp("audio/", mime, 6)) {
+                hasAudio = true;
+
+                if (!trackMeta->findInt32(kKeyBitRate, &audioBitrate)) {
+                    audioBitrate = -1;
+                }
+            } else if (!hasVideo && !strncasecmp("video/", mime, 6)) {
+                hasVideo = true;
+
+                CHECK(trackMeta->findInt32(kKeyWidth, &videoWidth));
+                CHECK(trackMeta->findInt32(kKeyHeight, &videoHeight));
+            }
+        }
     }
 
     // The duration value is a string representing the duration in ms.
     sprintf(tmp, "%lld", (maxDurationUs + 500) / 1000);
     mMetaData.add(METADATA_KEY_DURATION, String8(tmp));
 
+    if (hasAudio) {
+        mMetaData.add(METADATA_KEY_HAS_AUDIO, String8("yes"));
+    }
+
+    if (hasVideo) {
+        mMetaData.add(METADATA_KEY_HAS_VIDEO, String8("yes"));
+
+        sprintf(tmp, "%d", videoWidth);
+        mMetaData.add(METADATA_KEY_VIDEO_WIDTH, String8(tmp));
+
+        sprintf(tmp, "%d", videoHeight);
+        mMetaData.add(METADATA_KEY_VIDEO_HEIGHT, String8(tmp));
+    }
+
+    if (numTracks == 1 && hasAudio && audioBitrate >= 0) {
+        sprintf(tmp, "%d", audioBitrate);
+        mMetaData.add(METADATA_KEY_BITRATE, String8(tmp));
+    } else {
+        off64_t sourceSize;
+        if (mSource->getSize(&sourceSize) == OK) {
+            int64_t avgBitRate = (int64_t)(sourceSize * 8E6 / maxDurationUs);
+
+            sprintf(tmp, "%lld", avgBitRate);
+            mMetaData.add(METADATA_KEY_BITRATE, String8(tmp));
+        }
+    }
+
     if (numTracks == 1) {
         const char *fileMIME;
         CHECK(meta->findCString(kKeyMIMEType, &fileMIME));
diff --git a/media/libstagefright/WAVExtractor.cpp b/media/libstagefright/WAVExtractor.cpp
index 9332120..76f47f7 100644
--- a/media/libstagefright/WAVExtractor.cpp
+++ b/media/libstagefright/WAVExtractor.cpp
@@ -353,8 +353,6 @@
         return ERROR_END_OF_STREAM;
     }
 
-    mCurrentPos += n;
-
     buffer->set_range(0, n);
 
     if (mWaveFormat == WAVE_FORMAT_PCM) {
@@ -406,6 +404,7 @@
                 / (mNumChannels * bytesPerSample) / mSampleRate);
 
     buffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
+    mCurrentPos += n;
 
     *out = buffer;
 
@@ -426,6 +425,11 @@
         return false;
     }
 
+    sp<MediaExtractor> extractor = new WAVExtractor(source);
+    if (extractor->countTracks() == 0) {
+        return false;
+    }
+
     *mimeType = MEDIA_MIMETYPE_CONTAINER_WAV;
     *confidence = 0.3f;
 
diff --git a/media/libstagefright/chromium_http/Android.mk b/media/libstagefright/chromium_http/Android.mk
new file mode 100644
index 0000000..80b2478
--- /dev/null
+++ b/media/libstagefright/chromium_http/Android.mk
@@ -0,0 +1,25 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:=       \
+        ChromiumHTTPDataSource.cpp        \
+        support.cpp                     \
+
+LOCAL_C_INCLUDES:= \
+        $(JNI_H_INCLUDE) \
+        frameworks/base/media/libstagefright \
+        $(TOP)/frameworks/base/include/media/stagefright/openmax \
+        external/chromium \
+        external/chromium/android
+
+LOCAL_CFLAGS += -Wno-multichar
+
+ifneq ($(TARGET_SIMULATOR),true)
+LOCAL_SHARED_LIBRARIES += libstlport
+include external/stlport/libstlport.mk
+endif
+
+LOCAL_MODULE:= libstagefright_chromium_http
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp b/media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp
new file mode 100644
index 0000000..1096717
--- /dev/null
+++ b/media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp
@@ -0,0 +1,336 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ChromiumHTTPDataSource"
+#include <media/stagefright/foundation/ADebug.h>
+
+#include "include/ChromiumHTTPDataSource.h"
+
+#include <media/stagefright/foundation/ALooper.h>
+#include <media/stagefright/MediaErrors.h>
+
+#include "support.h"
+
+namespace android {
+
+ChromiumHTTPDataSource::ChromiumHTTPDataSource(uint32_t flags)
+    : mFlags(flags),
+      mState(DISCONNECTED),
+      mDelegate(new SfDelegate),
+      mCurrentOffset(0),
+      mIOResult(OK),
+      mContentSize(-1),
+      mNumBandwidthHistoryItems(0),
+      mTotalTransferTimeUs(0),
+      mTotalTransferBytes(0),
+      mDecryptHandle(NULL),
+      mDrmManagerClient(NULL) {
+    mDelegate->setOwner(this);
+}
+
+ChromiumHTTPDataSource::~ChromiumHTTPDataSource() {
+    disconnect();
+
+    delete mDelegate;
+    mDelegate = NULL;
+
+    if (mDrmManagerClient != NULL) {
+        delete mDrmManagerClient;
+        mDrmManagerClient = NULL;
+    }
+}
+
+status_t ChromiumHTTPDataSource::connect(
+        const char *uri,
+        const KeyedVector<String8, String8> *headers,
+        off64_t offset) {
+    Mutex::Autolock autoLock(mLock);
+
+    return connect_l(uri, headers, offset);
+}
+
+status_t ChromiumHTTPDataSource::connect_l(
+        const char *uri,
+        const KeyedVector<String8, String8> *headers,
+        off64_t offset) {
+    if (mState != DISCONNECTED) {
+        disconnect_l();
+    }
+
+    if (!(mFlags & kFlagIncognito)) {
+        LOG_PRI(ANDROID_LOG_INFO, LOG_TAG, "connect to %s @%lld", uri, offset);
+    } else {
+        LOG_PRI(ANDROID_LOG_INFO, LOG_TAG,
+                "connect to <URL suppressed> @%lld", offset);
+    }
+
+    mURI = uri;
+    mContentType = String8("application/octet-stream");
+
+    if (headers != NULL) {
+        mHeaders = *headers;
+    } else {
+        mHeaders.clear();
+    }
+
+    mState = CONNECTING;
+    mContentSize = -1;
+    mCurrentOffset = offset;
+
+    mDelegate->initiateConnection(mURI.c_str(), &mHeaders, offset);
+
+    while (mState == CONNECTING) {
+        mCondition.wait(mLock);
+    }
+
+    return mState == CONNECTED ? OK : mIOResult;
+}
+
+void ChromiumHTTPDataSource::onConnectionEstablished(
+        int64_t contentSize, const char *contentType) {
+    Mutex::Autolock autoLock(mLock);
+    mState = CONNECTED;
+    mContentSize = (contentSize < 0) ? -1 : contentSize + mCurrentOffset;
+    mContentType = String8(contentType);
+    mCondition.broadcast();
+}
+
+void ChromiumHTTPDataSource::onConnectionFailed(status_t err) {
+    Mutex::Autolock autoLock(mLock);
+    mState = DISCONNECTED;
+    mCondition.broadcast();
+
+    mURI.clear();
+
+    mIOResult = err;
+
+    clearDRMState_l();
+}
+
+void ChromiumHTTPDataSource::disconnect() {
+    Mutex::Autolock autoLock(mLock);
+    disconnect_l();
+}
+
+void ChromiumHTTPDataSource::disconnect_l() {
+    if (mState == DISCONNECTED) {
+        return;
+    }
+
+    mState = DISCONNECTING;
+    mIOResult = -EINTR;
+
+    mDelegate->initiateDisconnect();
+
+    while (mState == DISCONNECTING) {
+        mCondition.wait(mLock);
+    }
+
+    CHECK_EQ((int)mState, (int)DISCONNECTED);
+}
+
+status_t ChromiumHTTPDataSource::initCheck() const {
+    Mutex::Autolock autoLock(mLock);
+
+    return mState == CONNECTED ? OK : NO_INIT;
+}
+
+ssize_t ChromiumHTTPDataSource::readAt(off64_t offset, void *data, size_t size) {
+    Mutex::Autolock autoLock(mLock);
+
+    if (mState != CONNECTED) {
+        return ERROR_NOT_CONNECTED;
+    }
+
+    if (offset != mCurrentOffset) {
+        AString tmp = mURI;
+        KeyedVector<String8, String8> tmpHeaders = mHeaders;
+
+        disconnect_l();
+
+        status_t err = connect_l(tmp.c_str(), &tmpHeaders, offset);
+
+        if (err != OK) {
+            return err;
+        }
+    }
+
+    mState = READING;
+
+    int64_t startTimeUs = ALooper::GetNowUs();
+
+    mDelegate->initiateRead(data, size);
+
+    while (mState == READING) {
+        mCondition.wait(mLock);
+    }
+
+    if (mIOResult < OK) {
+        return mIOResult;
+    }
+
+    if (mState == CONNECTED) {
+        int64_t delayUs = ALooper::GetNowUs() - startTimeUs;
+
+        // The read operation was successful, mIOResult contains
+        // the number of bytes read.
+        addBandwidthMeasurement_l(mIOResult, delayUs);
+
+        mCurrentOffset += mIOResult;
+        return mIOResult;
+    }
+
+    return ERROR_IO;
+}
+
+void ChromiumHTTPDataSource::onReadCompleted(ssize_t size) {
+    Mutex::Autolock autoLock(mLock);
+
+    mIOResult = size;
+
+    if (mState == READING) {
+        mState = CONNECTED;
+        mCondition.broadcast();
+    }
+}
+
+status_t ChromiumHTTPDataSource::getSize(off64_t *size) {
+    Mutex::Autolock autoLock(mLock);
+
+    if (mContentSize < 0) {
+        return ERROR_UNSUPPORTED;
+    }
+
+    *size = mContentSize;
+
+    return OK;
+}
+
+uint32_t ChromiumHTTPDataSource::flags() {
+    return kWantsPrefetching;
+}
+
+// static
+void ChromiumHTTPDataSource::InitiateRead(
+        ChromiumHTTPDataSource *me, void *data, size_t size) {
+    me->initiateRead(data, size);
+}
+
+void ChromiumHTTPDataSource::initiateRead(void *data, size_t size) {
+    mDelegate->initiateRead(data, size);
+}
+
+void ChromiumHTTPDataSource::onDisconnectComplete() {
+    Mutex::Autolock autoLock(mLock);
+    CHECK_EQ((int)mState, (int)DISCONNECTING);
+
+    mState = DISCONNECTED;
+    mURI.clear();
+
+    mCondition.broadcast();
+
+    clearDRMState_l();
+}
+
+void ChromiumHTTPDataSource::addBandwidthMeasurement_l(
+        size_t numBytes, int64_t delayUs) {
+    BandwidthEntry entry;
+    entry.mDelayUs = delayUs;
+    entry.mNumBytes = numBytes;
+    mTotalTransferTimeUs += delayUs;
+    mTotalTransferBytes += numBytes;
+
+    mBandwidthHistory.push_back(entry);
+    if (++mNumBandwidthHistoryItems > 100) {
+        BandwidthEntry *entry = &*mBandwidthHistory.begin();
+        mTotalTransferTimeUs -= entry->mDelayUs;
+        mTotalTransferBytes -= entry->mNumBytes;
+        mBandwidthHistory.erase(mBandwidthHistory.begin());
+        --mNumBandwidthHistoryItems;
+    }
+}
+
+bool ChromiumHTTPDataSource::estimateBandwidth(int32_t *bandwidth_bps) {
+    Mutex::Autolock autoLock(mLock);
+
+    if (mNumBandwidthHistoryItems < 2) {
+        return false;
+    }
+
+    *bandwidth_bps = ((double)mTotalTransferBytes * 8E6 / mTotalTransferTimeUs);
+
+    return true;
+}
+
+sp<DecryptHandle> ChromiumHTTPDataSource::DrmInitialization() {
+    Mutex::Autolock autoLock(mLock);
+
+    if (mDrmManagerClient == NULL) {
+        mDrmManagerClient = new DrmManagerClient();
+    }
+
+    if (mDrmManagerClient == NULL) {
+        return NULL;
+    }
+
+    if (mDecryptHandle == NULL) {
+        /* Note if redirect occurs, mUri is the redirect uri instead of the
+         * original one
+         */
+        mDecryptHandle = mDrmManagerClient->openDecryptSession(
+                String8(mURI.c_str()));
+    }
+
+    if (mDecryptHandle == NULL) {
+        delete mDrmManagerClient;
+        mDrmManagerClient = NULL;
+    }
+
+    return mDecryptHandle;
+}
+
+void ChromiumHTTPDataSource::getDrmInfo(
+        sp<DecryptHandle> &handle, DrmManagerClient **client) {
+    Mutex::Autolock autoLock(mLock);
+
+    handle = mDecryptHandle;
+    *client = mDrmManagerClient;
+}
+
+String8 ChromiumHTTPDataSource::getUri() {
+    Mutex::Autolock autoLock(mLock);
+
+    return String8(mURI.c_str());
+}
+
+String8 ChromiumHTTPDataSource::getMIMEType() const {
+    Mutex::Autolock autoLock(mLock);
+
+    return mContentType;
+}
+
+void ChromiumHTTPDataSource::clearDRMState_l() {
+    if (mDecryptHandle != NULL) {
+        // To release mDecryptHandle
+        CHECK(mDrmManagerClient);
+        mDrmManagerClient->closeDecryptSession(mDecryptHandle);
+        mDecryptHandle = NULL;
+    }
+}
+
+}  // namespace android
+
diff --git a/media/libstagefright/chromium_http/support.cpp b/media/libstagefright/chromium_http/support.cpp
new file mode 100644
index 0000000..af2f6ac
--- /dev/null
+++ b/media/libstagefright/chromium_http/support.cpp
@@ -0,0 +1,461 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ChromiumHTTPDataSourceSupport"
+#include <utils/Log.h>
+
+#include <media/stagefright/foundation/AString.h>
+
+#include "support.h"
+
+#include "android/net/android_network_library_impl.h"
+#include "base/thread.h"
+#include "net/base/host_resolver.h"
+#include "net/base/ssl_config_service.h"
+#include "net/http/http_auth_handler_factory.h"
+#include "net/http/http_cache.h"
+#include "net/proxy/proxy_config_service_android.h"
+
+#include "include/ChromiumHTTPDataSource.h"
+
+#include <cutils/properties.h>
+#include <media/stagefright/MediaErrors.h>
+
+namespace android {
+
+static Mutex gNetworkThreadLock;
+static base::Thread *gNetworkThread = NULL;
+static scoped_refptr<URLRequestContext> gReqContext;
+
+static void InitializeNetworkThreadIfNecessary() {
+    Mutex::Autolock autoLock(gNetworkThreadLock);
+    if (gNetworkThread == NULL) {
+        gNetworkThread = new base::Thread("network");
+        base::Thread::Options options;
+        options.message_loop_type = MessageLoop::TYPE_IO;
+        CHECK(gNetworkThread->StartWithOptions(options));
+
+        gReqContext = new SfRequestContext;
+
+        net::AndroidNetworkLibrary::RegisterSharedInstance(
+                new SfNetworkLibrary);
+    }
+}
+
+static void MY_LOGI(const char *s) {
+    LOG_PRI(ANDROID_LOG_INFO, LOG_TAG, "%s", s);
+}
+
+static void MY_LOGV(const char *s) {
+#if !defined(LOG_NDEBUG) || LOG_NDEBUG == 0
+    LOG_PRI(ANDROID_LOG_VERBOSE, LOG_TAG, "%s", s);
+#endif
+}
+
+SfNetLog::SfNetLog()
+    : mNextID(1) {
+}
+
+void SfNetLog::AddEntry(
+        EventType type,
+        const base::TimeTicks &time,
+        const Source &source,
+        EventPhase phase,
+        EventParameters *params) {
+#if 0
+    MY_LOGI(StringPrintf(
+                "AddEntry time=%s type=%s source=%s phase=%s\n",
+                TickCountToString(time).c_str(),
+                EventTypeToString(type),
+                SourceTypeToString(source.type),
+                EventPhaseToString(phase)).c_str());
+#endif
+}
+
+uint32 SfNetLog::NextID() {
+    return mNextID++;
+}
+
+net::NetLog::LogLevel SfNetLog::GetLogLevel() const {
+    return LOG_ALL;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+SfRequestContext::SfRequestContext() {
+    AString ua;
+    ua.append("stagefright/1.2 (Linux;Android ");
+
+#if (PROPERTY_VALUE_MAX < 8)
+#error "PROPERTY_VALUE_MAX must be at least 8"
+#endif
+
+    char value[PROPERTY_VALUE_MAX];
+    property_get("ro.build.version.release", value, "Unknown");
+    ua.append(value);
+    ua.append(")");
+
+    mUserAgent = ua.c_str();
+
+    net_log_ = new SfNetLog;
+
+    host_resolver_ =
+        net::CreateSystemHostResolver(
+                net::HostResolver::kDefaultParallelism,
+                NULL /* resolver_proc */,
+                net_log_);
+
+    ssl_config_service_ =
+        net::SSLConfigService::CreateSystemSSLConfigService();
+
+    proxy_service_ = net::ProxyService::CreateWithoutProxyResolver(
+            new net::ProxyConfigServiceAndroid, net_log_);
+
+    http_transaction_factory_ = new net::HttpCache(
+            host_resolver_,
+            dnsrr_resolver_,
+            dns_cert_checker_.get(),
+            proxy_service_.get(),
+            ssl_config_service_.get(),
+            net::HttpAuthHandlerFactory::CreateDefault(host_resolver_),
+            network_delegate_,
+            net_log_,
+            NULL);  // backend_factory
+}
+
+const std::string &SfRequestContext::GetUserAgent(const GURL &url) const {
+    return mUserAgent;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+SfNetworkLibrary::SfNetworkLibrary() {}
+
+SfNetworkLibrary::VerifyResult SfNetworkLibrary::VerifyX509CertChain(
+        const std::vector<std::string>& cert_chain,
+        const std::string& hostname,
+        const std::string& auth_type) {
+    return VERIFY_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+SfDelegate::SfDelegate()
+    : mOwner(NULL),
+      mURLRequest(NULL),
+      mReadBuffer(new net::IOBufferWithSize(8192)),
+      mNumBytesRead(0),
+      mNumBytesTotal(0),
+      mDataDestination(NULL),
+      mAtEOS(false) {
+    InitializeNetworkThreadIfNecessary();
+}
+
+SfDelegate::~SfDelegate() {
+    CHECK(mURLRequest == NULL);
+}
+
+void SfDelegate::setOwner(ChromiumHTTPDataSource *owner) {
+    mOwner = owner;
+}
+
+void SfDelegate::OnReceivedRedirect(
+            URLRequest *request, const GURL &new_url, bool *defer_redirect) {
+    MY_LOGI("OnReceivedRedirect");
+}
+
+void SfDelegate::OnAuthRequired(
+            URLRequest *request, net::AuthChallengeInfo *auth_info) {
+    MY_LOGI("OnAuthRequired");
+
+    inherited::OnAuthRequired(request, auth_info);
+}
+
+void SfDelegate::OnCertificateRequested(
+            URLRequest *request, net::SSLCertRequestInfo *cert_request_info) {
+    MY_LOGI("OnCertificateRequested");
+
+    inherited::OnCertificateRequested(request, cert_request_info);
+}
+
+void SfDelegate::OnSSLCertificateError(
+            URLRequest *request, int cert_error, net::X509Certificate *cert) {
+    fprintf(stderr, "OnSSLCertificateError cert_error=%d\n", cert_error);
+
+    inherited::OnSSLCertificateError(request, cert_error, cert);
+}
+
+void SfDelegate::OnGetCookies(URLRequest *request, bool blocked_by_policy) {
+    MY_LOGI("OnGetCookies");
+}
+
+void SfDelegate::OnSetCookie(
+        URLRequest *request,
+        const std::string &cookie_line,
+        const net::CookieOptions &options,
+        bool blocked_by_policy) {
+    MY_LOGI("OnSetCookie");
+}
+
+void SfDelegate::OnResponseStarted(URLRequest *request) {
+    if (request->status().status() != URLRequestStatus::SUCCESS) {
+        MY_LOGI(StringPrintf(
+                    "Request failed with status %d and os_error %d",
+                    request->status().status(),
+                    request->status().os_error()).c_str());
+
+        delete mURLRequest;
+        mURLRequest = NULL;
+
+        mOwner->onConnectionFailed(ERROR_IO);
+        return;
+    } else if (mRangeRequested && request->GetResponseCode() != 206) {
+        MY_LOGI(StringPrintf(
+                    "We requested a content range, but server didn't "
+                    "support that. (responded with %d)",
+                    request->GetResponseCode()).c_str());
+
+        delete mURLRequest;
+        mURLRequest = NULL;
+
+        mOwner->onConnectionFailed(-EPIPE);
+        return;
+    } else if ((request->GetResponseCode() / 100) != 2) {
+        MY_LOGI(StringPrintf(
+                    "Server responded with http status %d",
+                    request->GetResponseCode()).c_str());
+
+        delete mURLRequest;
+        mURLRequest = NULL;
+
+        mOwner->onConnectionFailed(ERROR_IO);
+        return;
+    }
+
+    MY_LOGV("OnResponseStarted");
+
+    std::string headers;
+    request->GetAllResponseHeaders(&headers);
+
+    MY_LOGV(StringPrintf("response headers: %s", headers.c_str()).c_str());
+
+    std::string contentType;
+    request->GetResponseHeaderByName("Content-Type", &contentType);
+
+    mOwner->onConnectionEstablished(
+            request->GetExpectedContentSize(), contentType.c_str());
+}
+
+void SfDelegate::OnReadCompleted(URLRequest *request, int bytes_read) {
+    if (bytes_read == -1) {
+        MY_LOGI(StringPrintf(
+                    "OnReadCompleted, read failed, status %d",
+                    request->status().status()).c_str());
+
+        mOwner->onReadCompleted(ERROR_IO);
+        return;
+    }
+
+    MY_LOGV(StringPrintf("OnReadCompleted, read %d bytes", bytes_read).c_str());
+
+    if (bytes_read < 0) {
+        MY_LOGI(StringPrintf(
+                    "Read failed w/ status %d\n",
+                    request->status().status()).c_str());
+
+        mOwner->onReadCompleted(ERROR_IO);
+        return;
+    } else if (bytes_read == 0) {
+        mAtEOS = true;
+        mOwner->onReadCompleted(mNumBytesRead);
+        return;
+    }
+
+    CHECK_GT(bytes_read, 0);
+    CHECK_LE(mNumBytesRead + bytes_read, mNumBytesTotal);
+
+    memcpy((uint8_t *)mDataDestination + mNumBytesRead,
+           mReadBuffer->data(),
+           bytes_read);
+
+    mNumBytesRead += bytes_read;
+
+    readMore(request);
+}
+
+void SfDelegate::readMore(URLRequest *request) {
+    while (mNumBytesRead < mNumBytesTotal) {
+        size_t copy = mNumBytesTotal - mNumBytesRead;
+        if (copy > mReadBuffer->size()) {
+            copy = mReadBuffer->size();
+        }
+
+        int n;
+        if (request->Read(mReadBuffer, copy, &n)) {
+            MY_LOGV(StringPrintf("Read %d bytes directly.", n).c_str());
+
+            CHECK_LE((size_t)n, copy);
+
+            memcpy((uint8_t *)mDataDestination + mNumBytesRead,
+                   mReadBuffer->data(),
+                   n);
+
+            mNumBytesRead += n;
+
+            if (n == 0) {
+                mAtEOS = true;
+                break;
+            }
+        } else {
+            MY_LOGV("readMore pending read");
+
+            if (request->status().status() != URLRequestStatus::IO_PENDING) {
+                MY_LOGI(StringPrintf(
+                            "Direct read failed w/ status %d\n",
+                            request->status().status()).c_str());
+
+                mOwner->onReadCompleted(ERROR_IO);
+                return;
+            }
+
+            return;
+        }
+    }
+
+    mOwner->onReadCompleted(mNumBytesRead);
+}
+
+void SfDelegate::initiateConnection(
+        const char *uri,
+        const KeyedVector<String8, String8> *headers,
+        off64_t offset) {
+    GURL url(uri);
+
+    MessageLoop *loop = gNetworkThread->message_loop();
+    loop->PostTask(
+            FROM_HERE,
+            NewRunnableFunction(
+                &SfDelegate::OnInitiateConnectionWrapper,
+                this,
+                url,
+                headers,
+                offset));
+
+}
+
+// static
+void SfDelegate::OnInitiateConnectionWrapper(
+        SfDelegate *me, GURL url,
+        const KeyedVector<String8, String8> *headers,
+        off64_t offset) {
+    me->onInitiateConnection(url, headers, offset);
+}
+
+void SfDelegate::onInitiateConnection(
+        const GURL &url,
+        const KeyedVector<String8, String8> *extra,
+        off64_t offset) {
+    CHECK(mURLRequest == NULL);
+
+    mURLRequest = new URLRequest(url, this);
+    mAtEOS = false;
+
+    mRangeRequested = false;
+
+    if (offset != 0 || extra != NULL) {
+        net::HttpRequestHeaders headers =
+            mURLRequest->extra_request_headers();
+
+        if (offset != 0) {
+            headers.AddHeaderFromString(
+                    StringPrintf("Range: bytes=%lld-", offset).c_str());
+
+            mRangeRequested = true;
+        }
+
+        if (extra != NULL) {
+            for (size_t i = 0; i < extra->size(); ++i) {
+                AString s;
+                s.append(extra->keyAt(i).string());
+                s.append(": ");
+                s.append(extra->valueAt(i).string());
+
+                headers.AddHeaderFromString(s.c_str());
+            }
+        }
+
+        mURLRequest->SetExtraRequestHeaders(headers);
+    }
+
+    mURLRequest->set_context(gReqContext);
+
+    mURLRequest->Start();
+}
+
+void SfDelegate::initiateDisconnect() {
+    MessageLoop *loop = gNetworkThread->message_loop();
+    loop->PostTask(
+            FROM_HERE,
+            NewRunnableFunction(
+                &SfDelegate::OnInitiateDisconnectWrapper, this));
+}
+
+// static
+void SfDelegate::OnInitiateDisconnectWrapper(SfDelegate *me) {
+    me->onInitiateDisconnect();
+}
+
+void SfDelegate::onInitiateDisconnect() {
+    mURLRequest->Cancel();
+
+    delete mURLRequest;
+    mURLRequest = NULL;
+
+    mOwner->onDisconnectComplete();
+}
+
+void SfDelegate::initiateRead(void *data, size_t size) {
+    MessageLoop *loop = gNetworkThread->message_loop();
+    loop->PostTask(
+            FROM_HERE,
+            NewRunnableFunction(
+                &SfDelegate::OnInitiateReadWrapper, this, data, size));
+}
+
+// static
+void SfDelegate::OnInitiateReadWrapper(
+        SfDelegate *me, void *data, size_t size) {
+    me->onInitiateRead(data, size);
+}
+
+void SfDelegate::onInitiateRead(void *data, size_t size) {
+    CHECK(mURLRequest != NULL);
+
+    mNumBytesRead = 0;
+    mNumBytesTotal = size;
+    mDataDestination = data;
+
+    if (mAtEOS) {
+        mOwner->onReadCompleted(0);
+        return;
+    }
+
+    readMore(mURLRequest);
+}
+
+}  // namespace android
+
diff --git a/media/libstagefright/chromium_http/support.h b/media/libstagefright/chromium_http/support.h
new file mode 100644
index 0000000..634ac93
--- /dev/null
+++ b/media/libstagefright/chromium_http/support.h
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SUPPORT_H_
+
+#define SUPPORT_H_
+
+#include <assert.h>
+
+#include "net/base/net_log.h"
+#include "net/url_request/url_request.h"
+#include "net/url_request/url_request_context.h"
+#include "net/base/android_network_library.h"
+#include "net/base/io_buffer.h"
+
+#include <utils/KeyedVector.h>
+#include <utils/String8.h>
+
+namespace android {
+
+struct SfNetLog : public net::NetLog {
+    SfNetLog();
+
+    virtual void AddEntry(
+            EventType type,
+            const base::TimeTicks &time,
+            const Source &source,
+            EventPhase phase,
+            EventParameters *params);
+
+    virtual uint32 NextID();
+    virtual LogLevel GetLogLevel() const;
+
+private:
+    uint32 mNextID;
+
+    DISALLOW_EVIL_CONSTRUCTORS(SfNetLog);
+};
+
+struct SfRequestContext : public URLRequestContext {
+    SfRequestContext();
+
+    virtual const std::string &GetUserAgent(const GURL &url) const;
+
+private:
+    std::string mUserAgent;
+
+    DISALLOW_EVIL_CONSTRUCTORS(SfRequestContext);
+};
+
+// This is required for https support, we don't really verify certificates,
+// we accept anything...
+struct SfNetworkLibrary : public net::AndroidNetworkLibrary {
+    SfNetworkLibrary();
+
+    virtual VerifyResult VerifyX509CertChain(
+            const std::vector<std::string>& cert_chain,
+            const std::string& hostname,
+            const std::string& auth_type);
+
+private:
+    DISALLOW_EVIL_CONSTRUCTORS(SfNetworkLibrary);
+};
+
+struct ChromiumHTTPDataSource;
+
+struct SfDelegate : public URLRequest::Delegate {
+    SfDelegate();
+    virtual ~SfDelegate();
+
+    void initiateConnection(
+            const char *uri,
+            const KeyedVector<String8, String8> *headers,
+            off64_t offset);
+
+    void initiateDisconnect();
+    void initiateRead(void *data, size_t size);
+
+    void setOwner(ChromiumHTTPDataSource *mOwner);
+
+    virtual void OnReceivedRedirect(
+            URLRequest *request, const GURL &new_url, bool *defer_redirect);
+
+    virtual void OnAuthRequired(
+            URLRequest *request, net::AuthChallengeInfo *auth_info);
+
+    virtual void OnCertificateRequested(
+            URLRequest *request, net::SSLCertRequestInfo *cert_request_info);
+
+    virtual void OnSSLCertificateError(
+            URLRequest *request, int cert_error, net::X509Certificate *cert);
+
+    virtual void OnGetCookies(URLRequest *request, bool blocked_by_policy);
+
+    virtual void OnSetCookie(
+            URLRequest *request,
+            const std::string &cookie_line,
+            const net::CookieOptions &options,
+            bool blocked_by_policy);
+
+    virtual void OnResponseStarted(URLRequest *request);
+
+    virtual void OnReadCompleted(URLRequest *request, int bytes_read);
+
+private:
+    typedef Delegate inherited;
+
+    ChromiumHTTPDataSource *mOwner;
+
+    URLRequest *mURLRequest;
+    scoped_refptr<net::IOBufferWithSize> mReadBuffer;
+
+    size_t mNumBytesRead;
+    size_t mNumBytesTotal;
+    void *mDataDestination;
+
+    bool mRangeRequested;
+    bool mAtEOS;
+
+    void readMore(URLRequest *request);
+
+    static void OnInitiateConnectionWrapper(
+            SfDelegate *me,
+            GURL url,
+            const KeyedVector<String8, String8> *headers,
+            off64_t offset);
+
+    static void OnInitiateDisconnectWrapper(SfDelegate *me);
+
+    static void OnInitiateReadWrapper(
+            SfDelegate *me, void *data, size_t size);
+
+    void onInitiateConnection(
+            const GURL &url,
+            const KeyedVector<String8, String8> *headers,
+            off64_t offset);
+
+    void onInitiateDisconnect();
+    void onInitiateRead(void *data, size_t size);
+
+    DISALLOW_EVIL_CONSTRUCTORS(SfDelegate);
+};
+
+}  // namespace android
+
+#endif  // SUPPORT_H_
diff --git a/media/libstagefright/codecs/aacdec/sbr_dec.cpp b/media/libstagefright/codecs/aacdec/sbr_dec.cpp
index 8fcc3ce..8519b17 100644
--- a/media/libstagefright/codecs/aacdec/sbr_dec.cpp
+++ b/media/libstagefright/codecs/aacdec/sbr_dec.cpp
@@ -1,5 +1,5 @@
 /* ------------------------------------------------------------------
- * Copyright (C) 1998-2009 PacketVideo
+ * Copyright (C) 1998-2010 PacketVideo
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -447,7 +447,12 @@
 
             if (xoverBand > sbrDec->highSubband)
             {
-                xoverBand = 32; /* error condition, default to upsampling mode */
+                /*
+                 * error condition, default to upsampling mode
+                 * and make sure that the number of bands for xover does
+                 * not exceed the number of high freq bands.
+                 */
+                xoverBand = (sbrDec->highSubband > 32)? 32: sbrDec->highSubband;
             }
 
             m = sbrDec->bufReadOffs + i;    /*  2 + i */
@@ -558,18 +563,22 @@
         /*
          *  Set Circular buffer for PS hybrid analysis
          */
+
+        int32_t *pt_temp = &scratch_mem[2][32];
+
         for (i = 0, j = 0; i < 3; i++)
         {
 
-            pv_memmove(&scratch_mem[2][32 + j     ],
+            pv_memmove(&pt_temp[ j],
                        hParametricStereoDec->hHybrid->mQmfBufferReal[i],
                        HYBRID_FILTER_LENGTH_m_1*sizeof(*hParametricStereoDec->hHybrid->mQmfBufferReal));
-            pv_memmove(&scratch_mem[2][32 + j + 44],
+            pv_memmove(&pt_temp[ j + 44],
                        hParametricStereoDec->hHybrid->mQmfBufferImag[i],
                        HYBRID_FILTER_LENGTH_m_1*sizeof(*hParametricStereoDec->hHybrid->mQmfBufferImag));
             j += 88;
         }
 
+
         pv_memset((void *)&qmf_PS_generated_Real[hParametricStereoDec->usb],
                   0,
                   (64 - hParametricStereoDec->usb)*sizeof(*qmf_PS_generated_Real));
@@ -626,19 +635,23 @@
          *  Save Circular buffer history used on PS hybrid analysis
          */
 
+
+        pt_temp = &scratch_mem[2][64];
+
         for (i = 0, j = 0; i < 3; i++)
         {
             pv_memmove(hParametricStereoDec->hHybrid->mQmfBufferReal[i],
-                       &scratch_mem[2][ 64 + j     ],
+                       &pt_temp[ j],
                        HYBRID_FILTER_LENGTH_m_1*sizeof(*hParametricStereoDec->hHybrid->mQmfBufferReal));
 
             pv_memmove(hParametricStereoDec->hHybrid->mQmfBufferImag[i],
-                       &scratch_mem[2][ 64 + j + 44],
+                       &pt_temp[ j + 44],
                        HYBRID_FILTER_LENGTH_m_1*sizeof(*hParametricStereoDec->hHybrid->mQmfBufferImag));
 
             j += 88;
         }
 
+
         pv_memmove(hFrameData->V, &circular_buffer_s[0], 1152*sizeof(*circular_buffer_s));
 
         /*
@@ -746,7 +759,12 @@
 
                 if (xoverBand > sbrDec->highSubband)
                 {
-                    xoverBand = 32; /* error condition, default to upsampling mode */
+                    /*
+                     * error condition, default to upsampling mode
+                     * and make sure that the number of bands for xover does
+                     * not exceed the number of high freq bands.
+                     */
+                    xoverBand = (sbrDec->highSubband > 32)? 32: sbrDec->highSubband;
                 }
             }
             else
diff --git a/media/libstagefright/codecs/aacenc/Android.mk b/media/libstagefright/codecs/aacenc/Android.mk
index cda4f9d..f9cc6a3 100644
--- a/media/libstagefright/codecs/aacenc/Android.mk
+++ b/media/libstagefright/codecs/aacenc/Android.mk
@@ -2,7 +2,7 @@
 include $(CLEAR_VARS)
 include frameworks/base/media/libstagefright/codecs/common/Config.mk
 
-LOCAL_PRELINK_MODULE := false
+
 
 LOCAL_SRC_FILES := basic_op/basicop2.c basic_op/oper_32b.c
 
diff --git a/media/libstagefright/codecs/aacenc/SampleCode/AAC_E_SAMPLES.c b/media/libstagefright/codecs/aacenc/SampleCode/AAC_E_SAMPLES.c
index 64d012d..774da7b 100644
--- a/media/libstagefright/codecs/aacenc/SampleCode/AAC_E_SAMPLES.c
+++ b/media/libstagefright/codecs/aacenc/SampleCode/AAC_E_SAMPLES.c
@@ -188,7 +188,7 @@
 	useData.memflag = VO_IMF_USERMEMOPERATOR;

 	useData.memData = (VO_PTR)(&moper);

 	// open encoder dll;

-	handle = dlopen("/data/local/tmp/libvoAACEncv7.so", RTLD_NOW);

+	handle = dlopen("libstagefright.so", RTLD_NOW);

 	if(handle == 0)

 	{

 		printf("open dll error......");

diff --git a/media/libstagefright/codecs/aacenc/SampleCode/Android.mk b/media/libstagefright/codecs/aacenc/SampleCode/Android.mk
index 52c9c07..ba3f4d2 100644
--- a/media/libstagefright/codecs/aacenc/SampleCode/Android.mk
+++ b/media/libstagefright/codecs/aacenc/SampleCode/Android.mk
@@ -1,24 +1,25 @@
 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_SRC_FILES := 	AAC_E_SAMPLES.c
-	
-LOCAL_SRC_FILES += 	\
-	../../../Common/cmnMemory.c 
+LOCAL_SRC_FILES := \
+    AAC_E_SAMPLES.c \
+    ../../common/cmnMemory.c
 
-LOCAL_MODULE := TestvoAACEnc
+LOCAL_CFLAGS += $(VO_CFLAGS)
+
+LOCAL_MODULE_TAGS := debug
+
+LOCAL_MODULE := AACEncTest
 
 LOCAL_ARM_MODE := arm
 
-LOCAL_STATIC_LIBRARIES := 
-
-LOCAL_SHARED_LIBRARIES := libvoAACEnc
+LOCAL_SHARED_LIBRARIES := \
+    libstagefright \
+    libdl
 
 LOCAL_C_INCLUDES := \
-	$(LOCAL_PATH)/ \
-	$(LOCAL_PATH)/../../../Common \
-	$(LOCAL_PATH)/../../../Include \
+    $(LOCAL_PATH)/ \
+    $(LOCAL_PATH)/../../common \
+    $(LOCAL_PATH)/../../common/include \
 
-LOCAL_CFLAGS := $(VO_CFLAGS)
-	
 include $(BUILD_EXECUTABLE)
diff --git a/media/libstagefright/codecs/aacenc/SampleCode/eclair/Makefile b/media/libstagefright/codecs/aacenc/SampleCode/eclair/Makefile
deleted file mode 100644
index 22c5dc1..0000000
--- a/media/libstagefright/codecs/aacenc/SampleCode/eclair/Makefile
+++ /dev/null
@@ -1,55 +0,0 @@
-#/*

-#** Copyright 2003-2010, VisualOn, Inc.

-#**

-#** Licensed under the Apache License, Version 2.0 (the "License");

-#** you may not use this file except in compliance with the License.

-#** You may obtain a copy of the License at

-#**

-#**     http://www.apache.org/licenses/LICENSE-2.0

-#**

-#** Unless required by applicable law or agreed to in writing, software

-#** distributed under the License is distributed on an "AS IS" BASIS,

-#** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

-#** See the License for the specific language governing permissions and

-#** limitations under the License.

-#*/

-

-# target6

-# available: pc, v4(armv4), v5(armv5), v5x(armv5 xscale), v6(armv6), v7(cortex-a8 neon)

-VOTT:= v7

-

-

-# module type

-# please specify the type of your module: lib or exe

-VOMT:= exe

-

-

-# module macros

-# please append the additional macro definitions here for your module if necessary. 

-# e.g. -DVISUALON, macro VISUALON defined for your module 

-VOMM:= #ARMV5E

-

-

-

-# please specify the name of your module

-VOTARGET:= voAACEncTestv7

-

-

-# please modify here to be sure to see the g1.mk

-include ../../../../Tools/eclair.mk 

-

-# dependent libraries.

-VODEPLIBS:=-ldl

-

-# module source

-# please modify here to be sure to see the ms.mk which specifies all source info of your module

-include ../ms.mk

-

-

-# please specify where is the voRelease on your PC, relative path is suggested

-VORELDIR:=../../../../../Release/

-

-

-# please modify here to be sure to see the doit.mk

-include ../../../../Tools/doit.mk 

-

diff --git a/media/libstagefright/codecs/aacenc/SampleCode/ms.mk b/media/libstagefright/codecs/aacenc/SampleCode/ms.mk
deleted file mode 100644
index 771a569..0000000
--- a/media/libstagefright/codecs/aacenc/SampleCode/ms.mk
+++ /dev/null
@@ -1,23 +0,0 @@
-#/*

-#** Copyright 2003-2010, VisualOn, Inc.

-#**

-#** Licensed under the Apache License, Version 2.0 (the "License");

-#** you may not use this file except in compliance with the License.

-#** You may obtain a copy of the License at

-#**

-#**     http://www.apache.org/licenses/LICENSE-2.0

-#**

-#** Unless required by applicable law or agreed to in writing, software

-#** distributed under the License is distributed on an "AS IS" BASIS,

-#** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

-#** See the License for the specific language governing permissions and

-#** limitations under the License.

-#*/

-

-# please list all objects needed by your target here

-OBJS:=AAC_E_SAMPLES.o	cmnMemory.o

-			

-# please list all directories that all source files relative with your module(.h .c .cpp) locate 

-VOSRCDIR:=../ ../../../../include  ../../../../Common

-					

-				

diff --git a/media/libstagefright/codecs/aacenc/Tools/doit.mk b/media/libstagefright/codecs/aacenc/Tools/doit.mk
deleted file mode 100644
index dea0b0a..0000000
--- a/media/libstagefright/codecs/aacenc/Tools/doit.mk
+++ /dev/null
@@ -1,133 +0,0 @@
-#/*
-# ** Copyright 2003-2010, VisualOn, Inc.
-# **
-# ** Licensed under the Apache License, Version 2.0 (the "License");
-# ** you may not use this file except in compliance with the License.
-# ** You may obtain a copy of the License at
-# **
-# **     http://www.apache.org/licenses/LICENSE-2.0
-# **
-# ** Unless required by applicable law or agreed to in writing, software
-# ** distributed under the License is distributed on an "AS IS" BASIS,
-# ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# ** See the License for the specific language governing permissions and
-# ** limitations under the License.
-# */
-
-VERBOSE:=@
-
-
-VOMT ?= lib
-
-ifeq ($(VOMT), lib)
-LIB_STATIC=$(VOTARGET).a
-LIB_DYNAMIC=$(VOTARGET).so
-endif
-
-ifeq ($(VOMT), exe)
-TARGET=$(VOTARGET)
-endif
-
-CFLAGS=$(VOCFLAGS) $(addprefix -I, $(VOSRCDIR)) 
-CPPFLAGS=$(VOCPPFLAGS) $(addprefix -I, $(VOSRCDIR)) 
-ifneq ($(VOTT), pc)
-ASFLAGS=$(VOASFLAGS) $(addprefix -I, $(VOSRCDIR)) 
-endif
-
-LDFLAGS:=$(VOLDFLAGS)
-VOTEDEPS+=$(VODEPLIBS)
-VOTLDEPS+=$(VODEPLIBS)
-VOSTCLIBS ?=
-
-vpath %.c $(VOSRCDIR)
-vpath %.cpp $(VOSRCDIR)
-ifneq ($(VOTT), pc)
-vpath %.s $(VOSRCDIR)
-endif
-
-ifeq ($(VOTT), pc)
-BLTDIRS=$(VORELDIR)/Linux/static
-BLTDIRD=$(VORELDIR)/Linux/shared
-else
-BLTDIRS=$(VORELDIR)/Google/$(VONJ)/lib/$(VOTT)
-BLTDIRD=$(VORELDIR)/Google/$(VONJ)/so/$(VOTT)
-endif
-
-
-.PRECIOUS: $(OBJDIR)/%.o
-
-ifeq ($(VOMT), lib)
-all: mkdirs $(LIB_STATIC) $(LIB_DYNAMIC)
-mkdirs: $(OBJDIR) $(BLTDIRS) $(BLTDIRD)
-else
-all: mkdirs $(TARGET)
-mkdirs: $(OBJDIR)
-endif
-
-$(OBJDIR):
-	@if test ! -d $@; then \
-		mkdir -p $@; \
-	fi;
-
-ifeq ($(VOMT), lib)
-$(BLTDIRS):
-	@if test ! -d $@; then \
-		mkdir -p $@; \
-	fi;
-$(BLTDIRD):
-	@if test ! -d $@; then \
-		mkdir -p $@; \
-	fi;
-endif
-
-
-ifeq ($(VOMT), lib)
-$(LIB_STATIC):$(OBJS)
-	$(AR) cr $@ $(OBJDIR)/*.o $(VOSTCLIBS)
-	$(RANLIB) $@
-ifneq ($(VODBG), yes)
-	#$(STRIP) $@
-endif
-
-$(LIB_DYNAMIC):$(OBJS)
-	$(GG) $(LDFLAGS) -o $@ $(OBJDIR)/*.o -Wl,--whole-archive $(VOSTCLIBS) -Wl,--no-whole-archive $(VOTLDEPS) 
-ifneq ($(VODBG), yes)
-		$(STRIP) $@
-endif
-
-else
-
-$(TARGET):$(OBJS)
-	$(GG) $(LDFLAGS) -o $@ $(OBJDIR)/*.o -Wl,--whole-archive $(VOSTCLIBS) -Wl,--no-whole-archive $(VOTEDEPS)
-ifneq ($(VODBG), yes)
-	$(STRIP) $@
-endif
-
-endif
-
-
-.SUFFIXES: .c .cpp .s .o
-.c.o:
-	$(VERBOSE) $(CC) $(CFLAGS) -o $(OBJDIR)/$@ -c $<
-#%.c:$(OBJDIR)/%.o
-#	$(VERBOSE) $(CC) $(CFLAGS) -o $@ -c $<
-.cpp.o:
-	$(VERBOSE) $(GG) $(CPPFLAGS) -o $(OBJDIR)/$@ -c $<
-ifneq ($(VOTT), pc)
-.s.o:
-	$(VERBOSE) $(AS) $(ASFLAGS) -o $(OBJDIR)/$@ $<
-endif
-
-
-.PHONY: clean devel
-clean:
-ifeq ($(VOMT), lib)
-	-rm -fr $(OBJDIR) .*.sw* $(VOTARGET).*
-else
-	-rm -fr $(OBJDIR) .*.sw* $(VOTARGET)
-endif
-
-devel:
-	cp -a $(LIB_STATIC) $(BLTDIRS)
-	cp -a $(LIB_DYNAMIC) $(BLTDIRD)
-
diff --git a/media/libstagefright/codecs/aacenc/Tools/eclair.mk b/media/libstagefright/codecs/aacenc/Tools/eclair.mk
deleted file mode 100644
index 1688361..0000000
--- a/media/libstagefright/codecs/aacenc/Tools/eclair.mk
+++ /dev/null
@@ -1,172 +0,0 @@
-#/*
-# ** Copyright 2003-2010, VisualOn, Inc.
-# **
-# ** Licensed under the Apache License, Version 2.0 (the "License");
-# ** you may not use this file except in compliance with the License.
-# ** You may obtain a copy of the License at
-# **
-# **     http://www.apache.org/licenses/LICENSE-2.0
-# **
-# ** Unless required by applicable law or agreed to in writing, software
-# ** distributed under the License is distributed on an "AS IS" BASIS,
-# ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# ** See the License for the specific language governing permissions and
-# ** limitations under the License.
-# */
-
-# special macro definitions for building 
-VOPREDEF=-DLINUX -D_LINUX 
-
-VOPRJ ?= 
-VONJ ?= eclair
-VOTT ?= v6
-# control the version to release out
-# available: eva(evaluation), rel(release)
-VOVER=
-ifeq ($(VOVER), eva)
-VOPREDEF+=-D__VOVER_EVA__
-endif
-
-# for debug or not: yes for debug, any other for release
-VODBG?=ye
-
-# for detecting memory leak
-VODML=
-ifeq ($(VODML), yes)
-VOPREDEF+=-DDMEMLEAK
-endif
-
-VOPREDEF+=-D__VOTT_ARM__ -D__VONJ_ECLAIR__
-TCROOTPATH:=/opt/eclair
-GCCVER:=4.4.0
-TCPATH:=$(TCROOTPATH)/prebuilt/linux-x86/toolchain/arm-eabi-$(GCCVER)
-CCTPRE:=$(TCPATH)/bin/arm-eabi-
-AS:=$(CCTPRE)as
-AR:=$(CCTPRE)ar
-NM:=$(CCTPRE)nm
-CC:=$(CCTPRE)gcc
-GG:=$(CCTPRE)g++
-LD:=$(CCTPRE)ld
-SIZE:=$(CCTPRE)size
-STRIP:=$(CCTPRE)strip
-RANLIB:=$(CCTPRE)ranlib
-OBJCOPY:=$(CCTPRE)objcopy
-OBJDUMP:=$(CCTPRE)objdump
-READELF:=$(CCTPRE)readelf
-STRINGS:=$(CCTPRE)strings
-
-# target product dependcy
-# available: dream, generic
-VOTP:=sapphire-open
-CCTLIB:=$(TCROOTPATH)/out/target/product/$(VOTP)/obj/lib
-CCTINC:=-I$(TCROOTPATH)/system/core/include \
-	-I$(TCROOTPATH)/hardware/libhardware/include \
-	-I$(TCROOTPATH)/hardware/ril/include \
-	-I$(TCROOTPATH)/hardware/libhardware_legacy/include \
-	-I$(TCROOTPATH)/dalvik/libnativehelper/include \
-	-I$(TCROOTPATH)/dalvik/libnativehelper/include/nativehelper \
-	-I$(TCROOTPATH)/frameworks/base/include \
-	-I$(TCROOTPATH)/frameworks/base/core/jni \
-	-I$(TCROOTPATH)/frameworks/base/libs/audioflinger \
-	-I$(TCROOTPATH)/external/skia/include \
-	-I$(TCROOTPATH)/out/target/product/$(VOTP)/obj/include \
-	-I$(TCROOTPATH)/bionic/libc/arch-arm/include \
-	-I$(TCROOTPATH)/bionic/libc/include \
-	-I$(TCROOTPATH)/bionic/libstdc++/include \
-	-I$(TCROOTPATH)/bionic/libc/kernel/common \
-	-I$(TCROOTPATH)/bionic/libc/kernel/arch-arm \
-	-I$(TCROOTPATH)/bionic/libm/include \
-	-I$(TCROOTPATH)/bionic/libm/include/arm \
-	-I$(TCROOTPATH)/bionic/libthread_db/include \
-	-I$(TCROOTPATH)/bionic/libm/arm \
-	-I$(TCROOTPATH)/bionic/libm \
-	-I$(TCROOTPATH)/frameworks/base/include/android_runtime 
-	#-I$(TCROOTPATH)/out/target/product/$(VOTP)/obj/SHARED_LIBRARIES/libm_intermediates
-
-CCTCFLAGS:=-msoft-float -mthumb-interwork -fno-exceptions -ffunction-sections -funwind-tables -fstack-protector -fno-short-enums -fmessage-length=0 -finline-functions -finline-limit=600 -fno-inline-functions-called-once -fgcse-after-reload -frerun-cse-after-loop -frename-registers -fstrict-aliasing -funswitch-loops
-#-fwide-exec-charset=charset=UTF-32 
-
-# for target exe
-TELDFLAGS:=-nostdlib -Bdynamic -Wl,-T,$(TCROOTPATH)/build/core/armelf.x -Wl,-dynamic-linker,/system/bin/linker -Wl,--gc-sections -Wl,-z,nocopyreloc -Wl,--no-undefined -Wl,-rpath-link=$(CCTLIB) -L$(CCTLIB) 
-
-VOTEDEPS:=$(CCTLIB)/crtbegin_dynamic.o $(CCTLIB)/crtend_android.o $(TCPATH)/lib/gcc/arm-eabi/$(GCCVER)/interwork/libgcc.a -lc -lm
-
-# for target lib
-TLLDFLAGS:=-nostdlib -Wl,-T,$(TCROOTPATH)/build/core/armelf.xsc -Wl,--gc-sections -Wl,-shared,-Bsymbolic -L$(CCTLIB) -Wl,--no-whole-archive -Wl,--no-undefined $(TCPATH)/lib/gcc/arm-eabi/$(GCCVER)/interwork/libgcc.a 
-
-VOTLDEPS:=-lm -lc
-
-
-ifeq ($(VOTT), v4)
-VOCFLAGS:=-mtune=arm9tdmi -march=armv4t
-VOASFLAGS:=-march=armv4t -mfpu=softfpa
-endif
-
-ifeq ($(VOTT), v5)
-VOCFLAGS:=-march=armv5te
-VOASFLAGS:=-march=armv5te -mfpu=vfp
-endif
-
-ifeq ($(VOTT), v5x)
-VOCFLAGS:=-march=armv5te -mtune=xscale
-VOASFLAGS:=-march=armv5te -mfpu=vfp
-endif
-
-ifeq ($(VOTT), v6)
-#VOCFLAGS:=-march=armv6 -mtune=arm1136jf-s 
-#VOASFLAGS:=-march=armv6
-VOCFLAGS:=-march=armv6j -mtune=arm1136jf-s -mfpu=vfp -mfloat-abi=softfp -mapcs -mtpcs-leaf-frame -mlong-calls
-VOASFLAGS:=-march=armv6j -mcpu=arm1136jf-s -mfpu=arm1136jf-s -mfloat-abi=softfp -mapcs-float -mapcs-reentrant
-endif
-
-#
-# global link options
-VOLDFLAGS:=-Wl,-x,-X,--as-needed
-
-
-ifeq ($(VOTT), v7)
-VOCFLAGS+=-march=armv7-a -mtune=cortex-a8 -mfpu=neon -mfloat-abi=softfp
-VOASFLAGS+=-march=armv7-a -mcpu=cortex-a8 -mfpu=neon -mfloat-abi=softfp
-VOLDFLAGS+=-Wl,--fix-cortex-a8
-endif
-
-#global compiling options for ARM target
-ifneq ($(VOTT), pc)
-VOASFLAGS+=--strip-local-absolute -R
-endif 
-
-
-ifeq ($(VODBG), yes)
-VOCFLAGS+=-D_DEBUG -g
-else
-VOCFLAGS+=-DNDEBUG -O3
-endif
-
-VOCFLAGS+=$(VOPREDEF) $(VOMM) -Wall -fsigned-char -fomit-frame-pointer -fno-leading-underscore -fpic -fPIC -pipe -ftracer -fforce-addr -fno-bounds-check #-fvisibility=hidden #-fvisibility-inlines-hidden ##-ftree-loop-linear  -mthumb -nostdinc  -dD -fprefetch-loop-arrays
-
-
-ifneq ($(VOTT), pc)
-VOCFLAGS+=$(CCTCFLAGS) $(CCTINC)
-VOCPPFLAGS:=-fno-rtti $(VOCFLAGS)
-
-ifeq ($(VOMT), exe)
-VOLDFLAGS+=$(TELDFLAGS)
-endif
-
-ifeq ($(VOMT), lib)
-VOLDFLAGS+=$(TLLDFLAGS)
-endif
-else
-VOCPPFLAGS:=$(VOCFLAGS)
-ifeq ($(VOMT), lib)
-VOLDFLAGS+=-shared
-endif
-endif
-
-ifeq ($(VODBG), yes)
-#VOLDFLAGS:=
-endif
-
-# where to place object files 
-OBJDIR=obj
-
diff --git a/media/libstagefright/codecs/aacenc/build/eclair/ARMV5E/Makefile b/media/libstagefright/codecs/aacenc/build/eclair/ARMV5E/Makefile
deleted file mode 100644
index b4f63af..0000000
--- a/media/libstagefright/codecs/aacenc/build/eclair/ARMV5E/Makefile
+++ /dev/null
@@ -1,55 +0,0 @@
-#/*

-#** Copyright 2003-2010, VisualOn, Inc.

-#**

-#** Licensed under the Apache License, Version 2.0 (the "License");

-#** you may not use this file except in compliance with the License.

-#** You may obtain a copy of the License at

-#**

-#**     http://www.apache.org/licenses/LICENSE-2.0

-#**

-#** Unless required by applicable law or agreed to in writing, software

-#** distributed under the License is distributed on an "AS IS" BASIS,

-#** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

-#** See the License for the specific language governing permissions and

-#** limitations under the License.

-#*/

-

-# target6

-# available: pc, v4(armv4), v5(armv5), v5x(armv5 xscale), v6(armv6), v7(cortex-a8 neon)

-VOTT:= v5

-

-

-# module type

-# please specify the type of your module: lib or exe

-VOMT:= lib

-

-

-# module macros

-# please append the additional macro definitions here for your module if necessary. 

-# e.g. -DVISUALON, macro VISUALON defined for your module 

-VOMM:= -DARMV5E -DARM_INASM -DARMV5_INASM 

-

-

-

-# please specify the name of your module

-VOTARGET:=libvoAACEncv5

-

-

-# please modify here to be sure to see the g1.mk

-include ../../../../../Tools/eclair.mk 

-

-# dependent libraries.

-VODEPLIBS:=#-ldl -lstdc++ 

-

-# module source

-# please modify here to be sure to see the ms.mk which specifies all source info of your module

-include ../../ms.mk

-

-

-# please specify where is the voRelease on your PC, relative path is suggested

-VORELDIR:=../../../../../../Release

-

-

-# please modify here to be sure to see the doit.mk

-include ../../../../../Tools/doit.mk 

-

diff --git a/media/libstagefright/codecs/aacenc/build/eclair/ARMV7/Makefile b/media/libstagefright/codecs/aacenc/build/eclair/ARMV7/Makefile
deleted file mode 100644
index cdce2c1..0000000
--- a/media/libstagefright/codecs/aacenc/build/eclair/ARMV7/Makefile
+++ /dev/null
@@ -1,55 +0,0 @@
-#/*

-#** Copyright 2003-2010, VisualOn, Inc.

-#**

-#** Licensed under the Apache License, Version 2.0 (the "License");

-#** you may not use this file except in compliance with the License.

-#** You may obtain a copy of the License at

-#**

-#**     http://www.apache.org/licenses/LICENSE-2.0

-#**

-#** Unless required by applicable law or agreed to in writing, software

-#** distributed under the License is distributed on an "AS IS" BASIS,

-#** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

-#** See the License for the specific language governing permissions and

-#** limitations under the License.

-#*/

-

-# target6

-# available: pc, v4(armv4), v5(armv5), v5x(armv5 xscale), v6(armv6), v7(cortex-a8 neon)

-VOTT:= v7

-

-

-# module type

-# please specify the type of your module: lib or exe

-VOMT:= lib

-

-

-# module macros

-# please append the additional macro definitions here for your module if necessary. 

-# e.g. -DVISUALON, macro VISUALON defined for your module 

-VOMM:= -DARMV5E -DARMV7Neon -DARM_INASM -DARMV5_INASM 

-

-

-

-# please specify the name of your module

-VOTARGET:=libvoAACEncv7

-

-

-# please modify here to be sure to see the g1.mk

-include ../../../../../Tools/eclair.mk 

-

-# dependent libraries.

-VODEPLIBS:=#-ldl -lstdc++ 

-

-# module source

-# please modify here to be sure to see the ms.mk which specifies all source info of your module

-include ../../ms.mk

-

-

-# please specify where is the voRelease on your PC, relative path is suggested

-VORELDIR:=../../../../../../Release

-

-

-# please modify here to be sure to see the doit.mk

-include ../../../../../Tools/doit.mk  

-

diff --git a/media/libstagefright/codecs/aacenc/build/eclair/makefile b/media/libstagefright/codecs/aacenc/build/eclair/makefile
deleted file mode 100644
index 6bb3c13..0000000
--- a/media/libstagefright/codecs/aacenc/build/eclair/makefile
+++ /dev/null
@@ -1,40 +0,0 @@
-#/*
-#** Copyright 2003-2010, VisualOn, Inc.
-#**
-#** Licensed under the Apache License, Version 2.0 (the "License");
-#** you may not use this file except in compliance with the License.
-#** You may obtain a copy of the License at
-#**
-#**     http://www.apache.org/licenses/LICENSE-2.0
-#**
-#** Unless required by applicable law or agreed to in writing, software
-#** distributed under the License is distributed on an "AS IS" BASIS,
-#** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-#** See the License for the specific language governing permissions and
-#** limitations under the License.
-#*/
-
-# Just acting as Father Makefile of Modules
-# please keep the name 'makefile' unchanged
- 
-# Module Subdirs
-VOMSD:=$(dir $(shell find . -name 'Makefile'))
-
-all:
-	for dir in $(VOMSD); \
-		do \
-			$(MAKE) -C $$dir; \
-		done
-
-.PHONY:clean devel
-clean:
-	for dir in $(VOMSD); \
-		do \
-			$(MAKE) -C $$dir clean; \
-		done
-
-devel:
-	for dir in $(VOMSD); \
-		do \
-			$(MAKE) -C $$dir devel; \
-		done
diff --git a/media/libstagefright/codecs/aacenc/build/ms.mk b/media/libstagefright/codecs/aacenc/build/ms.mk
deleted file mode 100644
index b67efbc..0000000
--- a/media/libstagefright/codecs/aacenc/build/ms.mk
+++ /dev/null
@@ -1,42 +0,0 @@
-#/*

-#** Copyright 2003-2010, VisualOn, Inc.

-#**

-#** Licensed under the Apache License, Version 2.0 (the "License");

-#** you may not use this file except in compliance with the License.

-#** You may obtain a copy of the License at

-#**

-#**     http://www.apache.org/licenses/LICENSE-2.0

-#**

-#** Unless required by applicable law or agreed to in writing, software

-#** distributed under the License is distributed on an "AS IS" BASIS,

-#** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

-#** See the License for the specific language governing permissions and

-#** limitations under the License.

-#*/

-

-

-# please list all objects needed by your target here

-OBJS:=basicop2.o oper_32b.o aac_rom.o aacenc.o aacenc_core.o adj_thr.o \

-			band_nrg.o bit_cnt.o bitbuffer.o bitenc.o block_switch.o channel_map.o \

-			dyn_bits.o grp_data.o interface.o line_pe.o memalign.o ms_stereo.o \

-			pre_echo_control.o psy_configuration.o psy_main.o qc_main.o quantize.o sf_estim.o \

-			spreading.o stat_bits.o tns.o transform.o

-			

-# please list all directories that all source files relative with your module(.h .c .cpp) locate 

-VOSRCDIR:=../../../src \

-					../../../inc \

-					../../../basic_op\

-					../../../../../Include 

-					

-ifeq ($(VOTT), v5)

-OBJS+= AutoCorrelation_v5.o band_nrg_v5.o CalcWindowEnergy_v5.o \

-				PrePostMDCT_v5.o R4R8First_v5.o Radix4FFT_v5.o

-VOSRCDIR+= ../../../src/asm/ARMV5E/

-endif	

-

-ifeq ($(VOTT), v7)

-OBJS+= AutoCorrelation_v5.o band_nrg_v5.o CalcWindowEnergy_v5.o \

-			 PrePostMDCT_v7.o R4R8First_v7.o Radix4FFT_v7.o

-VOSRCDIR+= ../../../src/asm/ARMV5E/

-VOSRCDIR+= ../../../src/asm/ARMV7/

-endif		
\ No newline at end of file
diff --git a/media/libstagefright/codecs/amrnb/dec/AMRNBDecoder.cpp b/media/libstagefright/codecs/amrnb/dec/AMRNBDecoder.cpp
index fb300da..a11d46b 100644
--- a/media/libstagefright/codecs/amrnb/dec/AMRNBDecoder.cpp
+++ b/media/libstagefright/codecs/amrnb/dec/AMRNBDecoder.cpp
@@ -14,6 +14,10 @@
  * limitations under the License.
  */
 
+//#define LOG_NDEBUG 0
+#define LOG_TAG "AMRNBDecoder"
+#include <utils/Log.h>
+
 #include "AMRNBDecoder.h"
 
 #include "gsmamr_dec.h"
@@ -154,18 +158,24 @@
     const uint8_t *inputPtr =
         (const uint8_t *)mInputBuffer->data() + mInputBuffer->range_offset();
 
-    size_t numBytesRead =
+    int32_t numBytesRead =
         AMRDecode(mState,
           (Frame_Type_3GPP)((inputPtr[0] >> 3) & 0x0f),
           (UWord8 *)&inputPtr[1],
           static_cast<int16_t *>(buffer->data()),
           MIME_IETF);
 
+    if (numBytesRead == -1 ) {
+        LOGE("PV AMR decoder AMRDecode() call failed");
+        buffer->release();
+        buffer = NULL;
+        return ERROR_MALFORMED;
+    }
     ++numBytesRead;  // Include the frame type header byte.
 
     buffer->set_range(0, kNumSamplesPerFrame * sizeof(int16_t));
 
-    if (numBytesRead > mInputBuffer->range_length()) {
+    if (static_cast<size_t>(numBytesRead) > mInputBuffer->range_length()) {
         // This is bad, should never have happened, but did. Abort now.
 
         buffer->release();
diff --git a/media/libstagefright/codecs/amrwbenc/Android.mk b/media/libstagefright/codecs/amrwbenc/Android.mk
index 4293287..5179380 100644
--- a/media/libstagefright/codecs/amrwbenc/Android.mk
+++ b/media/libstagefright/codecs/amrwbenc/Android.mk
@@ -2,7 +2,7 @@
 include $(CLEAR_VARS)
 include frameworks/base/media/libstagefright/codecs/common/Config.mk
 
-LOCAL_PRELINK_MODULE := false
+
  	
 LOCAL_SRC_FILES := \
 	AMRWBEncoder.cpp \
diff --git a/media/libstagefright/codecs/amrwbenc/SampleCode/AMRWB_E_SAMPLE.c b/media/libstagefright/codecs/amrwbenc/SampleCode/AMRWB_E_SAMPLE.c
index 792d3cc..5e71a5b 100644
--- a/media/libstagefright/codecs/amrwbenc/SampleCode/AMRWB_E_SAMPLE.c
+++ b/media/libstagefright/codecs/amrwbenc/SampleCode/AMRWB_E_SAMPLE.c
@@ -129,7 +129,7 @@
 	useData.memData = (VO_PTR)(&moper);

 

 #ifdef LINUX

-	handle = dlopen("/data/local/tmp/voAMRWBEnc.so", RTLD_NOW);

+	handle = dlopen("libstagefright.so", RTLD_NOW);

 	if(handle == 0)

 	{

 		printf("open dll error......");

diff --git a/media/libstagefright/codecs/amrwbenc/SampleCode/Android.mk b/media/libstagefright/codecs/amrwbenc/SampleCode/Android.mk
index 7edb166..85ddceb 100644
--- a/media/libstagefright/codecs/amrwbenc/SampleCode/Android.mk
+++ b/media/libstagefright/codecs/amrwbenc/SampleCode/Android.mk
@@ -1,26 +1,26 @@
 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_SRC_FILES := 	AMRWB_E_SAMPLE.c
-	
-LOCAL_SRC_FILES += 	\
-	../../../Common/cmnMemory.c 
+LOCAL_SRC_FILES := \
+    AMRWB_E_SAMPLE.c \
+    ../../common/cmnMemory.c
 
-LOCAL_MODULE := TestvoAMRWBEnc
+LOCAL_MODULE_TAGS := debug
+LOCAL_MODULE := AMRWBEncTest
 
 LOCAL_ARM_MODE := arm
 
-LOCAL_STATIC_LIBRARIES := 
+LOCAL_CFLAGS := $(VO_CFLAGS)
 
-LOCAL_SHARED_LIBRARIES := libvoAMRWBEnc
+LOCAL_SHARED_LIBRARIES := \
+    libstagefright \
+    libdl
 
 LOCAL_C_INCLUDES := \
-	$(LOCAL_PATH)/ \
-	$(LOCAL_PATH)/../../../Common \
-	$(LOCAL_PATH)/../../../Include \
+    $(LOCAL_PATH)/ \
+    $(LOCAL_PATH)/../../common \
+    $(LOCAL_PATH)/../../common/include
 
-LOCAL_CFLAGS := $(VO_CFLAGS)
-	
 include $(BUILD_EXECUTABLE)
 
 
diff --git a/media/libstagefright/codecs/amrwbenc/SampleCode/eclair/Makefile b/media/libstagefright/codecs/amrwbenc/SampleCode/eclair/Makefile
deleted file mode 100644
index 55b876a..0000000
--- a/media/libstagefright/codecs/amrwbenc/SampleCode/eclair/Makefile
+++ /dev/null
@@ -1,56 +0,0 @@
-#/*

-# ** Copyright 2003-2010, VisualOn, Inc.

-# **

-# ** Licensed under the Apache License, Version 2.0 (the "License");

-# ** you may not use this file except in compliance with the License.

-# ** You may obtain a copy of the License at

-# **

-# **     http://www.apache.org/licenses/LICENSE-2.0

-# **

-# ** Unless required by applicable law or agreed to in writing, software

-# ** distributed under the License is distributed on an "AS IS" BASIS,

-# ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

-# ** See the License for the specific language governing permissions and

-# ** limitations under the License.

-# */

-

-# target6

-# available: pc, v4(armv4), v5(armv5), v5x(armv5 xscale), v6(armv6), v7(cortex-a8 neon)

-VOTT:= v6

-

-

-# module type

-# please specify the type of your module: lib or exe

-VOMT:= exe

-

-

-# module macros

-# please append the additional macro definitions here for your module if necessary. 

-# e.g. -DVISUALON, macro VISUALON defined for your module 

-VOMM:= #ARMV5E

-

-

-

-# please specify the name of your module

-VOTARGET:= voAMRWBEnc_Test

-

-

-# please modify here to be sure to see the g1.mk

-include ../../../../Tools/eclair.mk 

-

-# dependent libraries.

-VODEPLIBS:=-ldl

-

-

-# module source

-# please modify here to be sure to see the ms.mk which specifies all source info of your module

-include ../ms.mk

-

-

-# please specify where is the voRelease on your PC, relative path is suggested

-VORELDIR:=../

-

-

-# please modify here to be sure to see the doit.mk

-include ../../../../Tools/doit.mk 

-

diff --git a/media/libstagefright/codecs/amrwbenc/SampleCode/ms.mk b/media/libstagefright/codecs/amrwbenc/SampleCode/ms.mk
deleted file mode 100644
index 74e8913..0000000
--- a/media/libstagefright/codecs/amrwbenc/SampleCode/ms.mk
+++ /dev/null
@@ -1,24 +0,0 @@
-#/*

-# ** Copyright 2003-2010, VisualOn, Inc.

-# **

-# ** Licensed under the Apache License, Version 2.0 (the "License");

-# ** you may not use this file except in compliance with the License.

-# ** You may obtain a copy of the License at

-# **

-# **     http://www.apache.org/licenses/LICENSE-2.0

-# **

-# ** Unless required by applicable law or agreed to in writing, software

-# ** distributed under the License is distributed on an "AS IS" BASIS,

-# ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

-# ** See the License for the specific language governing permissions and

-# ** limitations under the License.

-# */

-# please list all objects needed by your target here

-OBJS:=AMRWB_E_SAMPLE.o cmnMemory.o

-			

-# please list all directories that all source files relative with your module(.h .c .cpp) locate 

-VOSRCDIR:=../ \

-          ../../../../Common \

-	  ../../../../Include

-					

-				

diff --git a/media/libstagefright/codecs/amrwbenc/build/eclair/ARMV5E/Makefile b/media/libstagefright/codecs/amrwbenc/build/eclair/ARMV5E/Makefile
deleted file mode 100644
index 58fda29..0000000
--- a/media/libstagefright/codecs/amrwbenc/build/eclair/ARMV5E/Makefile
+++ /dev/null
@@ -1,53 +0,0 @@
-#/*

-# ** Copyright 2003-2010, VisualOn, Inc.

-# **

-# ** Licensed under the Apache License, Version 2.0 (the "License");

-# ** you may not use this file except in compliance with the License.

-# ** You may obtain a copy of the License at

-# **

-# **     http://www.apache.org/licenses/LICENSE-2.0

-# **

-# ** Unless required by applicable law or agreed to in writing, software

-# ** distributed under the License is distributed on an "AS IS" BASIS,

-# ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

-# ** See the License for the specific language governing permissions and

-# ** limitations under the License.

-# */

-

-# target type

-# available: pc, v4(armv4), v5(armv5), v5x(armv5 xscale), v6(armv6), v7(cortex-a8 neon)

-VOTT:= v5

-

-

-# module type

-# please specify the type of your module: lib or exe

-VOMT:= lib

-

-

-# module macros

-# please append the additional macro definitions here for your module if necessary. 

-ifeq ($(VOTT), v5)

-VOMM:=-DARM -DASM_OPT

-endif

-

-# please specify the name of your module

-VOTARGET:= libvoAMRWBEncv5

-

-

-# please modify here to be sure to see the g1.mk

-include ../../../../../Tools/eclair.mk 

-

-# dependent libraries.

-VODEPLIBS:=-ldl -lstdc++ -lcutils

-

-# module source

-# please modify here to be sure to see the ms.mk which specifies all source info of your module

-include ../ms.mk

-

-

-# please specify where is the voRelease on your PC, relative path is suggested

-VORELDIR:=../../../../../../Release

-

-# please modify here to be sure to see the doit.mk

-include ../../../../../Tools/doit.mk 

-

diff --git a/media/libstagefright/codecs/amrwbenc/build/eclair/ARMV7/Makefile b/media/libstagefright/codecs/amrwbenc/build/eclair/ARMV7/Makefile
deleted file mode 100644
index 5686411..0000000
--- a/media/libstagefright/codecs/amrwbenc/build/eclair/ARMV7/Makefile
+++ /dev/null
@@ -1,53 +0,0 @@
-#/*

-# ** Copyright 2003-2010, VisualOn, Inc.

-# **

-# ** Licensed under the Apache License, Version 2.0 (the "License");

-# ** you may not use this file except in compliance with the License.

-# ** You may obtain a copy of the License at

-# **

-# **     http://www.apache.org/licenses/LICENSE-2.0

-# **

-# ** Unless required by applicable law or agreed to in writing, software

-# ** distributed under the License is distributed on an "AS IS" BASIS,

-# ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

-# ** See the License for the specific language governing permissions and

-# ** limitations under the License.

-# */

-

-# target type

-# available: pc, v4(armv4), v5(armv5), v5x(armv5 xscale), v6(armv6), v7(cortex-a8 neon)

-VOTT:= v7

-

-

-# module type

-# please specify the type of your module: lib or exe

-VOMT:= lib

-

-

-# module macros

-# please append the additional macro definitions here for your module if necessary. 

-ifeq ($(VOTT), v7)

-VOMM:=-DARM -DARMV7 -DASM_OPT

-endif

-

-# please specify the name of your module

-VOTARGET:= libvoAMRWBEncv7

-

-

-# please modify here to be sure to see the g1.mk

-include ../../../../../Tools/eclair.mk 

-

-# dependent libraries.

-VODEPLIBS:=-ldl -lstdc++ -lcutils

-

-# module source

-# please modify here to be sure to see the ms.mk which specifies all source info of your module

-include ../ms.mk

-

-

-# please specify where is the voRelease on your PC, relative path is suggested

-VORELDIR:=../../../../../../Release

-

-# please modify here to be sure to see the doit.mk

-include ../../../../../Tools/doit.mk 

-

diff --git a/media/libstagefright/codecs/amrwbenc/build/eclair/makefile b/media/libstagefright/codecs/amrwbenc/build/eclair/makefile
deleted file mode 100644
index 3473a1a..0000000
--- a/media/libstagefright/codecs/amrwbenc/build/eclair/makefile
+++ /dev/null
@@ -1,39 +0,0 @@
-#/*
-# ** Copyright 2003-2010, VisualOn, Inc.
-# **
-# ** Licensed under the Apache License, Version 2.0 (the "License");
-# ** you may not use this file except in compliance with the License.
-# ** You may obtain a copy of the License at
-# **
-# **     http://www.apache.org/licenses/LICENSE-2.0
-# **
-# ** Unless required by applicable law or agreed to in writing, software
-# ** distributed under the License is distributed on an "AS IS" BASIS,
-# ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# ** See the License for the specific language governing permissions and
-# ** limitations under the License.
-# */
-# Just acting as Father Makefile of Modules
-# please keep the name 'makefile' unchanged
- 
-# Module Subdirs
-VOMSD:=$(dir $(shell find . -name 'Makefile'))
-
-all:
-	for dir in $(VOMSD); \
-		do \
-			$(MAKE) -C $$dir; \
-		done
-
-.PHONY:clean devel
-clean:
-	for dir in $(VOMSD); \
-		do \
-			$(MAKE) -C $$dir clean; \
-		done
-
-devel:
-	for dir in $(VOMSD); \
-		do \
-			$(MAKE) -C $$dir devel; \
-		done
diff --git a/media/libstagefright/codecs/amrwbenc/build/eclair/ms.mk b/media/libstagefright/codecs/amrwbenc/build/eclair/ms.mk
deleted file mode 100644
index bd6620c..0000000
--- a/media/libstagefright/codecs/amrwbenc/build/eclair/ms.mk
+++ /dev/null
@@ -1,43 +0,0 @@
-#/*

-# ** Copyright 2003-2010, VisualOn, Inc.

-# **

-# ** Licensed under the Apache License, Version 2.0 (the "License");

-# ** you may not use this file except in compliance with the License.

-# ** You may obtain a copy of the License at

-# **

-# **     http://www.apache.org/licenses/LICENSE-2.0

-# **

-# ** Unless required by applicable law or agreed to in writing, software

-# ** distributed under the License is distributed on an "AS IS" BASIS,

-# ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

-# ** See the License for the specific language governing permissions and

-# ** limitations under the License.

-# */

-# please list all directories that all source files relative with your module(.h .c .cpp) locate 

-VOSRCDIR:=../../../inc \

-          ../../../src \

-	  ../../../../../Include 

-

-# please list all objects needed by your target here

-OBJS:= autocorr.o az_isp.o bits.o c2t64fx.o c4t64fx.o convolve.o cor_h_x.o decim54.o \

-       deemph.o dtx.o g_pitch.o gpclip.o homing.o hp400.o hp50.o hp6k.o hp_wsp.o \

-       int_lpc.o isp_az.o isp_isf.o lag_wind.o levinson.o log2.o lp_dec2.o math_op.o mem_align.o \

-       oper_32b.o p_med_ol.o pit_shrp.o pitch_f4.o pred_lt4.o preemph.o q_gain2.o q_pulse.o \

-       qisf_ns.o qpisf_2s.o random.o residu.o scale.o stream.o syn_filt.o updt_tar.o util.o \

-       voAMRWBEnc.o voicefac.o wb_vad.o weight_a.o

-			

-

-ifeq ($(VOTT), v5)

-OBJS += cor_h_vec_opt.o Deemph_32_opt.o Dot_p_opt.o Filt_6k_7k_opt.o residu_asm_opt.o \

-       scale_sig_opt.o Syn_filt_32_opt.o syn_filt_opt.o pred_lt4_1_opt.o convolve_opt.o \

-       Norm_Corr_opt.o

-VOSRCDIR+= ../../../src/asm/ARMV5E

-endif

-

-ifeq ($(VOTT), v7)

-OBJS+= cor_h_vec_neon.o Deemph_32_neon.o Dot_p_neon.o Filt_6k_7k_neon.o residu_asm_neon.o \

-       scale_sig_neon.o Syn_filt_32_neon.o syn_filt_neon.o pred_lt4_1_neon.o convolve_neon.o \

-       Norm_Corr_neon.o

-VOSRCDIR+= ../../../src/asm/ARMV7

-endif

-

diff --git a/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp b/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp
index 5bbba35..490129f 100644
--- a/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp
+++ b/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp
@@ -534,7 +534,8 @@
             default:
             {
                 LOGE("Should not be here, unknown nalType %d", nalType);
-                CHECK(!"Should not be here");
+
+                err = ERROR_MALFORMED;
                 break;
             }
         }
diff --git a/media/libstagefright/codecs/common/Android.mk b/media/libstagefright/codecs/common/Android.mk
index fffb2ad..af8795a 100644
--- a/media/libstagefright/codecs/common/Android.mk
+++ b/media/libstagefright/codecs/common/Android.mk
@@ -1,7 +1,7 @@
 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_PRELINK_MODULE := false
+
 
 LOCAL_SRC_FILES := cmnMemory.c
 
diff --git a/media/libstagefright/codecs/mp3dec/MP3Decoder.cpp b/media/libstagefright/codecs/mp3dec/MP3Decoder.cpp
index 59dd740..0ba42ff 100644
--- a/media/libstagefright/codecs/mp3dec/MP3Decoder.cpp
+++ b/media/libstagefright/codecs/mp3dec/MP3Decoder.cpp
@@ -14,6 +14,9 @@
  * limitations under the License.
  */
 
+//#define LOG_NDEBUG 0
+#define LOG_TAG "MP3Decoder"
+
 #include "MP3Decoder.h"
 
 #include "include/pvmp3decoder_api.h"
@@ -175,7 +178,12 @@
             != NO_DECODING_ERROR) {
         LOGV("mp3 decoder returned error %d", decoderErr);
 
-        if (decoderErr != NO_ENOUGH_MAIN_DATA_ERROR) {
+        if (decoderErr != NO_ENOUGH_MAIN_DATA_ERROR ||
+                mConfig->outputFrameSize == 0) {
+
+            if (mConfig->outputFrameSize == 0) {
+                LOGE("Output frame size is 0");
+            }
             buffer->release();
             buffer = NULL;
 
diff --git a/media/libstagefright/foundation/ALooper.cpp b/media/libstagefright/foundation/ALooper.cpp
index b7087f8..a5b316d 100644
--- a/media/libstagefright/foundation/ALooper.cpp
+++ b/media/libstagefright/foundation/ALooper.cpp
@@ -33,18 +33,30 @@
 struct ALooper::LooperThread : public Thread {
     LooperThread(ALooper *looper, bool canCallJava)
         : Thread(canCallJava),
-          mLooper(looper) {
+          mLooper(looper),
+          mThreadId(NULL) {
+    }
+
+    virtual status_t readyToRun() {
+        mThreadId = androidGetThreadId();
+
+        return Thread::readyToRun();
     }
 
     virtual bool threadLoop() {
         return mLooper->loop();
     }
 
+    bool isCurrentThread() const {
+        return mThreadId == androidGetThreadId();
+    }
+
 protected:
     virtual ~LooperThread() {}
 
 private:
     ALooper *mLooper;
+    android_thread_id_t mThreadId;
 
     DISALLOW_EVIL_CONSTRUCTORS(LooperThread);
 };
@@ -136,7 +148,9 @@
 
     mQueueChangedCondition.signal();
 
-    if (!runningLocally) {
+    if (!runningLocally && !thread->isCurrentThread()) {
+        // If not running locally and this thread _is_ the looper thread,
+        // the loop() function will return and never be called again.
         thread->requestExitAndWait();
     }
 
@@ -197,6 +211,11 @@
 
     gLooperRoster.deliverMessage(event.mMessage);
 
+    // NOTE: It's important to note that at this point our "ALooper" object
+    // may no longer exist (its final reference may have gone away while
+    // delivering the message). We have made sure, however, that loop()
+    // won't be called again.
+
     return true;
 }
 
diff --git a/media/libstagefright/foundation/Android.mk b/media/libstagefright/foundation/Android.mk
index 4e07f6f..d5025a1 100644
--- a/media/libstagefright/foundation/Android.mk
+++ b/media/libstagefright/foundation/Android.mk
@@ -25,6 +25,6 @@
 
 LOCAL_MODULE:= libstagefright_foundation
 
-LOCAL_PRELINK_MODULE:= false
+
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libstagefright/httplive/LiveSession.cpp b/media/libstagefright/httplive/LiveSession.cpp
index f0cd6a0..8e1bdf3 100644
--- a/media/libstagefright/httplive/LiveSession.cpp
+++ b/media/libstagefright/httplive/LiveSession.cpp
@@ -23,7 +23,7 @@
 #include "LiveDataSource.h"
 
 #include "include/M3UParser.h"
-#include "include/NuHTTPDataSource.h"
+#include "include/HTTPBase.h"
 
 #include <cutils/properties.h>
 #include <media/stagefright/foundation/hexdump.h>
@@ -45,9 +45,9 @@
     : mFlags(flags),
       mDataSource(new LiveDataSource),
       mHTTPDataSource(
-              new NuHTTPDataSource(
+              HTTPBase::Create(
                   (mFlags & kFlagIncognito)
-                    ? NuHTTPDataSource::kFlagIncognito
+                    ? HTTPBase::kFlagIncognito
                     : 0)),
       mPrevBandwidthIndex(-1),
       mLastPlaylistFetchTimeUs(-1),
@@ -625,7 +625,12 @@
     } else {
         key = new ABuffer(16);
 
-        sp<NuHTTPDataSource> keySource = new NuHTTPDataSource;
+        sp<HTTPBase> keySource =
+              HTTPBase::Create(
+                  (mFlags & kFlagIncognito)
+                    ? HTTPBase::kFlagIncognito
+                    : 0);
+
         status_t err = keySource->connect(keyURI.c_str());
 
         if (err == OK) {
diff --git a/media/libstagefright/include/AVIExtractor.h b/media/libstagefright/include/AVIExtractor.h
new file mode 100644
index 0000000..375a94d
--- /dev/null
+++ b/media/libstagefright/include/AVIExtractor.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AVI_EXTRACTOR_H_
+
+#define AVI_EXTRACTOR_H_
+
+#include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/MediaExtractor.h>
+#include <media/stagefright/MediaSource.h>
+#include <utils/Vector.h>
+
+namespace android {
+
+struct AVIExtractor : public MediaExtractor {
+    AVIExtractor(const sp<DataSource> &dataSource);
+
+    virtual size_t countTracks();
+
+    virtual sp<MediaSource> getTrack(size_t index);
+
+    virtual sp<MetaData> getTrackMetaData(
+            size_t index, uint32_t flags);
+
+    virtual sp<MetaData> getMetaData();
+
+protected:
+    virtual ~AVIExtractor();
+
+private:
+    struct AVISource;
+
+    struct SampleInfo {
+        uint32_t mOffset;
+        bool mIsKey;
+    };
+
+    struct Track {
+        sp<MetaData> mMeta;
+        Vector<SampleInfo> mSamples;
+        uint32_t mRate;
+        uint32_t mScale;
+
+        enum Kind {
+            AUDIO,
+            VIDEO,
+            OTHER
+
+        } mKind;
+
+        size_t mNumSyncSamples;
+        size_t mThumbnailSampleSize;
+        ssize_t mThumbnailSampleIndex;
+        size_t mMaxSampleSize;
+    };
+
+    sp<DataSource> mDataSource;
+    status_t mInitCheck;
+    Vector<Track> mTracks;
+
+    off64_t mMovieOffset;
+    bool mFoundIndex;
+    bool mOffsetsAreAbsolute;
+
+    ssize_t parseChunk(off64_t offset, off64_t size, int depth = 0);
+    status_t parseStreamHeader(off64_t offset, size_t size);
+    status_t parseStreamFormat(off64_t offset, size_t size);
+    status_t parseIndex(off64_t offset, size_t size);
+
+    status_t parseHeaders();
+
+    status_t getSampleInfo(
+            size_t trackIndex, size_t sampleIndex,
+            off64_t *offset, size_t *size, bool *isKey);
+
+    status_t getSampleIndexAtTime(
+            size_t trackIndex,
+            int64_t timeUs, MediaSource::ReadOptions::SeekMode mode,
+            size_t *sampleIndex) const;
+
+    status_t addMPEG4CodecSpecificData(size_t trackIndex);
+
+    static bool IsCorrectChunkType(
+        ssize_t trackIndex, Track::Kind kind, uint32_t chunkType);
+
+    DISALLOW_EVIL_CONSTRUCTORS(AVIExtractor);
+};
+
+class String8;
+struct AMessage;
+
+bool SniffAVI(
+        const sp<DataSource> &source, String8 *mimeType, float *confidence,
+        sp<AMessage> *);
+
+}  // namespace android
+
+#endif  // AVI_EXTRACTOR_H_
diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h
index 4e6f75c..a9b7ae8 100644
--- a/media/libstagefright/include/AwesomePlayer.h
+++ b/media/libstagefright/include/AwesomePlayer.h
@@ -18,7 +18,7 @@
 
 #define AWESOME_PLAYER_H_
 
-#include "NuHTTPDataSource.h"
+#include "HTTPBase.h"
 #include "TimedEventQueue.h"
 
 #include <media/MediaPlayerInterface.h>
@@ -93,7 +93,7 @@
     // This is a mask of MediaExtractor::Flags.
     uint32_t flags() const;
 
-    void postAudioEOS();
+    void postAudioEOS(int64_t delayUs = 0ll);
     void postAudioSeekComplete();
 
 private:
@@ -203,13 +203,13 @@
     void postVideoEvent_l(int64_t delayUs = -1);
     void postBufferingEvent_l();
     void postStreamDoneEvent_l(status_t status);
-    void postCheckAudioStatusEvent_l();
+    void postCheckAudioStatusEvent_l(int64_t delayUs);
     void postVideoLagEvent_l();
     status_t play_l();
 
     MediaBuffer *mVideoBuffer;
 
-    sp<NuHTTPDataSource> mConnectingDataSource;
+    sp<HTTPBase> mConnectingDataSource;
     sp<NuCachedSource2> mCachedSource;
 
     sp<ALooper> mLooper;
@@ -217,7 +217,7 @@
     sp<ARTSPController> mConnectingRTSPController;
 
     DrmManagerClient *mDrmManagerClient;
-    DecryptHandle *mDecryptHandle;
+    sp<DecryptHandle> mDecryptHandle;
 
     status_t setDataSource_l(
             const char *uri,
diff --git a/media/libstagefright/include/ChromiumHTTPDataSource.h b/media/libstagefright/include/ChromiumHTTPDataSource.h
new file mode 100644
index 0000000..0e2927d
--- /dev/null
+++ b/media/libstagefright/include/ChromiumHTTPDataSource.h
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CHROME_HTTP_DATA_SOURCE_H_
+
+#define CHROME_HTTP_DATA_SOURCE_H_
+
+#include <media/stagefright/foundation/AString.h>
+#include <utils/threads.h>
+
+#include "HTTPBase.h"
+
+namespace android {
+
+struct SfDelegate;
+
+struct ChromiumHTTPDataSource : public HTTPBase {
+    ChromiumHTTPDataSource(uint32_t flags = 0);
+
+    virtual status_t connect(
+            const char *uri,
+            const KeyedVector<String8, String8> *headers = NULL,
+            off64_t offset = 0);
+
+    virtual void disconnect();
+
+    virtual status_t initCheck() const;
+
+    virtual ssize_t readAt(off64_t offset, void *data, size_t size);
+    virtual status_t getSize(off64_t *size);
+    virtual uint32_t flags();
+
+    virtual bool estimateBandwidth(int32_t *bandwidth_bps);
+
+    virtual sp<DecryptHandle> DrmInitialization();
+
+    virtual void getDrmInfo(sp<DecryptHandle> &handle, DrmManagerClient **client);
+
+    virtual String8 getUri();
+
+    virtual String8 getMIMEType() const;
+
+protected:
+    virtual ~ChromiumHTTPDataSource();
+
+private:
+    friend struct SfDelegate;
+
+    enum State {
+        DISCONNECTED,
+        CONNECTING,
+        CONNECTED,
+        READING,
+        DISCONNECTING
+    };
+
+    struct BandwidthEntry {
+        int64_t mDelayUs;
+        size_t mNumBytes;
+    };
+
+    const uint32_t mFlags;
+
+    mutable Mutex mLock;
+    Condition mCondition;
+
+    State mState;
+
+    SfDelegate *mDelegate;
+
+    AString mURI;
+    KeyedVector<String8, String8> mHeaders;
+
+    off64_t mCurrentOffset;
+
+    // Any connection error or the result of a read operation
+    // (for the lattter this is the number of bytes read, if successful).
+    ssize_t mIOResult;
+
+    int64_t mContentSize;
+
+    String8 mContentType;
+
+    List<BandwidthEntry> mBandwidthHistory;
+    size_t mNumBandwidthHistoryItems;
+    int64_t mTotalTransferTimeUs;
+    size_t mTotalTransferBytes;
+
+    sp<DecryptHandle> mDecryptHandle;
+    DrmManagerClient *mDrmManagerClient;
+
+    void disconnect_l();
+
+    status_t connect_l(
+            const char *uri,
+            const KeyedVector<String8, String8> *headers,
+            off64_t offset);
+
+    static void InitiateRead(
+            ChromiumHTTPDataSource *me, void *data, size_t size);
+
+    void initiateRead(void *data, size_t size);
+
+    void onConnectionEstablished(
+            int64_t contentSize, const char *contentType);
+
+    void onConnectionFailed(status_t err);
+    void onReadCompleted(ssize_t size);
+    void onDisconnectComplete();
+
+    void addBandwidthMeasurement_l(size_t numBytes, int64_t delayUs);
+
+    void clearDRMState_l();
+
+    DISALLOW_EVIL_CONSTRUCTORS(ChromiumHTTPDataSource);
+};
+
+}  // namespace android
+
+#endif  // CHROME_HTTP_DATA_SOURCE_H_
diff --git a/media/libstagefright/include/DRMExtractor.h b/media/libstagefright/include/DRMExtractor.h
index 9881cc1..b4e4afb 100644
--- a/media/libstagefright/include/DRMExtractor.h
+++ b/media/libstagefright/include/DRMExtractor.h
@@ -45,7 +45,7 @@
     sp<DataSource> mDataSource;
 
     sp<MediaExtractor> mOriginalExtractor;
-    DecryptHandle* mDecryptHandle;
+    sp<DecryptHandle> mDecryptHandle;
     DrmManagerClient* mDrmManagerClient;
 
     DRMExtractor(const DRMExtractor &);
diff --git a/media/libstagefright/include/HTTPBase.h b/media/libstagefright/include/HTTPBase.h
new file mode 100644
index 0000000..6cec390
--- /dev/null
+++ b/media/libstagefright/include/HTTPBase.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef HTTP_BASE_H_
+
+#define HTTP_BASE_H_
+
+#include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/DataSource.h>
+
+namespace android {
+
+struct HTTPBase : public DataSource {
+    enum Flags {
+        // Don't log any URLs.
+        kFlagIncognito = 1
+    };
+
+    HTTPBase();
+
+    virtual status_t connect(
+            const char *uri,
+            const KeyedVector<String8, String8> *headers = NULL,
+            off64_t offset = 0) = 0;
+
+    virtual void disconnect() = 0;
+
+    // Returns true if bandwidth could successfully be estimated,
+    // false otherwise.
+    virtual bool estimateBandwidth(int32_t *bandwidth_bps) = 0;
+
+    static sp<HTTPBase> Create(uint32_t flags = 0);
+
+private:
+    DISALLOW_EVIL_CONSTRUCTORS(HTTPBase);
+};
+
+}  // namespace android
+
+#endif  // HTTP_BASE_H_
diff --git a/media/libstagefright/include/LiveSession.h b/media/libstagefright/include/LiveSession.h
index 3fe5d4e..2b5ea0e 100644
--- a/media/libstagefright/include/LiveSession.h
+++ b/media/libstagefright/include/LiveSession.h
@@ -26,7 +26,7 @@
 struct DataSource;
 struct LiveDataSource;
 struct M3UParser;
-struct NuHTTPDataSource;
+struct HTTPBase;
 
 struct LiveSession : public AHandler {
     enum Flags {
@@ -75,7 +75,7 @@
 
     sp<LiveDataSource> mDataSource;
 
-    sp<NuHTTPDataSource> mHTTPDataSource;
+    sp<HTTPBase> mHTTPDataSource;
 
     AString mMasterURL;
     Vector<BandwidthItem> mBandwidthItems;
diff --git a/media/libstagefright/include/MPEG4Extractor.h b/media/libstagefright/include/MPEG4Extractor.h
index 04e8a6a..d9ef208 100644
--- a/media/libstagefright/include/MPEG4Extractor.h
+++ b/media/libstagefright/include/MPEG4Extractor.h
@@ -57,7 +57,7 @@
     };
 
     sp<DataSource> mDataSource;
-    bool mHaveMetadata;
+    status_t mInitCheck;
     bool mHasVideo;
 
     Track *mFirstTrack, *mLastTrack;
@@ -90,6 +90,10 @@
 
     status_t parseTrackHeader(off64_t data_offset, off64_t data_size);
 
+    Track *findTrackByMimePrefix(const char *mimePrefix);
+
+    status_t verifyIfStreamable();
+
     MPEG4Extractor(const MPEG4Extractor &);
     MPEG4Extractor &operator=(const MPEG4Extractor &);
 };
diff --git a/media/libstagefright/include/NuCachedSource2.h b/media/libstagefright/include/NuCachedSource2.h
index 022804c..2128682 100644
--- a/media/libstagefright/include/NuCachedSource2.h
+++ b/media/libstagefright/include/NuCachedSource2.h
@@ -37,9 +37,12 @@
     virtual status_t getSize(off64_t *size);
     virtual uint32_t flags();
 
-    virtual DecryptHandle* DrmInitialization();
-    virtual void getDrmInfo(DecryptHandle **handle, DrmManagerClient **client);
+    virtual sp<DecryptHandle> DrmInitialization();
+    virtual void getDrmInfo(sp<DecryptHandle> &handle, DrmManagerClient **client);
     virtual String8 getUri();
+
+    virtual String8 getMIMEType() const;
+
     ////////////////////////////////////////////////////////////////////////////
 
     size_t cachedSize();
diff --git a/media/libstagefright/include/NuHTTPDataSource.h b/media/libstagefright/include/NuHTTPDataSource.h
index 2569568..2ab1f19 100644
--- a/media/libstagefright/include/NuHTTPDataSource.h
+++ b/media/libstagefright/include/NuHTTPDataSource.h
@@ -18,28 +18,24 @@
 
 #define NU_HTTP_DATA_SOURCE_H_
 
-#include <media/stagefright/DataSource.h>
 #include <utils/List.h>
 #include <utils/String8.h>
 #include <utils/threads.h>
 
 #include "HTTPStream.h"
+#include "include/HTTPBase.h"
 
 namespace android {
 
-struct NuHTTPDataSource : public DataSource {
-    enum Flags {
-        // Don't log any URLs.
-        kFlagIncognito = 1
-    };
+struct NuHTTPDataSource : public HTTPBase {
     NuHTTPDataSource(uint32_t flags = 0);
 
-    status_t connect(
+    virtual status_t connect(
             const char *uri,
             const KeyedVector<String8, String8> *headers = NULL,
             off64_t offset = 0);
 
-    void disconnect();
+    virtual void disconnect();
 
     virtual status_t initCheck() const;
 
@@ -49,12 +45,14 @@
 
     // Returns true if bandwidth could successfully be estimated,
     // false otherwise.
-    bool estimateBandwidth(int32_t *bandwidth_bps);
+    virtual bool estimateBandwidth(int32_t *bandwidth_bps);
 
-    virtual DecryptHandle* DrmInitialization();
-    virtual void getDrmInfo(DecryptHandle **handle, DrmManagerClient **client);
+    virtual sp<DecryptHandle> DrmInitialization();
+    virtual void getDrmInfo(sp<DecryptHandle> &handle, DrmManagerClient **client);
     virtual String8 getUri();
 
+    virtual String8 getMIMEType() const;
+
 protected:
     virtual ~NuHTTPDataSource();
 
@@ -89,6 +87,8 @@
     bool mContentLengthValid;
     bool mHasChunkedTransferEncoding;
 
+    String8 mContentType;
+
     // The number of data bytes in the current chunk before any subsequent
     // chunk header (or -1 if no more chunks).
     ssize_t mChunkDataBytesLeft;
@@ -98,7 +98,7 @@
     int64_t mTotalTransferTimeUs;
     size_t mTotalTransferBytes;
 
-    DecryptHandle *mDecryptHandle;
+    sp<DecryptHandle> mDecryptHandle;
     DrmManagerClient *mDrmManagerClient;
 
     status_t connect(
diff --git a/media/libstagefright/include/StagefrightMetadataRetriever.h b/media/libstagefright/include/StagefrightMetadataRetriever.h
index 07b1ec8..b02ed0e 100644
--- a/media/libstagefright/include/StagefrightMetadataRetriever.h
+++ b/media/libstagefright/include/StagefrightMetadataRetriever.h
@@ -32,7 +32,10 @@
     StagefrightMetadataRetriever();
     virtual ~StagefrightMetadataRetriever();
 
-    virtual status_t setDataSource(const char *url);
+    virtual status_t setDataSource(
+            const char *url,
+            const KeyedVector<String8, String8> *headers);
+
     virtual status_t setDataSource(int fd, int64_t offset, int64_t length);
 
     virtual VideoFrame *getFrameAtTime(int64_t timeUs, int option);
diff --git a/media/libstagefright/matroska/MatroskaExtractor.cpp b/media/libstagefright/matroska/MatroskaExtractor.cpp
index 733de92b..b3e29b9 100644
--- a/media/libstagefright/matroska/MatroskaExtractor.cpp
+++ b/media/libstagefright/matroska/MatroskaExtractor.cpp
@@ -60,7 +60,10 @@
     virtual int Length(long long* total, long long* available) {
         off64_t size;
         if (mSource->getSize(&size) != OK) {
-            return -1;
+            *total = -1;
+            *available = (long long)((1ull << 63) - 1);
+
+            return 0;
         }
 
         if (total) {
@@ -84,7 +87,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 struct BlockIterator {
-    BlockIterator(mkvparser::Segment *segment, unsigned long trackNum);
+    BlockIterator(MatroskaExtractor *extractor, unsigned long trackNum);
 
     bool eos() const;
 
@@ -96,11 +99,14 @@
     int64_t blockTimeUs() const;
 
 private:
-    mkvparser::Segment *mSegment;
+    MatroskaExtractor *mExtractor;
     unsigned long mTrackNum;
 
-    mkvparser::Cluster *mCluster;
+    const mkvparser::Cluster *mCluster;
     const mkvparser::BlockEntry *mBlockEntry;
+    long mBlockEntryIndex;
+
+    void advance_l();
 
     BlockIterator(const BlockIterator &);
     BlockIterator &operator=(const BlockIterator &);
@@ -150,7 +156,7 @@
     : mExtractor(extractor),
       mTrackIndex(index),
       mType(OTHER),
-      mBlockIter(mExtractor->mSegment,
+      mBlockIter(mExtractor.get(),
                  mExtractor->mTracks.itemAt(index).mTrackNum),
       mNALSizeLen(0) {
     sp<MetaData> meta = mExtractor->mTracks.itemAt(index).mMeta;
@@ -199,11 +205,12 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 BlockIterator::BlockIterator(
-        mkvparser::Segment *segment, unsigned long trackNum)
-    : mSegment(segment),
+        MatroskaExtractor *extractor, unsigned long trackNum)
+    : mExtractor(extractor),
       mTrackNum(trackNum),
       mCluster(NULL),
-      mBlockEntry(NULL) {
+      mBlockEntry(NULL),
+      mBlockEntryIndex(0) {
     reset();
 }
 
@@ -212,45 +219,97 @@
 }
 
 void BlockIterator::advance() {
-    while (!eos()) {
-        if (mBlockEntry != NULL) {
-            mBlockEntry = mCluster->GetNext(mBlockEntry);
-        } else if (mCluster != NULL) {
-            mCluster = mSegment->GetNext(mCluster);
+    Mutex::Autolock autoLock(mExtractor->mLock);
+    advance_l();
+}
 
-            if (eos()) {
+void BlockIterator::advance_l() {
+    for (;;) {
+        long res = mCluster->GetEntry(mBlockEntryIndex, mBlockEntry);
+        LOGV("GetEntry returned %ld", res);
+
+        long long pos;
+        long len;
+        if (res < 0) {
+            // Need to parse this cluster some more
+
+            CHECK_EQ(res, mkvparser::E_BUFFER_NOT_FULL);
+
+            res = mCluster->Parse(pos, len);
+            LOGV("Parse returned %ld", res);
+
+            if (res < 0) {
+                // I/O error
+
+                LOGE("Cluster::Parse returned result %ld", res);
+
+                mCluster = NULL;
                 break;
             }
 
-            mBlockEntry = mCluster->GetFirst();
+            continue;
+        } else if (res == 0) {
+            // We're done with this cluster
+
+            const mkvparser::Cluster *nextCluster;
+            res = mExtractor->mSegment->ParseNext(
+                    mCluster, nextCluster, pos, len);
+            LOGV("ParseNext returned %ld", res);
+
+            if (res > 0) {
+                // EOF
+
+                mCluster = NULL;
+                break;
+            }
+
+            CHECK_EQ(res, 0);
+            CHECK(nextCluster != NULL);
+            CHECK(!nextCluster->EOS());
+
+            mCluster = nextCluster;
+
+            res = mCluster->Parse(pos, len);
+            LOGV("Parse (2) returned %ld", res);
+            CHECK_GE(res, 0);
+
+            mBlockEntryIndex = 0;
+            continue;
         }
 
-        if (mBlockEntry != NULL
-                && mBlockEntry->GetBlock()->GetTrackNumber() == mTrackNum) {
+        CHECK(mBlockEntry != NULL);
+        CHECK(mBlockEntry->GetBlock() != NULL);
+        ++mBlockEntryIndex;
+
+        if (mBlockEntry->GetBlock()->GetTrackNumber() == mTrackNum) {
             break;
         }
     }
 }
 
 void BlockIterator::reset() {
-    mCluster = mSegment->GetFirst();
-    mBlockEntry = mCluster->GetFirst();
+    Mutex::Autolock autoLock(mExtractor->mLock);
 
-    while (!eos() && block()->GetTrackNumber() != mTrackNum) {
-        advance();
-    }
+    mCluster = mExtractor->mSegment->GetFirst();
+    mBlockEntryIndex = 0;
+
+    do {
+        advance_l();
+    } while (!eos() && block()->GetTrackNumber() != mTrackNum);
 }
 
 void BlockIterator::seek(int64_t seekTimeUs) {
-    mCluster = mSegment->FindCluster(seekTimeUs * 1000ll);
-    mBlockEntry = mCluster != NULL ? mCluster->GetFirst() : NULL;
+    Mutex::Autolock autoLock(mExtractor->mLock);
+
+    mCluster = mExtractor->mSegment->FindCluster(seekTimeUs * 1000ll);
+    mBlockEntryIndex = 0;
 
     while (!eos() && block()->GetTrackNumber() != mTrackNum) {
-        advance();
+        advance_l();
     }
 
     while (!eos() && !mBlockEntry->GetBlock()->IsKey()) {
-        advance();
+        advance_l();
     }
 }
 
@@ -291,16 +350,6 @@
     }
 }
 
-#define BAIL(err) \
-    do {                        \
-        if (bigbuf) {           \
-            bigbuf->release();  \
-            bigbuf = NULL;      \
-        }                       \
-                                \
-        return err;             \
-    } while (0)
-
 status_t MatroskaSource::readBlock() {
     CHECK(mPendingFrames.empty());
 
@@ -310,181 +359,39 @@
 
     const mkvparser::Block *block = mBlockIter.block();
 
-    size_t size = block->GetSize();
     int64_t timeUs = mBlockIter.blockTimeUs();
-    int32_t isSync = block->IsKey();
 
-    MediaBuffer *bigbuf = new MediaBuffer(size);
+    for (int i = 0; i < block->GetFrameCount(); ++i) {
+        const mkvparser::Block::Frame &frame = block->GetFrame(i);
 
-    long res = block->Read(
-            mExtractor->mReader, (unsigned char *)bigbuf->data());
+        MediaBuffer *mbuf = new MediaBuffer(frame.len);
+        mbuf->meta_data()->setInt64(kKeyTime, timeUs);
+        mbuf->meta_data()->setInt32(kKeyIsSyncFrame, block->IsKey());
 
-    if (res != 0) {
-        bigbuf->release();
-        bigbuf = NULL;
+        long n = frame.Read(mExtractor->mReader, (unsigned char *)mbuf->data());
+        if (n != 0) {
+            mPendingFrames.clear();
 
-        return ERROR_END_OF_STREAM;
+            mBlockIter.advance();
+            return ERROR_IO;
+        }
+
+        mPendingFrames.push_back(mbuf);
     }
 
     mBlockIter.advance();
 
-    bigbuf->meta_data()->setInt64(kKeyTime, timeUs);
-    bigbuf->meta_data()->setInt32(kKeyIsSyncFrame, isSync);
-
-    unsigned lacing = (block->Flags() >> 1) & 3;
-
-    if (lacing == 0) {
-        mPendingFrames.push_back(bigbuf);
-        return OK;
-    }
-
-    LOGV("lacing = %u, size = %d", lacing, size);
-
-    const uint8_t *data = (const uint8_t *)bigbuf->data();
-    // hexdump(data, size);
-
-    if (size == 0) {
-        BAIL(ERROR_MALFORMED);
-    }
-
-    unsigned numFrames = (unsigned)data[0] + 1;
-    ++data;
-    --size;
-
-    Vector<uint64_t> frameSizes;
-
-    switch (lacing) {
-        case 1:  // Xiph
-        {
-            for (size_t i = 0; i < numFrames - 1; ++i) {
-                size_t frameSize = 0;
-                uint8_t byte;
-                do {
-                    if (size == 0) {
-                        BAIL(ERROR_MALFORMED);
-                    }
-                    byte = data[0];
-                    ++data;
-                    --size;
-
-                    frameSize += byte;
-                } while (byte == 0xff);
-
-                frameSizes.push(frameSize);
-            }
-
-            break;
-        }
-
-        case 2:  // fixed-size
-        {
-            if ((size % numFrames) != 0) {
-                BAIL(ERROR_MALFORMED);
-            }
-
-            size_t frameSize = size / numFrames;
-            for (size_t i = 0; i < numFrames - 1; ++i) {
-                frameSizes.push(frameSize);
-            }
-
-            break;
-        }
-
-        case 3:  // EBML
-        {
-            uint64_t lastFrameSize = 0;
-            for (size_t i = 0; i < numFrames - 1; ++i) {
-                uint8_t byte;
-
-                if (size == 0) {
-                    BAIL(ERROR_MALFORMED);
-                }
-                byte = data[0];
-                ++data;
-                --size;
-
-                size_t numLeadingZeroes = clz(byte);
-
-                uint64_t frameSize = byte & ~(0x80 >> numLeadingZeroes);
-                for (size_t j = 0; j < numLeadingZeroes; ++j) {
-                    if (size == 0) {
-                        BAIL(ERROR_MALFORMED);
-                    }
-
-                    frameSize = frameSize << 8;
-                    frameSize |= data[0];
-                    ++data;
-                    --size;
-                }
-
-                if (i == 0) {
-                    frameSizes.push(frameSize);
-                } else {
-                    size_t shift =
-                        7 - numLeadingZeroes + 8 * numLeadingZeroes;
-
-                    int64_t delta =
-                        (int64_t)frameSize - (1ll << (shift - 1)) + 1;
-
-                    frameSize = lastFrameSize + delta;
-
-                    frameSizes.push(frameSize);
-                }
-
-                lastFrameSize = frameSize;
-            }
-            break;
-        }
-
-        default:
-            TRESPASS();
-    }
-
-#if 0
-    AString out;
-    for (size_t i = 0; i < frameSizes.size(); ++i) {
-        if (i > 0) {
-            out.append(", ");
-        }
-        out.append(StringPrintf("%llu", frameSizes.itemAt(i)));
-    }
-    LOGV("sizes = [%s]", out.c_str());
-#endif
-
-    for (size_t i = 0; i < frameSizes.size(); ++i) {
-        uint64_t frameSize = frameSizes.itemAt(i);
-
-        if (size < frameSize) {
-            BAIL(ERROR_MALFORMED);
-        }
-
-        MediaBuffer *mbuf = new MediaBuffer(frameSize);
-        mbuf->meta_data()->setInt64(kKeyTime, timeUs);
-        mbuf->meta_data()->setInt32(kKeyIsSyncFrame, isSync);
-        memcpy(mbuf->data(), data, frameSize);
-        mPendingFrames.push_back(mbuf);
-
-        data += frameSize;
-        size -= frameSize;
-    }
-
-    size_t offset = bigbuf->range_length() - size;
-    bigbuf->set_range(offset, size);
-
-    mPendingFrames.push_back(bigbuf);
-
     return OK;
 }
 
-#undef BAIL
-
 status_t MatroskaSource::read(
         MediaBuffer **out, const ReadOptions *options) {
     *out = NULL;
 
     int64_t seekTimeUs;
     ReadOptions::SeekMode mode;
-    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
+    if (options && options->getSeekTo(&seekTimeUs, &mode)
+            && !mExtractor->isLiveStreaming()) {
         clearPendingFrames();
         mBlockIter.seek(seekTimeUs);
     }
@@ -584,6 +491,13 @@
       mReader(new DataSourceReader(mDataSource)),
       mSegment(NULL),
       mExtractedThumbnails(false) {
+    off64_t size;
+    mIsLiveStreaming =
+        (mDataSource->flags()
+            & (DataSource::kWantsPrefetching
+                | DataSource::kIsCachingDataSource))
+        && mDataSource->getSize(&size) != OK;
+
     mkvparser::EBMLHeader ebmlHeader;
     long long pos;
     if (ebmlHeader.Parse(mReader, pos) < 0) {
@@ -598,7 +512,16 @@
         return;
     }
 
-    ret = mSegment->Load();
+    if (isLiveStreaming()) {
+        ret = mSegment->ParseHeaders();
+        CHECK_EQ(ret, 0);
+
+        long len;
+        ret = mSegment->LoadCluster(pos, len);
+        CHECK_EQ(ret, 0);
+    } else {
+        ret = mSegment->Load();
+    }
 
     if (ret < 0) {
         delete mSegment;
@@ -635,7 +558,8 @@
         return NULL;
     }
 
-    if ((flags & kIncludeExtensiveMetaData) && !mExtractedThumbnails) {
+    if ((flags & kIncludeExtensiveMetaData) && !mExtractedThumbnails
+            && !isLiveStreaming()) {
         findThumbnails();
         mExtractedThumbnails = true;
     }
@@ -643,6 +567,10 @@
     return mTracks.itemAt(index).mMeta;
 }
 
+bool MatroskaExtractor::isLiveStreaming() const {
+    return mIsLiveStreaming;
+}
+
 static void addESDSFromAudioSpecificInfo(
         const sp<MetaData> &meta, const void *asi, size_t asiSize) {
     static const uint8_t kStaticESDS[] = {
@@ -794,7 +722,7 @@
             continue;
         }
 
-        BlockIterator iter(mSegment, info->mTrackNum);
+        BlockIterator iter(this, info->mTrackNum);
         int32_t i = 0;
         int64_t thumbnailTimeUs = 0;
         size_t maxBlockSize = 0;
@@ -802,7 +730,11 @@
             if (iter.block()->IsKey()) {
                 ++i;
 
-                size_t blockSize = iter.block()->GetSize();
+                size_t blockSize = 0;
+                for (int i = 0; i < iter.block()->GetFrameCount(); ++i) {
+                    blockSize += iter.block()->GetFrame(i).len;
+                }
+
                 if (blockSize > maxBlockSize) {
                     maxBlockSize = blockSize;
                     thumbnailTimeUs = iter.blockTimeUs();
@@ -821,6 +753,15 @@
     return meta;
 }
 
+uint32_t MatroskaExtractor::flags() const {
+    uint32_t x = CAN_PAUSE;
+    if (!isLiveStreaming()) {
+        x |= CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK;
+    }
+
+    return x;
+}
+
 bool SniffMatroska(
         const sp<DataSource> &source, String8 *mimeType, float *confidence,
         sp<AMessage> *) {
diff --git a/media/libstagefright/matroska/MatroskaExtractor.h b/media/libstagefright/matroska/MatroskaExtractor.h
index fa20b84..38ebd61 100644
--- a/media/libstagefright/matroska/MatroskaExtractor.h
+++ b/media/libstagefright/matroska/MatroskaExtractor.h
@@ -20,6 +20,7 @@
 
 #include <media/stagefright/MediaExtractor.h>
 #include <utils/Vector.h>
+#include <utils/threads.h>
 
 namespace mkvparser {
 struct Segment;
@@ -45,26 +46,34 @@
 
     virtual sp<MetaData> getMetaData();
 
+    virtual uint32_t flags() const;
+
 protected:
     virtual ~MatroskaExtractor();
 
 private:
     friend struct MatroskaSource;
+    friend struct BlockIterator;
 
     struct TrackInfo {
         unsigned long mTrackNum;
         sp<MetaData> mMeta;
     };
+
+    Mutex mLock;
     Vector<TrackInfo> mTracks;
 
     sp<DataSource> mDataSource;
     DataSourceReader *mReader;
     mkvparser::Segment *mSegment;
     bool mExtractedThumbnails;
+    bool mIsLiveStreaming;
 
     void addTracks();
     void findThumbnails();
 
+    bool isLiveStreaming() const;
+
     MatroskaExtractor(const MatroskaExtractor &);
     MatroskaExtractor &operator=(const MatroskaExtractor &);
 };
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index 6cbd599..cdce772 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#define LOG_NDEBUG 0
+//#define LOG_NDEBUG 0
 #define LOG_TAG "OMXNodeInstance"
 #include <utils/Log.h>
 
diff --git a/media/libstagefright/rtsp/ARTSPConnection.cpp b/media/libstagefright/rtsp/ARTSPConnection.cpp
index 0740515..c4e0cdc 100644
--- a/media/libstagefright/rtsp/ARTSPConnection.cpp
+++ b/media/libstagefright/rtsp/ARTSPConnection.cpp
@@ -20,6 +20,8 @@
 
 #include "ARTSPConnection.h"
 
+#include <cutils/properties.h>
+
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
@@ -44,6 +46,7 @@
       mConnectionID(0),
       mNextCSeq(0),
       mReceiveResponseEventPending(false) {
+    MakeUserAgent(&mUserAgent);
 }
 
 ARTSPConnection::~ARTSPConnection() {
@@ -378,6 +381,7 @@
     reply->setString("original-request", request.c_str(), request.size());
 
     addAuthentication(&request);
+    addUserAgent(&request);
 
     // Find the boundary between headers and the body.
     ssize_t i = request.find("\r\n\r\n");
@@ -979,4 +983,27 @@
 #endif
 }
 
+// static
+void ARTSPConnection::MakeUserAgent(AString *userAgent) {
+    userAgent->clear();
+    userAgent->setTo("User-Agent: stagefright/1.1 (Linux;Android ");
+
+#if (PROPERTY_VALUE_MAX < 8)
+#error "PROPERTY_VALUE_MAX must be at least 8"
+#endif
+
+    char value[PROPERTY_VALUE_MAX];
+    property_get("ro.build.version.release", value, "Unknown");
+    userAgent->append(value);
+    userAgent->append(")\r\n");
+}
+
+void ARTSPConnection::addUserAgent(AString *request) const {
+    // Find the boundary between headers and the body.
+    ssize_t i = request->find("\r\n\r\n");
+    CHECK_GE(i, 0);
+
+    request->insert(mUserAgent, i + 2);
+}
+
 }  // namespace android
diff --git a/media/libstagefright/rtsp/ARTSPConnection.h b/media/libstagefright/rtsp/ARTSPConnection.h
index 0fecf3c6..ac2e3ae 100644
--- a/media/libstagefright/rtsp/ARTSPConnection.h
+++ b/media/libstagefright/rtsp/ARTSPConnection.h
@@ -87,6 +87,8 @@
 
     sp<AMessage> mObserveBinaryMessage;
 
+    AString mUserAgent;
+
     void onConnect(const sp<AMessage> &msg);
     void onDisconnect(const sp<AMessage> &msg);
     void onCompleteConnection(const sp<AMessage> &msg);
@@ -106,6 +108,8 @@
     bool parseAuthMethod(const sp<ARTSPResponse> &response);
     void addAuthentication(AString *request);
 
+    void addUserAgent(AString *request) const;
+
     status_t findPendingRequest(
             const sp<ARTSPResponse> &response, ssize_t *index) const;
 
@@ -114,6 +118,8 @@
     static bool ParseSingleUnsignedLong(
             const char *from, unsigned long *x);
 
+    static void MakeUserAgent(AString *userAgent);
+
     DISALLOW_EVIL_CONSTRUCTORS(ARTSPConnection);
 };
 
diff --git a/media/libstagefright/yuv/Android.mk b/media/libstagefright/yuv/Android.mk
index 7697e3c..a4253f6 100644
--- a/media/libstagefright/yuv/Android.mk
+++ b/media/libstagefright/yuv/Android.mk
@@ -10,6 +10,6 @@
 
 LOCAL_MODULE:= libstagefright_yuv
 
-LOCAL_PRELINK_MODULE := false
+
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 2b08ab5..2702242 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -1738,7 +1738,10 @@
                     LOGV("BUFFER TIMEOUT: remove(%d) from active list on thread %p", track->name(), this);
                     tracksToRemove->add(track);
                     // indicate to client process that the track was disabled because of underrun
-                    cblk->flags |= CBLK_DISABLED_ON;
+                    {
+                        AutoMutex _l(cblk->lock);
+                        cblk->flags |= CBLK_DISABLED_ON;
+                    }
                 } else if (mixerStatus != MIXER_TRACKS_READY) {
                     mixerStatus = MIXER_TRACKS_ENABLED;
                 }
@@ -1787,10 +1790,9 @@
     for (size_t i = 0; i < size; i++) {
         sp<Track> t = mTracks[i];
         if (t->type() == streamType) {
-            t->mCblk->lock.lock();
+            AutoMutex _lcblk(t->mCblk->lock);
             t->mCblk->flags |= CBLK_INVALID_ON;
             t->mCblk->cv.signal();
-            t->mCblk->lock.unlock();
         }
     }
 }
@@ -2948,6 +2950,7 @@
 
     if (mCblk->framesReady() >= mCblk->frameCount ||
             (mCblk->flags & CBLK_FORCEREADY_MSK)) {
+        AutoMutex _l(mCblk->lock);
         mFillingUpStatus = FS_FILLED;
         mCblk->flags &= ~CBLK_FORCEREADY_MSK;
         return true;
@@ -3063,19 +3066,18 @@
         // STOPPED state
         mState = STOPPED;
 
-        mCblk->lock.lock();
         // NOTE: reset() will reset cblk->user and cblk->server with
         // the risk that at the same time, the AudioMixer is trying to read
         // data. In this case, getNextBuffer() would return a NULL pointer
         // as audio buffer => the AudioMixer code MUST always test that pointer
         // returned by getNextBuffer() is not NULL!
         reset();
-        mCblk->lock.unlock();
     }
 }
 
 void AudioFlinger::PlaybackThread::Track::reset()
 {
+    AutoMutex _l(mCblk->lock);
     // Do not reset twice to avoid discarding data written just after a flush and before
     // the audioflinger thread detects the track is stopped.
     if (!mResetDone) {
@@ -3209,10 +3211,13 @@
     if (thread != 0) {
         RecordThread *recordThread = (RecordThread *)thread.get();
         recordThread->stop(this);
-        TrackBase::reset();
-        // Force overerrun condition to avoid false overrun callback until first data is
-        // read from buffer
-        mCblk->flags |= CBLK_UNDERRUN_ON;
+        {
+            AutoMutex _l(mCblk->lock);
+            TrackBase::reset();
+            // Force overerrun condition to avoid false overrun callback until first data is
+            // read from buffer
+            mCblk->flags |= CBLK_UNDERRUN_ON;
+        }
     }
 }
 
diff --git a/services/camera/libcameraservice/Android.mk b/services/camera/libcameraservice/Android.mk
index b52fc69..14f1e8b 100644
--- a/services/camera/libcameraservice/Android.mk
+++ b/services/camera/libcameraservice/Android.mk
@@ -49,7 +49,6 @@
     libcutils \
     libmedia \
     libcamera_client \
-    libsurfaceflinger_client \
     libgui
 
 LOCAL_MODULE:= libcameraservice
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index a09e16b..f3c9959 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -666,20 +666,6 @@
     mHardware->releaseRecordingFrame(mem);
 }
 
-int32_t CameraService::Client::getNumberOfVideoBuffers() const {
-    LOG1("getNumberOfVideoBuffers");
-    Mutex::Autolock lock(mLock);
-    if (checkPidAndHardware() != NO_ERROR) return 0;
-    return mHardware->getNumberOfVideoBuffers();
-}
-
-sp<IMemory> CameraService::Client::getVideoBuffer(int32_t index) const {
-    LOG1("getVideoBuffer: %d", index);
-    Mutex::Autolock lock(mLock);
-    if (checkPidAndHardware() != NO_ERROR) return 0;
-    return mHardware->getVideoBuffer(index);
-}
-
 status_t CameraService::Client::storeMetaDataInBuffers(bool enabled)
 {
     LOG1("storeMetaDataInBuffers: %s", enabled? "true": "false");
@@ -938,7 +924,7 @@
     switch (msgType) {
         case CAMERA_MSG_SHUTTER:
             // ext1 is the dimension of the yuv picture.
-            client->handleShutter((image_rect_type *)ext1);
+            client->handleShutter();
             break;
         default:
             client->handleGenericNotify(msgType, ext1, ext2);
@@ -997,9 +983,7 @@
 }
 
 // snapshot taken callback
-// "size" is the width and height of yuv picture for registerBuffer.
-// If it is NULL, use the picture size from parameters.
-void CameraService::Client::handleShutter(image_rect_type *size) {
+void CameraService::Client::handleShutter(void) {
     if (mPlayShutterSound) {
         mCameraService->playSound(SOUND_SHUTTER);
     }
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 1c43b00..28e8cc0 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -99,8 +99,6 @@
         virtual status_t        startPreview();
         virtual void            stopPreview();
         virtual bool            previewEnabled();
-        virtual int32_t         getNumberOfVideoBuffers() const;
-        virtual sp<IMemory>     getVideoBuffer(int32_t index) const;
         virtual status_t        storeMetaDataInBuffers(bool enabled);
         virtual status_t        startRecording();
         virtual void            stopRecording();
@@ -152,7 +150,7 @@
         // convert client from cookie
         static sp<Client>       getClientFromCookie(void* user);
         // handlers for messages
-        void                    handleShutter(image_rect_type *size);
+        void                    handleShutter(void);
         void                    handlePreviewData(const sp<IMemory>& mem);
         void                    handlePostview(const sp<IMemory>& mem);
         void                    handleRawPicture(const sp<IMemory>& mem);
diff --git a/services/camera/tests/CameraServiceTest/Android.mk b/services/camera/tests/CameraServiceTest/Android.mk
index cf4e42f..cf7302a 100644
--- a/services/camera/tests/CameraServiceTest/Android.mk
+++ b/services/camera/tests/CameraServiceTest/Android.mk
@@ -19,7 +19,7 @@
                 libutils \
                 libui \
                 libcamera_client \
-                libsurfaceflinger_client
+                libgui
 
 # Disable it because the ISurface interface may change, and before we have a
 # chance to fix this test, we don't want to break normal builds.