Code drop from //branches/cupcake/...@124589
diff --git a/media/libmediaplayerservice/Android.mk b/media/libmediaplayerservice/Android.mk
index b3a5747..f710921 100644
--- a/media/libmediaplayerservice/Android.mk
+++ b/media/libmediaplayerservice/Android.mk
@@ -7,7 +7,9 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:=               \
+	MediaRecorderClient.cpp \
 	MediaPlayerService.cpp \
+	MetadataRetrieverClient.cpp \
 	VorbisPlayer.cpp \
 	MidiFile.cpp
 
@@ -21,6 +23,7 @@
 	libvorbisidec \
 	libsonivox \
 	libopencoreplayer \
+	libopencoreauthor \
 	libmedia \
 	libandroid_runtime
 
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index fd5f0ed..53831717 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -34,11 +34,17 @@
 #include <utils/IServiceManager.h>
 #include <utils/MemoryHeapBase.h>
 #include <utils/MemoryBase.h>
+#include <cutils/properties.h>
 
 #include <media/MediaPlayerInterface.h>
+#include <media/mediarecorder.h>
+#include <media/MediaMetadataRetrieverInterface.h>
 #include <media/AudioTrack.h>
 
+#include "MediaRecorderClient.h"
 #include "MediaPlayerService.h"
+#include "MetadataRetrieverClient.h"
+
 #include "MidiFile.h"
 #include "VorbisPlayer.h"
 #include <media/PVPlayer.h>
@@ -72,7 +78,7 @@
     restart continuously.
 */
 #define USE_SIGBUS_HANDLER 0
- 
+
 // TODO: Temp hack until we can register players
 static const char* MIDI_FILE_EXTS[] =
 {
@@ -87,8 +93,10 @@
 
 namespace android {
 
-// TODO: should come from audio driver
-/* static */ const uint32_t MediaPlayerService::AudioOutput::kDriverLatencyInMsecs = 150;
+// TODO: Find real cause of Audio/Video delay in PV framework and remove this workaround
+/* static */ const uint32_t MediaPlayerService::AudioOutput::kAudioVideoDelayMs = 96;
+/* static */ int MediaPlayerService::AudioOutput::mMinBufferCount = 4;
+/* static */ bool MediaPlayerService::AudioOutput::mIsOnEmulator = false;
 
 static struct sigaction oldact;
 static pthread_key_t sigbuskey;
@@ -172,7 +180,7 @@
 
     pthread_key_create(&sigbuskey, NULL);
 
-  
+
 #if USE_SIGBUS_HANDLER
     struct sigaction act;
     memset(&act,0, sizeof act);
@@ -191,6 +199,20 @@
     LOGV("MediaPlayerService destroyed");
 }
 
+sp<IMediaRecorder> MediaPlayerService::createMediaRecorder(pid_t pid)
+{
+    sp<MediaRecorderClient> recorder = new MediaRecorderClient(pid);
+    LOGV("Create new media recorder client from pid %d", pid);
+    return recorder;
+}
+
+sp<IMediaMetadataRetriever> MediaPlayerService::createMetadataRetriever(pid_t pid)
+{
+    sp<MetadataRetrieverClient> retriever = new MetadataRetrieverClient(pid);
+    LOGV("Create new media retriever from pid %d", pid);
+    return retriever;
+}
+
 sp<IMediaPlayer> MediaPlayerService::create(pid_t pid, const sp<IMediaPlayerClient>& client, const char* url)
 {
     int32_t connId = android_atomic_inc(&mNextConnId);
@@ -237,8 +259,8 @@
                 mHeap->getBase(), mHeap->getSize(), mHeap->getFlags(), mHeap->getDevice());
         result.append(buffer);
     }
-    snprintf(buffer, 255, "  msec per frame(%f), channel count(%ld), frame count(%ld)\n",
-            mMsecsPerFrame, mChannelCount, mFrameCount);
+    snprintf(buffer, 255, "  msec per frame(%f), channel count(%d), format(%d), frame count(%ld)\n",
+            mMsecsPerFrame, mChannelCount, mFormat, mFrameCount);
     result.append(buffer);
     snprintf(buffer, 255, "  sample rate(%d), size(%d), error(%d), command complete(%s)\n",
             mSampleRate, mSize, mError, mCommandComplete?"true":"false");
@@ -257,8 +279,8 @@
     snprintf(buffer, 255, "  stream type(%d), left - right volume(%f, %f)\n",
             mStreamType, mLeftVolume, mRightVolume);
     result.append(buffer);
-    snprintf(buffer, 255, "  msec per frame(%f), latency (%d), driver latency(%d)\n",
-            mMsecsPerFrame, mLatency, kDriverLatencyInMsecs);
+    snprintf(buffer, 255, "  msec per frame(%f), latency (%d)\n",
+            mMsecsPerFrame, mLatency);
     result.append(buffer);
     ::write(fd, result.string(), result.size());
     if (mTrack != 0) {
@@ -315,7 +337,7 @@
         if (f) {
             while (!feof(f)) {
                 fgets(buffer, SIZE, f);
-                if (strstr(buffer, " /sdcard/") || 
+                if (strstr(buffer, " /sdcard/") ||
                     strstr(buffer, " /system/sounds/") ||
                     strstr(buffer, " /system/media/")) {
                     result.append("  ");
@@ -334,7 +356,7 @@
         if (d) {
             struct dirent *ent;
             while((ent = readdir(d)) != NULL) {
-                if (strcmp(ent->d_name,".") && strcmp(ent->d_name,"..")) { 
+                if (strcmp(ent->d_name,".") && strcmp(ent->d_name,"..")) {
                     snprintf(buffer, SIZE, "/proc/%d/fd/%s", myTid(), ent->d_name);
                     struct stat s;
                     if (lstat(buffer, &s) == 0) {
@@ -350,7 +372,7 @@
                                 } else {
                                     linkto[len] = 0;
                                 }
-                                if (strstr(linkto, "/sdcard/") == linkto || 
+                                if (strstr(linkto, "/sdcard/") == linkto ||
                                     strstr(linkto, "/system/sounds/") == linkto ||
                                     strstr(linkto, "/system/media/") == linkto) {
                                     result.append("  ");
@@ -683,20 +705,6 @@
     return NO_ERROR;
 }
 
-status_t MediaPlayerService::Client::getVideoSize(int *w, int *h)
-{
-    sp<MediaPlayerBase> p = getPlayer();
-    if (p == 0) return UNKNOWN_ERROR;
-    status_t ret = p->getVideoWidth(w);
-    if (ret == NO_ERROR) ret = p->getVideoHeight(h);
-    if (ret == NO_ERROR) {
-        LOGV("[%d] getVideoWidth = (%d, %d)", mConnId, *w, *h);
-    } else {
-        LOGE("getVideoSize returned %d", ret);
-    }
-    return ret;
-}
-
 status_t MediaPlayerService::Client::getCurrentPosition(int *msec)
 {
     LOGV("getCurrentPosition");
@@ -812,7 +820,7 @@
 
 static size_t kDefaultHeapSize = 1024 * 1024; // 1MB
 
-sp<IMemory> MediaPlayerService::decode(const char* url, uint32_t *pSampleRate, int* pNumChannels)
+sp<IMemory> MediaPlayerService::decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat)
 {
     LOGV("decode(%s)", url);
     sp<MemoryBase> mem;
@@ -856,14 +864,15 @@
     mem = new MemoryBase(cache->getHeap(), 0, cache->size());
     *pSampleRate = cache->sampleRate();
     *pNumChannels = cache->channelCount();
-    LOGV("return memory @ %p, sampleRate=%u, channelCount = %d", mem->pointer(), *pSampleRate, *pNumChannels);
+    *pFormat = cache->format();
+    LOGV("return memory @ %p, sampleRate=%u, channelCount = %d, format = %d", mem->pointer(), *pSampleRate, *pNumChannels, *pFormat);
 
 Exit:
     if (player != 0) player->reset();
     return mem;
 }
 
-sp<IMemory> MediaPlayerService::decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels)
+sp<IMemory> MediaPlayerService::decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat)
 {
     LOGV("decode(%d, %lld, %lld)", fd, offset, length);
     sp<MemoryBase> mem;
@@ -898,7 +907,8 @@
     mem = new MemoryBase(cache->getHeap(), 0, cache->size());
     *pSampleRate = cache->sampleRate();
     *pNumChannels = cache->channelCount();
-    LOGV("return memory @ %p, sampleRate=%u, channelCount = %d", mem->pointer(), *pSampleRate, *pNumChannels);
+    *pFormat = cache->format();
+    LOGV("return memory @ %p, sampleRate=%u, channelCount = %d, format = %d", mem->pointer(), *pSampleRate, *pNumChannels, *pFormat);
 
 Exit:
     if (player != 0) player->reset();
@@ -916,6 +926,7 @@
     mRightVolume = 1.0;
     mLatency = 0;
     mMsecsPerFrame = 0;
+    setMinBufferCount();
 }
 
 MediaPlayerService::AudioOutput::~AudioOutput()
@@ -923,10 +934,31 @@
     close();
 }
 
+void MediaPlayerService::AudioOutput::setMinBufferCount()
+{
+    char value[PROPERTY_VALUE_MAX];
+    if (property_get("ro.kernel.qemu", value, 0)) {
+        mIsOnEmulator = true;
+        mMinBufferCount = 12;  // to prevent systematic buffer underrun for emulator
+    }
+}
+
+bool MediaPlayerService::AudioOutput::isOnEmulator()
+{
+    setMinBufferCount();
+    return mIsOnEmulator;
+}
+
+int MediaPlayerService::AudioOutput::getMinBufferCount()
+{
+    setMinBufferCount();
+    return mMinBufferCount;
+}
+
 ssize_t MediaPlayerService::AudioOutput::bufferSize() const
 {
     if (mTrack == 0) return NO_INIT;
-    return mTrack->frameCount() * mTrack->channelCount() * sizeof(int16_t);
+    return mTrack->frameCount() * frameSize();
 }
 
 ssize_t MediaPlayerService::AudioOutput::frameCount() const
@@ -944,7 +976,7 @@
 ssize_t MediaPlayerService::AudioOutput::frameSize() const
 {
     if (mTrack == 0) return NO_INIT;
-    return mTrack->channelCount() * sizeof(int16_t);
+    return mTrack->frameSize();
 }
 
 uint32_t MediaPlayerService::AudioOutput::latency () const
@@ -957,12 +989,29 @@
     return mMsecsPerFrame;
 }
 
-status_t MediaPlayerService::AudioOutput::open(uint32_t sampleRate, int channelCount, int bufferCount)
+status_t MediaPlayerService::AudioOutput::open(uint32_t sampleRate, int channelCount, int format, int bufferCount)
 {
-    LOGV("open(%u, %d, %d)", sampleRate, channelCount, bufferCount);
-    if (mTrack) close();
+    // Check argument "bufferCount" against the mininum buffer count
+    if (bufferCount < mMinBufferCount) {
+        LOGD("bufferCount (%d) is too small and increased to %d", bufferCount, mMinBufferCount);
+        bufferCount = mMinBufferCount;
 
-    AudioTrack *t = new AudioTrack(mStreamType, sampleRate, AudioSystem::PCM_16_BIT, channelCount, bufferCount);
+    }
+    LOGV("open(%u, %d, %d, %d)", sampleRate, channelCount, format, bufferCount);
+    if (mTrack) close();
+    int afSampleRate;
+    int afFrameCount;
+    int frameCount;
+
+    if (AudioSystem::getOutputFrameCount(&afFrameCount) != NO_ERROR) {
+        return NO_INIT;
+    }
+    if (AudioSystem::getOutputSamplingRate(&afSampleRate) != NO_ERROR) {
+        return NO_INIT;
+    }
+
+    frameCount = (sampleRate*afFrameCount)/afSampleRate;
+    AudioTrack *t = new AudioTrack(mStreamType, sampleRate, format, channelCount, frameCount*bufferCount);
     if ((t == 0) || (t->initCheck() != NO_ERROR)) {
         LOGE("Unable to create audio track");
         delete t;
@@ -972,7 +1021,7 @@
     LOGV("setVolume");
     t->setVolume(mLeftVolume, mRightVolume);
     mMsecsPerFrame = 1.e3 / (float) sampleRate;
-    mLatency = (mMsecsPerFrame * bufferCount * t->frameCount()) + kDriverLatencyInMsecs;
+    mLatency = t->latency() + kAudioVideoDelayMs;
     mTrack = t;
     return NO_ERROR;
 }
@@ -1031,7 +1080,7 @@
 #undef LOG_TAG
 #define LOG_TAG "AudioCache"
 MediaPlayerService::AudioCache::AudioCache(const char* name) :
-    mChannelCount(0), mFrameCount(0), mSampleRate(0), mSize(0),
+    mChannelCount(0), mFrameCount(1024), mSampleRate(0), mSize(0),
     mError(NO_ERROR), mCommandComplete(false)
 {
     // create ashmem heap
@@ -1048,12 +1097,13 @@
     return mMsecsPerFrame;
 }
 
-status_t MediaPlayerService::AudioCache::open(uint32_t sampleRate, int channelCount, int bufferCount)
+status_t MediaPlayerService::AudioCache::open(uint32_t sampleRate, int channelCount, int format, int bufferCount)
 {
-    LOGV("open(%u, %d, %d)", sampleRate, channelCount, bufferCount);
-   if (mHeap->getHeapID() < 0) return NO_INIT;
-   mSampleRate = sampleRate;
-   mChannelCount = channelCount;
+    LOGV("open(%u, %d, %d, %d)", sampleRate, channelCount, format, bufferCount);
+    if (mHeap->getHeapID() < 0) return NO_INIT;
+    mSampleRate = sampleRate;
+    mChannelCount = (uint16_t)channelCount;
+    mFormat = (uint16_t)format;
     mMsecsPerFrame = 1.e3 / (float) sampleRate;
     return NO_ERROR;
 }
@@ -1067,6 +1117,10 @@
     if (p == NULL) return NO_INIT;
     p += mSize;
     LOGV("memcpy(%p, %p, %u)", p, buffer, size);
+    if (mSize + size > mHeap->getSize()) {
+        LOGE("Heap size overflow! req size: %d, max size: %d", (mSize + size), mHeap->getSize());
+        size = mHeap->getSize() - mSize;
+    }
     memcpy(p, buffer, size);
     mSize += size;
     return size;
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index c2007cb..f138886 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -25,10 +25,11 @@
 #include <media/IMediaPlayerService.h>
 #include <media/MediaPlayerInterface.h>
 
-class SkBitmap;
-
 namespace android {
 
+class IMediaRecorder;
+class IMediaMetadataRetriever;
+
 #define CALLBACK_ANTAGONIZER 0
 #if CALLBACK_ANTAGONIZER
 class Antagonizer {
@@ -68,7 +69,7 @@
         virtual ssize_t         frameSize() const;
         virtual uint32_t        latency() const;
         virtual float           msecsPerFrame() const;
-        virtual status_t        open(uint32_t sampleRate, int channelCount, int bufferCount=4);
+        virtual status_t        open(uint32_t sampleRate, int channelCount, int format, int bufferCount=4);
         virtual void            start();
         virtual ssize_t         write(const void* buffer, size_t size);
         virtual void            stop();
@@ -78,14 +79,24 @@
                 void            setAudioStreamType(int streamType) { mStreamType = streamType; }
                 void            setVolume(float left, float right);
         virtual status_t        dump(int fd, const Vector<String16>& args) const;
+
+        static bool             isOnEmulator();
+        static int              getMinBufferCount();
     private:
+        static void             setMinBufferCount();
+
         AudioTrack*             mTrack;
         int                     mStreamType;
         float                   mLeftVolume;
         float                   mRightVolume;
         float                   mMsecsPerFrame;
         uint32_t                mLatency;
-        static const uint32_t   kDriverLatencyInMsecs;
+
+        // TODO: Find real cause of Audio/Video delay in PV framework and remove this workaround
+        static const uint32_t   kAudioVideoDelayMs;
+        static bool             mIsOnEmulator;
+        static int              mMinBufferCount;  // 12 for emulator; otherwise 4
+
     };
 
     class AudioCache : public MediaPlayerBase::AudioSink
@@ -96,13 +107,13 @@
 
         virtual bool            ready() const { return (mChannelCount > 0) && (mHeap->getHeapID() > 0); }
         virtual bool            realtime() const { return false; }
-        virtual ssize_t         bufferSize() const { return 4096; }
+        virtual ssize_t         bufferSize() const { return frameSize() * mFrameCount; }
         virtual ssize_t         frameCount() const { return mFrameCount; }
-        virtual ssize_t         channelCount() const { return mChannelCount; }
-        virtual ssize_t         frameSize() const { return ssize_t(mChannelCount * sizeof(int16_t)); }
+        virtual ssize_t         channelCount() const { return (ssize_t)mChannelCount; }
+        virtual ssize_t         frameSize() const { return ssize_t(mChannelCount * ((mFormat == AudioSystem::PCM_16_BIT)?sizeof(int16_t):sizeof(u_int8_t))); }
         virtual uint32_t        latency() const;
         virtual float           msecsPerFrame() const;
-        virtual status_t        open(uint32_t sampleRate, int channelCount, int bufferCount=1);
+        virtual status_t        open(uint32_t sampleRate, int channelCount, int format, int bufferCount=1);
         virtual void            start() {}
         virtual ssize_t         write(const void* buffer, size_t size);
         virtual void            stop() {}
@@ -112,6 +123,7 @@
                 void            setAudioStreamType(int streamType) {}
                 void            setVolume(float left, float right) {}
                 uint32_t        sampleRate() const { return mSampleRate; }
+                uint32_t        format() const { return (uint32_t)mFormat; }
                 size_t          size() const { return mSize; }
                 status_t        wait();
 
@@ -127,7 +139,8 @@
         Condition           mSignal;
         sp<MemoryHeapBase>  mHeap;
         float               mMsecsPerFrame;
-        ssize_t             mChannelCount;
+        uint16_t            mChannelCount;
+        uint16_t			mFormat;
         ssize_t             mFrameCount;
         uint32_t            mSampleRate;
         uint32_t            mSize;
@@ -139,10 +152,14 @@
     static  void                instantiate();
 
     // IMediaPlayerService interface
+    virtual sp<IMediaRecorder>  createMediaRecorder(pid_t pid);
+    virtual sp<IMediaMetadataRetriever> createMetadataRetriever(pid_t pid);
+
+    // House keeping for media player clients
     virtual sp<IMediaPlayer>    create(pid_t pid, const sp<IMediaPlayerClient>& client, const char* url);
     virtual sp<IMediaPlayer>    create(pid_t pid, const sp<IMediaPlayerClient>& client, int fd, int64_t offset, int64_t length);
-    virtual sp<IMemory>         decode(const char* url, uint32_t *pSampleRate, int* pNumChannels);
-    virtual sp<IMemory>         decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels);
+    virtual sp<IMemory>         decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat);
+    virtual sp<IMemory>         decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat);
 
     virtual status_t            dump(int fd, const Vector<String16>& args);
 
@@ -160,7 +177,6 @@
         virtual status_t        stop();
         virtual status_t        pause();
         virtual status_t        isPlaying(bool* state);
-        virtual status_t        getVideoSize(int* w, int* h);
         virtual status_t        seekTo(int msec);
         virtual status_t        getCurrentPosition(int* msec);
         virtual status_t        getDuration(int* msec);
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
new file mode 100644
index 0000000..f326a0e
--- /dev/null
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -0,0 +1,251 @@
+/*
+ ** Copyright 2008, HTC 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "MediaRecorderService"
+#include <utils/Log.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <string.h>
+#include <cutils/atomic.h>
+#include <android_runtime/ActivityManager.h>
+#include <utils/IPCThreadState.h>
+#include <utils/IServiceManager.h>
+#include <utils/MemoryHeapBase.h>
+#include <utils/MemoryBase.h>
+#include <media/PVMediaRecorder.h>
+
+#include "MediaRecorderClient.h"
+
+namespace android {
+
+status_t MediaRecorderClient::setCamera(const sp<ICamera>& camera)
+{
+    LOGV("setCamera");
+    Mutex::Autolock lock(mLock);
+    if (mRecorder == NULL) {
+        LOGE("recorder is not initialized");
+        return NO_INIT;
+    }
+    return mRecorder->setCamera(camera);
+}
+
+status_t MediaRecorderClient::setPreviewSurface(const sp<ISurface>& surface)
+{
+    LOGV("setPreviewSurface");
+    Mutex::Autolock lock(mLock);
+    if (mRecorder == NULL) {
+        LOGE("recorder is not initialized");
+        return NO_INIT;
+    }
+    return mRecorder->setPreviewSurface(surface);
+}
+
+status_t MediaRecorderClient::setVideoSource(int vs)
+{
+    LOGV("setVideoSource(%d)", vs);
+    Mutex::Autolock lock(mLock);
+    if (mRecorder == NULL)	{
+        LOGE("recorder is not initialized");
+    }
+    return mRecorder->setVideoSource((video_source)vs);
+}
+
+status_t MediaRecorderClient::setAudioSource(int as)
+{
+    LOGV("setAudioSource(%d)", as);
+    Mutex::Autolock lock(mLock);
+    if (mRecorder == NULL)  {
+        LOGE("recorder is not initialized");
+    }
+    return mRecorder->setAudioSource((audio_source)as);
+}
+
+status_t MediaRecorderClient::setOutputFormat(int of)
+{
+    LOGV("setOutputFormat(%d)", of);
+    Mutex::Autolock lock(mLock);
+    if (mRecorder == NULL) {
+        LOGE("recorder is not initialized");
+        return NO_INIT;
+    }
+    return mRecorder->setOutputFormat((output_format)of);
+}
+
+status_t MediaRecorderClient::setVideoEncoder(int ve)
+{
+    LOGV("setVideoEncoder(%d)", ve);
+    Mutex::Autolock lock(mLock);
+    if (mRecorder == NULL) {
+        LOGE("recorder is not initialized");
+        return NO_INIT;
+    }
+    return mRecorder->setVideoEncoder((video_encoder)ve);
+}
+
+status_t MediaRecorderClient::setAudioEncoder(int ae)
+{
+    LOGV("setAudioEncoder(%d)", ae);
+    Mutex::Autolock lock(mLock);
+    if (mRecorder == NULL) {
+        LOGE("recorder is not initialized");
+        return NO_INIT;
+    }
+    return mRecorder->setAudioEncoder((audio_encoder)ae);
+}
+
+status_t MediaRecorderClient::setOutputFile(const char* path)
+{
+    LOGV("setOutputFile(%s)", path);
+    Mutex::Autolock lock(mLock);
+    if (mRecorder == NULL) {
+        LOGE("recorder is not initialized");
+        return NO_INIT;
+    }
+    return mRecorder->setOutputFile(path);
+}
+
+status_t MediaRecorderClient::setVideoSize(int width, int height)
+{
+    LOGV("setVideoSize(%dx%d)", width, height);
+    Mutex::Autolock lock(mLock);
+    if (mRecorder == NULL) {
+        LOGE("recorder is not initialized");
+        return NO_INIT;
+    }
+    return mRecorder->setVideoSize(width, height);
+}
+
+status_t MediaRecorderClient::setVideoFrameRate(int frames_per_second)
+{
+    LOGV("setVideoFrameRate(%d)", frames_per_second);
+    Mutex::Autolock lock(mLock);
+    if (mRecorder == NULL) {
+        LOGE("recorder is not initialized");
+        return NO_INIT;
+    }
+    return mRecorder->setVideoFrameRate(frames_per_second);
+}
+
+status_t MediaRecorderClient::prepare()
+{
+    LOGV("prepare");
+    Mutex::Autolock lock(mLock);
+    if (mRecorder == NULL) {
+        LOGE("recorder is not initialized");
+        return NO_INIT;
+    }
+    return mRecorder->prepare();
+}
+
+
+status_t MediaRecorderClient::getMaxAmplitude(int* max)
+{
+    LOGV("getMaxAmplitude");
+    Mutex::Autolock lock(mLock);
+    if (mRecorder == NULL) {
+        LOGE("recorder is not initialized");
+        return NO_INIT;
+    }
+    return mRecorder->getMaxAmplitude(max);
+}
+
+status_t MediaRecorderClient::start()
+{
+    LOGV("start");
+    Mutex::Autolock lock(mLock);
+    if (mRecorder == NULL) {
+        LOGE("recorder is not initialized");
+        return NO_INIT;
+    }
+    return mRecorder->start();
+
+}
+
+status_t MediaRecorderClient::stop()
+{
+    LOGV("stop");
+    Mutex::Autolock lock(mLock);
+    if (mRecorder == NULL) {
+        LOGE("recorder is not initialized");
+        return NO_INIT;
+    }
+    return mRecorder->stop();
+}
+
+status_t MediaRecorderClient::init()
+{
+    LOGV("init");
+    Mutex::Autolock lock(mLock);
+    if (mRecorder == NULL) {
+        LOGE("recorder is not initialized");
+        return NO_INIT;
+    }
+    return mRecorder->init();
+}
+
+status_t MediaRecorderClient::close()
+{
+    LOGV("close");
+    Mutex::Autolock lock(mLock);
+    if (mRecorder == NULL) {
+        LOGE("recorder is not initialized");
+        return NO_INIT;
+    }
+    return mRecorder->close();
+}
+
+
+status_t MediaRecorderClient::reset()
+{
+    LOGV("reset");
+    Mutex::Autolock lock(mLock);
+    if (mRecorder == NULL) {
+        LOGE("recorder is not initialized");
+        return NO_INIT;
+    }
+    return mRecorder->reset();
+}
+
+status_t MediaRecorderClient::release()
+{
+    LOGV("release");
+    Mutex::Autolock lock(mLock);
+    if (mRecorder != NULL) {
+        delete mRecorder;
+        mRecorder = NULL;
+    }
+    return NO_ERROR;
+}
+
+MediaRecorderClient::MediaRecorderClient(pid_t pid)
+{
+    LOGV("Client constructor");
+    mPid = pid;
+    mRecorder = new PVMediaRecorder();
+}
+
+MediaRecorderClient::~MediaRecorderClient()
+{
+    LOGV("Client destructor");
+    release();
+}
+
+}; // namespace android
+
diff --git a/media/libmediaplayerservice/MediaRecorderClient.h b/media/libmediaplayerservice/MediaRecorderClient.h
new file mode 100644
index 0000000..3158017
--- /dev/null
+++ b/media/libmediaplayerservice/MediaRecorderClient.h
@@ -0,0 +1,64 @@
+/*
+ **
+ ** Copyright 2008, HTC 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.
+ */
+
+#ifndef ANDROID_MEDIARECORDERCLIENT_H
+#define ANDROID_MEDIARECORDERCLIENT_H
+
+#include <media/IMediaRecorder.h>
+
+namespace android {
+
+class PVMediaRecorder;
+class ISurface;
+
+class MediaRecorderClient : public BnMediaRecorder
+{
+public:
+    virtual	    status_t		setCamera(const sp<ICamera>& camera);
+    virtual     status_t        setPreviewSurface(const sp<ISurface>& surface);
+    virtual     status_t        setVideoSource(int vs);
+    virtual     status_t        setAudioSource(int as);
+    virtual     status_t        setOutputFormat(int of);
+    virtual     status_t        setVideoEncoder(int ve);
+    virtual     status_t        setAudioEncoder(int ae);
+    virtual     status_t        setOutputFile(const char* path);
+    virtual     status_t        setVideoSize(int width, int height);
+    virtual     status_t        setVideoFrameRate(int frames_per_second);
+    virtual     status_t        prepare();
+    virtual     status_t        getMaxAmplitude(int* max);
+    virtual     status_t        start();
+    virtual     status_t        stop();
+    virtual	    status_t        reset();
+    virtual     status_t        init();
+    virtual     status_t        close();
+    virtual     status_t        release();
+
+private:
+    friend class                 MediaPlayerService;  // for accessing private constructor
+
+                                 MediaRecorderClient(pid_t pid);
+    virtual 		         ~MediaRecorderClient();
+
+    pid_t			 mPid;
+    Mutex			 mLock;
+    PVMediaRecorder              *mRecorder;
+};
+
+}; // namespace android
+
+#endif // ANDROID_MEDIARECORDERCLIENT_H
+
diff --git a/media/libmediaplayerservice/MetadataRetrieverClient.cpp b/media/libmediaplayerservice/MetadataRetrieverClient.cpp
new file mode 100644
index 0000000..a320bd5
--- /dev/null
+++ b/media/libmediaplayerservice/MetadataRetrieverClient.cpp
@@ -0,0 +1,250 @@
+/*
+**
+** Copyright (C) 2008 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 "MetadataRetrieverClient"
+#include <utils/Log.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <unistd.h>
+
+#include <string.h>
+#include <cutils/atomic.h>
+#include <utils/MemoryDealer.h>
+#include <android_runtime/ActivityManager.h>
+#include <utils/IPCThreadState.h>
+#include <utils/IServiceManager.h>
+#include <media/MediaMetadataRetrieverInterface.h>
+#include <media/MediaPlayerInterface.h>
+#include <media/PVMetadataRetriever.h>
+#include <private/media/VideoFrame.h>
+
+#include "MetadataRetrieverClient.h"
+
+
+namespace android {
+
+MetadataRetrieverClient::MetadataRetrieverClient(pid_t pid)
+{
+    LOGV("MetadataRetrieverClient constructor pid(%d)", pid);
+    mPid = pid;
+    mThumbnailDealer = NULL;
+    mAlbumArtDealer = NULL;
+    mThumbnail = NULL;
+    mAlbumArt = NULL;
+
+    mRetriever = new PVMetadataRetriever();
+    if (mRetriever == NULL) {
+        LOGE("failed to initialize the retriever");
+    }
+}
+
+MetadataRetrieverClient::~MetadataRetrieverClient()
+{
+    LOGV("MetadataRetrieverClient destructor");
+    disconnect();
+}
+
+status_t MetadataRetrieverClient::dump(int fd, const Vector<String16>& args) const
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+    result.append(" MetadataRetrieverClient\n");
+    snprintf(buffer, 255, "  pid(%d)\n", mPid);
+    result.append(buffer);
+    write(fd, result.string(), result.size());
+    write(fd, "\n", 1);
+    return NO_ERROR;
+}
+
+void MetadataRetrieverClient::disconnect()
+{
+    LOGV("disconnect from pid %d", mPid);
+    Mutex::Autolock lock(mLock);
+    mRetriever.clear();
+    mThumbnailDealer.clear();
+    mAlbumArtDealer.clear();
+    mThumbnail.clear();
+    mAlbumArt.clear();
+    IPCThreadState::self()->flushCommands();
+}
+
+status_t MetadataRetrieverClient::setDataSource(const char *url)
+{
+    LOGV("setDataSource(%s)", url);
+    Mutex::Autolock lock(mLock);
+    if (url == NULL) {
+        return UNKNOWN_ERROR;
+    }
+    if (mRetriever == NULL) {
+        LOGE("retriever is not initialized");
+        return NO_INIT;
+    }
+    return mRetriever->setDataSource(url);
+}
+
+status_t MetadataRetrieverClient::setDataSource(int fd, int64_t offset, int64_t length)
+{
+    LOGV("setDataSource fd=%d, offset=%lld, length=%lld", fd, offset, length);
+    Mutex::Autolock lock(mLock);
+    if (mRetriever == NULL) {
+        LOGE("retriever is not initialized");
+        ::close(fd);
+        return NO_INIT;
+    }
+
+    struct stat sb;
+    int ret = fstat(fd, &sb);
+    if (ret != 0) {
+        LOGE("fstat(%d) failed: %d, %s", fd, ret, strerror(errno));
+        return UNKNOWN_ERROR;
+    }
+    LOGV("st_dev  = %llu", sb.st_dev);
+    LOGV("st_mode = %u", sb.st_mode);
+    LOGV("st_uid  = %lu", sb.st_uid);
+    LOGV("st_gid  = %lu", sb.st_gid);
+    LOGV("st_size = %llu", sb.st_size);
+
+    if (offset >= sb.st_size) {
+        LOGE("offset (%lld) bigger than file size (%llu)", offset, sb.st_size);
+        ::close(fd);
+        return UNKNOWN_ERROR;
+    }
+    if (offset + length > sb.st_size) {
+        length = sb.st_size - offset;
+        LOGE("calculated length = %lld", length);
+    }
+    status_t status = mRetriever->setDataSource(fd, offset, length);
+    ::close(fd);
+    return status;
+}
+
+status_t MetadataRetrieverClient::setMode(int mode)
+{
+    LOGV("setMode");
+    Mutex::Autolock lock(mLock);
+    if (mRetriever == NULL) {
+        LOGE("retriever is not initialized");
+        return NO_INIT;
+    }
+    return mRetriever->setMode(mode);
+}
+
+status_t MetadataRetrieverClient::getMode(int* mode) const
+{
+    LOGV("getMode");
+    Mutex::Autolock lock(mLock);
+    if (mRetriever == NULL) {
+        LOGE("retriever is not initialized");
+        return NO_INIT;
+    }
+    return mRetriever->getMode(mode);
+}
+
+sp<IMemory> MetadataRetrieverClient::captureFrame()
+{
+    LOGV("captureFrame");
+    Mutex::Autolock lock(mLock);
+    mThumbnail.clear();
+    mThumbnailDealer.clear();
+    if (mRetriever == NULL) {
+        LOGE("retriever is not initialized");
+        return NULL;
+    }
+    VideoFrame *frame = mRetriever->captureFrame();
+    if (frame == NULL) {
+        LOGE("failed to capture a video frame");
+        return NULL;
+    }
+    size_t size = sizeof(VideoFrame) + frame->mSize;
+    mThumbnailDealer = new MemoryDealer(size);
+    if (mThumbnailDealer == NULL) {
+        LOGE("failed to create MemoryDealer");
+        delete frame;
+        return NULL;
+    }
+    mThumbnail = mThumbnailDealer->allocate(size);
+    if (mThumbnail == NULL) {
+        LOGE("not enough memory for VideoFrame size=%u", size);
+        mThumbnailDealer.clear();
+        delete frame;
+        return NULL;
+    }
+    VideoFrame *frameCopy = static_cast<VideoFrame *>(mThumbnail->pointer());
+    frameCopy->mWidth = frame->mWidth;
+    frameCopy->mHeight = frame->mHeight;
+    frameCopy->mDisplayWidth = frame->mDisplayWidth;
+    frameCopy->mDisplayHeight = frame->mDisplayHeight;
+    frameCopy->mSize = frame->mSize;
+    frameCopy->mData = (uint8_t *)frameCopy + sizeof(VideoFrame);
+    memcpy(frameCopy->mData, frame->mData, frame->mSize);
+    delete frame;  // Fix memory leakage
+    return mThumbnail;
+}
+
+sp<IMemory> MetadataRetrieverClient::extractAlbumArt()
+{
+    LOGV("extractAlbumArt");
+    Mutex::Autolock lock(mLock);
+    mAlbumArt.clear();
+    mAlbumArtDealer.clear();
+    if (mRetriever == NULL) {
+        LOGE("retriever is not initialized");
+        return NULL;
+    }
+    MediaAlbumArt *albumArt = mRetriever->extractAlbumArt();
+    if (albumArt == NULL) {
+        LOGE("failed to extract an album art");
+        return NULL;
+    }
+    size_t size = sizeof(MediaAlbumArt) + albumArt->mSize;
+    mAlbumArtDealer = new MemoryDealer(size);
+    if (mAlbumArtDealer == NULL) {
+        LOGE("failed to create MemoryDealer object");
+        delete albumArt;
+        return NULL;
+    }
+    mAlbumArt = mAlbumArtDealer->allocate(size);
+    if (mAlbumArt == NULL) {
+        LOGE("not enough memory for MediaAlbumArt size=%u", size);
+        mAlbumArtDealer.clear();
+        delete albumArt;
+        return NULL;
+    }
+    MediaAlbumArt *albumArtCopy = static_cast<MediaAlbumArt *>(mAlbumArt->pointer());
+    albumArtCopy->mSize = albumArt->mSize;
+    albumArtCopy->mData = (uint8_t *)albumArtCopy + sizeof(MediaAlbumArt);
+    memcpy(albumArtCopy->mData, albumArt->mData, albumArt->mSize);
+    delete albumArt;  // Fix memory leakage
+    return mAlbumArt;
+}
+
+const char* MetadataRetrieverClient::extractMetadata(int keyCode)
+{
+    LOGV("extractMetadata");
+    Mutex::Autolock lock(mLock);
+    if (mRetriever == NULL) {
+        LOGE("retriever is not initialized");
+        return NULL;
+    }
+    return mRetriever->extractMetadata(keyCode);
+}
+
+}; // namespace android
diff --git a/media/libmediaplayerservice/MetadataRetrieverClient.h b/media/libmediaplayerservice/MetadataRetrieverClient.h
new file mode 100644
index 0000000..ce29c98
--- /dev/null
+++ b/media/libmediaplayerservice/MetadataRetrieverClient.h
@@ -0,0 +1,71 @@
+/*
+**
+** Copyright (C) 2008 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 ANDROID_MEDIAMETADATARETRIEVERSERVICE_H
+#define ANDROID_MEDIAMETADATARETRIEVERSERVICE_H
+
+#include <utils.h>
+#include <utils/KeyedVector.h>
+#include <utils/IMemory.h>
+
+#include <media/MediaMetadataRetrieverInterface.h>
+
+
+namespace android {
+
+class IMediaPlayerService;
+class MemoryDealer;
+
+class MetadataRetrieverClient : public BnMediaMetadataRetriever
+{
+public:
+    MetadataRetrieverClient(const sp<IMediaPlayerService>& service, pid_t pid, int32_t connId);
+
+    // Implements IMediaMetadataRetriever interface
+    // These methods are called in IMediaMetadataRetriever.cpp?
+    virtual void                    disconnect();
+    virtual status_t                setDataSource(const char *url);
+    virtual status_t                setDataSource(int fd, int64_t offset, int64_t length);
+    virtual status_t                setMode(int mode);
+    virtual status_t                getMode(int* mode) const;
+    virtual sp<IMemory>             captureFrame();
+    virtual sp<IMemory>             extractAlbumArt();
+    virtual const char*             extractMetadata(int keyCode);
+
+    virtual status_t                dump(int fd, const Vector<String16>& args) const;
+
+private:
+    friend class MediaPlayerService;
+
+    explicit MetadataRetrieverClient(pid_t pid);
+    virtual ~MetadataRetrieverClient();
+
+    mutable Mutex                          mLock;
+    sp<MediaMetadataRetrieverBase>         mRetriever;
+    pid_t                                  mPid;
+
+    // Keep the shared memory copy of album art and capture frame (for thumbnail)
+    sp<MemoryDealer>                       mAlbumArtDealer;
+    sp<MemoryDealer>                       mThumbnailDealer;
+    sp<IMemory>                            mAlbumArt;
+    sp<IMemory>                            mThumbnail;
+};
+
+}; // namespace android
+
+#endif // ANDROID_MEDIAMETADATARETRIEVERSERVICE_H
+
diff --git a/media/libmediaplayerservice/MidiFile.cpp b/media/libmediaplayerservice/MidiFile.cpp
index 538f7d4..cfad66c 100644
--- a/media/libmediaplayerservice/MidiFile.cpp
+++ b/media/libmediaplayerservice/MidiFile.cpp
@@ -431,7 +431,7 @@
 }
 
 status_t MidiFile::createOutputTrack() {
-    if (mAudioSink->open(pLibConfig->sampleRate,pLibConfig->numChannels, 2) != NO_ERROR) {
+    if (mAudioSink->open(pLibConfig->sampleRate, pLibConfig->numChannels, AudioSystem::PCM_16_BIT, 2) != NO_ERROR) {
         LOGE("mAudioSink open failed");
         return ERROR_OPEN_FAILED;
     }
diff --git a/media/libmediaplayerservice/VorbisPlayer.cpp b/media/libmediaplayerservice/VorbisPlayer.cpp
index a0e0f39..9a64403 100644
--- a/media/libmediaplayerservice/VorbisPlayer.cpp
+++ b/media/libmediaplayerservice/VorbisPlayer.cpp
@@ -385,7 +385,7 @@
 
     LOGV("Create AudioTrack object: rate=%ld, channels=%d\n",
             vi->rate, vi->channels);
-    if (mAudioSink->open(vi->rate, vi->channels, DEFAULT_AUDIOSINK_BUFFERCOUNT) != NO_ERROR) {
+    if (mAudioSink->open(vi->rate, vi->channels, AudioSystem::PCM_16_BIT, DEFAULT_AUDIOSINK_BUFFERCOUNT) != NO_ERROR) {
         LOGE("mAudioSink open failed");
         return ERROR_OPEN_FAILED;
     }