Initial Contribution
diff --git a/include/media/AudioRecord.h b/include/media/AudioRecord.h
new file mode 100644
index 0000000..008569f
--- /dev/null
+++ b/include/media/AudioRecord.h
@@ -0,0 +1,235 @@
+/*
+ * 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 AUDIORECORD_H_
+#define AUDIORECORD_H_
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <media/IAudioFlinger.h>
+#include <media/IAudioRecord.h>
+#include <media/AudioTrack.h>
+
+#include <utils/RefBase.h>
+#include <utils/Errors.h>
+#include <utils/IInterface.h>
+#include <utils/IMemory.h>
+#include <utils/threads.h>
+
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+class AudioRecord
+{
+public: 
+    
+    enum stream_type {
+        DEFAULT_INPUT   =-1,
+        MIC_INPUT       = 0,
+        NUM_STREAM_TYPES
+    };
+    
+    static const int DEFAULT_SAMPLE_RATE = 8000; 
+    
+    /* Create Buffer on the stack and pass it to obtainBuffer()
+     * and releaseBuffer().
+     */
+
+    class Buffer
+    {
+    public:
+        enum {
+            MUTE    = 0x00000001
+        };
+        uint32_t    flags;
+        int         channelCount;
+        int         format;
+        size_t      frameCount;
+        size_t      size;
+        union {
+            void*       raw;
+            short*      i16;
+            int8_t*     i8;
+        };
+    };
+
+    /* These are static methods to control the system-wide AudioFlinger
+     * only privileged processes can have access to them
+     */
+
+//    static status_t setMasterMute(bool mute);
+
+    /* Returns AudioFlinger's frame count. AudioRecord's buffers will
+     * be created with this size.
+     */
+    static  size_t      frameCount();
+
+    /* As a convenience, if a callback is supplied, a handler thread
+     * is automatically created with the appropriate priority. This thread
+     * invokes the callback when a new buffer becomes availlable.
+     */
+    typedef bool (*callback_t)(void* user, const Buffer& info);
+
+    /* Constructs an uninitialized AudioRecord. No connection with
+     * AudioFlinger takes place.
+     */
+                        AudioRecord();
+                        
+    /* Creates an AudioRecord track and registers it with AudioFlinger.
+     * Once created, the track needs to be started before it can be used.
+     * Unspecified values are set to the audio hardware's current
+     * values.
+     */
+     
+                        AudioRecord(int streamType      = 0,
+                                    uint32_t sampleRate = 0,
+                                    int format          = 0,
+                                    int channelCount    = 0,
+                                    int bufferCount     = 0,
+                                    uint32_t flags      = 0,
+                                    callback_t cbf = 0, void* user = 0);
+
+
+    /* Terminates the AudioRecord and unregisters it from AudioFlinger.
+     * Also destroys all resources assotiated with the AudioRecord.
+     */ 
+                        ~AudioRecord();
+
+
+    /* Initialize an uninitialized AudioRecord. */
+            status_t    set(int streamType      = 0,
+                            uint32_t sampleRate = 0,
+                            int format          = 0,
+                            int channelCount    = 0,
+                            int bufferCount     = 0,
+                            uint32_t flags      = 0,
+                            callback_t cbf = 0, void* user = 0);
+        
+
+    /* Result of constructing the AudioRecord. This must be checked
+     * before using any AudioRecord API (except for set()), using
+     * an uninitialized AudioRecord prduces undefined results.
+     */
+            status_t    initCheck() const;
+
+    /* Returns this track's latency in nanoseconds or framecount.
+     * This only includes the latency due to the fill buffer size.
+     * In particular, the hardware or driver latencies are not accounted.
+     */
+            nsecs_t     latency() const;
+
+   /* getters, see constructor */ 
+            
+            uint32_t    sampleRate() const;
+            int         format() const;
+            int         channelCount() const;
+            int         bufferCount() const;
+
+
+    /* After it's created the track is not active. Call start() to
+     * make it active. If set, the callback will start being called.
+     */
+            status_t    start();
+
+    /* Stop a track. If set, the callback will cease being called and
+     * obtainBuffer returns STOPPED. Note that obtainBuffer() still works
+     * and will fill up buffers until the pool is exhausted.
+     */
+            status_t    stop();
+            bool        stopped() const;
+
+    /* get sample rate for this track
+     */
+            uint32_t    getSampleRate();
+
+    /* obtains a buffer of "frameCount" frames. The buffer must be
+     * filled entirely. If the track is stopped, obtainBuffer() returns
+     * STOPPED instead of NO_ERROR as long as there are buffers availlable,
+     * at which point NO_MORE_BUFFERS is returned.
+     * Buffers will be returned until the pool (buffercount())
+     * is exhausted, at which point obtainBuffer() will either block 
+     * or return WOULD_BLOCK depending on the value of the "blocking"
+     * parameter. 
+     */
+     
+        enum {
+            NO_MORE_BUFFERS = 0x80000001,
+            STOPPED = 1
+        };
+     
+            status_t    obtainBuffer(Buffer* audioBuffer, bool blocking);
+            void        releaseBuffer(Buffer* audioBuffer);
+
+
+    /* As a convenience we provide a read() interface to the audio buffer.
+     * This is implemented on top of lockBuffer/unlockBuffer. 
+     */
+            ssize_t     read(void* buffer, size_t size);
+
+private:
+    /* copying audio tracks is not allowed */
+                        AudioRecord(const AudioRecord& other);
+            AudioRecord& operator = (const AudioRecord& other);
+
+    /* a small internal class to handle the callback */
+    class ClientRecordThread : public Thread
+    {
+    public:
+        ClientRecordThread(AudioRecord& receiver);
+    private:
+        friend class AudioRecord;
+        virtual bool        threadLoop();
+        virtual status_t    readyToRun() { return NO_ERROR; }
+        virtual void        onFirstRef() {}
+        AudioRecord& mReceiver;
+    };
+    
+            bool processAudioBuffer(const sp<ClientRecordThread>& thread);
+
+    sp<IAudioFlinger>       mAudioFlinger;
+    sp<IAudioRecord>        mAudioRecord;
+    sp<IMemory>             mCblkMemory;
+    sp<ClientRecordThread>  mClientRecordThread;
+    Mutex                   mRecordThreadLock;
+    
+    uint32_t                mSampleRate;
+    size_t                  mFrameCount;
+
+    audio_track_cblk_t*     mCblk;
+    uint8_t                 mFormat;
+    uint8_t                 mBufferCount;
+    uint8_t                 mChannelCount   : 4;
+    uint8_t                 mReserved       : 3;
+    status_t                mStatus;
+    nsecs_t                 mLatency;
+
+    volatile int32_t        mActive;
+
+    callback_t              mCbf;
+    void*                   mUserData;
+    
+    AudioRecord::Buffer      mAudioBuffer;
+    size_t                  mPosition;
+
+    uint32_t                mReservedFBC[4];
+};
+
+}; // namespace android
+
+#endif /*AUDIORECORD_H_*/
diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h
new file mode 100644
index 0000000..9fcbea5
--- /dev/null
+++ b/include/media/AudioSystem.h
@@ -0,0 +1,122 @@
+/*
+ * 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_AUDIOSYSTEM_H_
+#define ANDROID_AUDIOSYSTEM_H_
+
+#include <utils/RefBase.h>
+#include <utils/threads.h>
+#include <media/IAudioFlinger.h>
+
+namespace android {
+
+typedef void (*audio_error_callback)(status_t err);
+
+class AudioSystem
+{
+public:
+
+    enum audio_format {
+        DEFAULT = 0,
+        PCM_16_BIT,
+        PCM_8_BIT,
+        INVALID_FORMAT
+    };
+
+    enum audio_mode {
+        MODE_INVALID = -2,
+        MODE_CURRENT = -1,
+        MODE_NORMAL = 0,
+        MODE_RINGTONE,
+        MODE_IN_CALL,
+        NUM_MODES  // not a valid entry, denotes end-of-list
+    };
+
+    enum audio_routes {
+        ROUTE_EARPIECE       = (1 << 0),
+        ROUTE_SPEAKER        = (1 << 1),
+        ROUTE_BLUETOOTH      = (1 << 2),
+        ROUTE_HEADSET        = (1 << 3),
+        ROUTE_ALL       = (ROUTE_EARPIECE | ROUTE_SPEAKER | ROUTE_BLUETOOTH | ROUTE_HEADSET)
+    };
+
+    /* These are static methods to control the system-wide AudioFlinger
+     * only privileged processes can have access to them
+     */
+
+    // routing helper functions
+    static status_t speakerphone(bool state);
+    static status_t isSpeakerphoneOn(bool* state);
+    static status_t bluetoothSco(bool state);
+    static status_t isBluetoothScoOn(bool* state);
+    static status_t muteMicrophone(bool state);
+    static status_t isMicrophoneMuted(bool *state);
+
+    static status_t setMasterVolume(float value);
+    static status_t setMasterMute(bool mute);
+    static status_t getMasterVolume(float* volume);
+    static status_t getMasterMute(bool* mute);
+
+    static status_t setStreamVolume(int stream, float value);
+    static status_t setStreamMute(int stream, bool mute);
+    static status_t getStreamVolume(int stream, float* volume);
+    static status_t getStreamMute(int stream, bool* mute);
+
+    static status_t setMode(int mode);
+    static status_t getMode(int* mode);
+
+    static status_t setRouting(int mode, uint32_t routes, uint32_t mask);
+    static status_t getRouting(int mode, uint32_t* routes);
+
+    static status_t isMusicActive(bool *state);
+
+    // Temporary interface, do not use
+    // TODO: Replace with a more generic key:value get/set mechanism
+    static status_t setParameter(const char* key, const char* value);
+    
+    static void setErrorCallback(audio_error_callback cb);
+
+    // helper function to obtain AudioFlinger service handle
+    static const sp<IAudioFlinger>& get_audio_flinger();
+
+    static float linearToLog(int volume);
+    static int logToLinear(float volume);
+
+    // ----------------------------------------------------------------------------
+
+private:
+
+    class DeathNotifier: public IBinder::DeathRecipient
+    {
+    public:
+        DeathNotifier() {      
+        }
+        
+        virtual void binderDied(const wp<IBinder>& who);
+    };
+
+    static sp<DeathNotifier> gDeathNotifier;
+
+    friend class DeathNotifier;
+
+    static Mutex gLock;
+    static sp<IAudioFlinger> gAudioFlinger;
+    static audio_error_callback gAudioErrorCallback;
+};
+
+};  // namespace android
+
+#endif  /*ANDROID_AUDIOSYSTEM_H_*/
diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h
new file mode 100644
index 0000000..a89d7ff
--- /dev/null
+++ b/include/media/AudioTrack.h
@@ -0,0 +1,277 @@
+/*
+ * Copyright (C) 2007 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_AUDIOTRACK_H
+#define ANDROID_AUDIOTRACK_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <media/IAudioFlinger.h>
+#include <media/IAudioTrack.h>
+#include <media/AudioSystem.h>
+
+#include <utils/RefBase.h>
+#include <utils/Errors.h>
+#include <utils/IInterface.h>
+#include <utils/IMemory.h>
+#include <utils/threads.h>
+
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+class audio_track_cblk_t;
+
+// ----------------------------------------------------------------------------
+
+class AudioTrack
+{
+public: 
+
+    enum stream_type {
+        DEFAULT     =-1,
+        VOICE_CALL  = 0,
+        SYSTEM      = 1,
+        RING        = 2,
+        MUSIC       = 3,
+        ALARM       = 4,
+        NUM_STREAM_TYPES
+    };
+
+    enum channel_index {
+        MONO   = 0,
+        LEFT   = 0,
+        RIGHT  = 1
+    };
+
+    /* Create Buffer on the stack and pass it to obtainBuffer()
+     * and releaseBuffer().
+     */
+
+    class Buffer
+    {
+    public:
+        enum {
+            MUTE    = 0x00000001
+        };
+        uint32_t    flags;
+        int         channelCount;
+        int         format;
+        size_t      frameCount;
+        size_t      size;
+        union {
+            void*       raw;
+            short*      i16;
+            int8_t*     i8;
+        };
+    };
+
+    /* Returns AudioFlinger's frame count. AudioTrack's buffers will
+     * be created with this size.
+     */
+    static  size_t      frameCount();
+
+    /* As a convenience, if a callback is supplied, a handler thread
+     * is automatically created with the appropriate priority. This thread
+     * invokes the callback when a new buffer becomes availlable.
+     */
+    typedef void (*callback_t)(void* user, const Buffer& info);
+
+    /* Constructs an uninitialized AudioTrack. No connection with
+     * AudioFlinger takes place.
+     */
+                        AudioTrack();
+                        
+    /* Creates an audio track and registers it with AudioFlinger.
+     * Once created, the track needs to be started before it can be used.
+     * Unspecified values are set to the audio hardware's current
+     * values.
+     */
+     
+                        AudioTrack( int streamType,
+                                    uint32_t sampleRate = 0,
+                                    int format          = 0,
+                                    int channelCount    = 0,
+                                    int bufferCount     = 0,
+                                    uint32_t flags      = 0,
+                                    callback_t cbf = 0, void* user = 0);
+
+
+    /* Terminates the AudioTrack and unregisters it from AudioFlinger.
+     * Also destroys all resources assotiated with the AudioTrack.
+     */ 
+                        ~AudioTrack();
+
+
+    /* Initialize an uninitialized AudioTrack. */
+            status_t    set(int streamType      =-1,
+                            uint32_t sampleRate = 0,
+                            int format          = 0,
+                            int channelCount    = 0,
+                            int bufferCount     = 0,
+                            uint32_t flags      = 0,
+                            callback_t cbf = 0, void* user = 0);
+        
+
+    /* Result of constructing the AudioTrack. This must be checked
+     * before using any AudioTrack API (except for set()), using
+     * an uninitialized AudoiTrack prduces undefined results.
+     */
+            status_t    initCheck() const;
+
+    /* Returns this track's latency in nanoseconds or framecount.
+     * This only includes the latency due to the fill buffer size.
+     * In particular, the hardware or driver latencies are not accounted.
+     */
+            nsecs_t     latency() const;
+
+   /* getters, see constructor */ 
+            
+            int         streamType() const;
+            uint32_t    sampleRate() const;
+            int         format() const;
+            int         channelCount() const;
+            int         bufferCount() const;
+
+
+    /* After it's created the track is not active. Call start() to
+     * make it active. If set, the callback will start being called.
+     */
+            void        start();
+
+    /* Stop a track. If set, the callback will cease being called and
+     * obtainBuffer returns STOPPED. Note that obtainBuffer() still works
+     * and will fill up buffers until the pool is exhausted.
+     */
+            void        stop();
+            bool        stopped() const;
+
+    /* flush a stopped track. All pending buffers are discarded.
+     * This function has no effect if the track is not stoped.
+     */
+            void        flush();
+
+    /* Pause a track. If set, the callback will cease being called and
+     * obtainBuffer returns STOPPED. Note that obtainBuffer() still works
+     * and will fill up buffers until the pool is exhausted.
+     */
+            void        pause();
+
+    /* mute or unmutes this track.
+     * While mutted, the callback, if set, is still called.
+     */
+            void        mute(bool);
+            bool        muted() const;
+
+
+    /* set volume for this track, mostly used for games' sound effects
+     */
+            void        setVolume(float left, float right);
+            void        getVolume(float* left, float* right);
+
+    /* set sample rate for this track, mostly used for games' sound effects
+     */
+            void        setSampleRate(int sampleRate);
+            uint32_t    getSampleRate();
+
+    /* obtains a buffer of "frameCount" frames. The buffer must be
+     * filled entirely. If the track is stopped, obtainBuffer() returns
+     * STOPPED instead of NO_ERROR as long as there are buffers availlable,
+     * at which point NO_MORE_BUFFERS is returned.
+     * Buffers will be returned until the pool (buffercount())
+     * is exhausted, at which point obtainBuffer() will either block 
+     * or return WOULD_BLOCK depending on the value of the "blocking"
+     * parameter. 
+     */
+     
+        enum {
+            NO_MORE_BUFFERS = 0x80000001,
+            STOPPED = 1
+        };
+     
+            status_t    obtainBuffer(Buffer* audioBuffer, bool blocking);
+            void        releaseBuffer(Buffer* audioBuffer);
+
+
+    /* As a convenience we provide a write() interface to the audio buffer.
+     * This is implemented on top of lockBuffer/unlockBuffer. For best
+     * performance
+     * 
+     */
+            ssize_t     write(const void* buffer, size_t size);
+            
+    /*
+     * Dumps the state of an audio track.
+     */
+            status_t dump(int fd, const Vector<String16>& args) const;
+
+private:
+    /* copying audio tracks is not allowed */
+                        AudioTrack(const AudioTrack& other);
+            AudioTrack& operator = (const AudioTrack& other);
+
+    /* a small internal class to handle the callback */
+    class AudioTrackThread : public Thread
+    {
+    public:
+        AudioTrackThread(AudioTrack& receiver);
+    private:
+        friend class AudioTrack;
+        virtual bool        threadLoop();
+        virtual status_t    readyToRun();
+        virtual void        onFirstRef();
+        AudioTrack& mReceiver;
+        Mutex       mLock;
+    };
+    
+            bool processAudioBuffer(const sp<AudioTrackThread>& thread);
+
+    sp<IAudioFlinger>       mAudioFlinger;
+    sp<IAudioTrack>         mAudioTrack;
+    sp<IMemory>             mCblkMemory;
+    sp<AudioTrackThread>    mAudioTrackThread;
+    
+    float                   mVolume[2];
+    uint32_t                mSampleRate;
+    size_t                  mFrameCount;
+
+    audio_track_cblk_t*     mCblk;
+    uint8_t                 mStreamType;
+    uint8_t                 mFormat;
+    uint8_t                 mBufferCount;
+    uint8_t                 mChannelCount   : 4;
+    uint8_t                 mMuted          : 1;
+    uint8_t                 mReserved       : 2;
+    status_t                mStatus;
+    nsecs_t                 mLatency;
+
+    volatile int32_t        mActive;
+
+    callback_t              mCbf;
+    void*                   mUserData;
+    
+    AudioTrack::Buffer      mAudioBuffer;
+    size_t                  mPosition;
+
+    uint32_t                mReservedFBC[4];
+};
+
+
+}; // namespace android
+
+#endif // ANDROID_AUDIOTRACK_H
diff --git a/include/media/IAudioFlinger.h b/include/media/IAudioFlinger.h
new file mode 100644
index 0000000..fa8e121
--- /dev/null
+++ b/include/media/IAudioFlinger.h
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2007 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_IAUDIOFLINGER_H
+#define ANDROID_IAUDIOFLINGER_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <utils/RefBase.h>
+#include <utils/Errors.h>
+#include <utils/IInterface.h>
+#include <media/IAudioTrack.h>
+#include <media/IAudioRecord.h>
+
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+class IAudioFlinger : public IInterface
+{
+public:
+    DECLARE_META_INTERFACE(AudioFlinger);
+
+    /* create an audio track and registers it with AudioFlinger.
+     * return null if the track cannot be created.
+     */
+    virtual sp<IAudioTrack> createTrack(
+                                pid_t pid,
+                                int streamType,
+                                uint32_t sampleRate,
+                                int format,
+                                int channelCount,
+                                int bufferCount,
+                                uint32_t flags) = 0;
+
+    virtual sp<IAudioRecord> openRecord(
+                                pid_t pid,
+                                int streamType,
+                                uint32_t sampleRate,
+                                int format,
+                                int channelCount,
+                                int bufferCount,
+                                uint32_t flags) = 0;
+
+    /* query the audio hardware state. This state never changes,
+     * and therefore can be cached.
+     */
+    virtual     uint32_t    sampleRate() const = 0;
+    virtual     int         channelCount() const = 0;
+    virtual     int         format() const = 0;
+    virtual     size_t      frameCount() const = 0;
+
+    /* set/get the audio hardware state. This will probably be used by
+     * the preference panel, mostly.
+     */
+    virtual     status_t    setMasterVolume(float value) = 0;
+    virtual     status_t    setMasterMute(bool muted) = 0;
+
+    virtual     float       masterVolume() const = 0;
+    virtual     bool        masterMute() const = 0;
+
+    /* set/get stream type state. This will probably be used by
+     * the preference panel, mostly.
+     */
+    virtual     status_t    setStreamVolume(int stream, float value) = 0;
+    virtual     status_t    setStreamMute(int stream, bool muted) = 0;
+
+    virtual     float       streamVolume(int stream) const = 0;
+    virtual     bool        streamMute(int stream) const = 0;
+
+    // set/get audio routing
+    virtual     status_t    setRouting(int mode, uint32_t routes, uint32_t mask) = 0;
+    virtual     uint32_t    getRouting(int mode) const = 0;
+
+    // set/get audio mode
+    virtual     status_t    setMode(int mode) = 0;
+    virtual     int         getMode() const = 0;
+
+    // mic mute/state
+    virtual     status_t    setMicMute(bool state) = 0;
+    virtual     bool        getMicMute() const = 0;
+
+    // is a music stream active?
+    virtual     bool        isMusicActive() const = 0;
+
+    // pass a generic configuration parameter to libaudio
+    // Temporary interface, do not use
+    // TODO: Replace with a more generic key:value get/set mechanism
+    virtual     status_t  setParameter(const char* key, const char* value) = 0;
+};
+
+
+// ----------------------------------------------------------------------------
+
+class BnAudioFlinger : public BnInterface<IAudioFlinger>
+{
+public:
+    virtual status_t    onTransact( uint32_t code,
+                                    const Parcel& data,
+                                    Parcel* reply,
+                                    uint32_t flags = 0);
+};
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_IAUDIOFLINGER_H
diff --git a/include/media/IAudioRecord.h b/include/media/IAudioRecord.h
new file mode 100644
index 0000000..9d45d2d
--- /dev/null
+++ b/include/media/IAudioRecord.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2007 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 IAUDIORECORD_H_
+#define IAUDIORECORD_H_
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/RefBase.h>
+#include <utils/Errors.h>
+#include <utils/IInterface.h>
+#include <utils/IMemory.h>
+
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+class IAudioRecord : public IInterface
+{
+public: 
+    DECLARE_META_INTERFACE(AudioRecord);
+
+    /* After it's created the track is not active. Call start() to
+     * make it active. If set, the callback will start being called.
+     */
+    virtual status_t    start() = 0;
+
+    /* Stop a track. If set, the callback will cease being called and
+     * obtainBuffer will return an error. Buffers that are already released 
+     * will be processed, unless flush() is called.
+     */
+    virtual void        stop() = 0;
+
+    /* get this tracks control block */
+    virtual sp<IMemory> getCblk() const = 0;    
+};
+
+// ----------------------------------------------------------------------------
+
+class BnAudioRecord : public BnInterface<IAudioRecord>
+{
+public:
+    virtual status_t    onTransact( uint32_t code,
+                                    const Parcel& data,
+                                    Parcel* reply,
+                                    uint32_t flags = 0);
+};
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
+
+#endif /*IAUDIORECORD_H_*/
diff --git a/include/media/IAudioTrack.h b/include/media/IAudioTrack.h
new file mode 100644
index 0000000..12f2111
--- /dev/null
+++ b/include/media/IAudioTrack.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2007 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_IAUDIOTRACK_H
+#define ANDROID_IAUDIOTRACK_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/RefBase.h>
+#include <utils/Errors.h>
+#include <utils/IInterface.h>
+#include <utils/IMemory.h>
+
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+class IAudioTrack : public IInterface
+{
+public: 
+    DECLARE_META_INTERFACE(AudioTrack);
+
+    /* After it's created the track is not active. Call start() to
+     * make it active. If set, the callback will start being called.
+     */
+    virtual status_t    start() = 0;
+
+    /* Stop a track. If set, the callback will cease being called and
+     * obtainBuffer will return an error. Buffers that are already released 
+     * will be processed, unless flush() is called.
+     */
+    virtual void        stop() = 0;
+
+    /* flush a stopped track. All pending buffers are discarded.
+     * This function has no effect if the track is not stoped.
+     */
+    virtual void        flush() = 0;
+
+    /* mute or unmutes this track.
+     * While mutted, the callback, if set, is still called.
+     */
+    virtual void        mute(bool) = 0;
+    
+    /* Pause a track. If set, the callback will cease being called and
+     * obtainBuffer will return an error. Buffers that are already released 
+     * will be processed, unless flush() is called.
+     */
+    virtual void        pause() = 0;
+
+    /* get this tracks control block */
+    virtual sp<IMemory> getCblk() const = 0;    
+};
+
+// ----------------------------------------------------------------------------
+
+class BnAudioTrack : public BnInterface<IAudioTrack>
+{
+public:
+    virtual status_t    onTransact( uint32_t code,
+                                    const Parcel& data,
+                                    Parcel* reply,
+                                    uint32_t flags = 0);
+};
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_IAUDIOTRACK_H
diff --git a/include/media/IMediaPlayer.h b/include/media/IMediaPlayer.h
new file mode 100644
index 0000000..43abf77
--- /dev/null
+++ b/include/media/IMediaPlayer.h
@@ -0,0 +1,65 @@
+/*
+ * 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_IMEDIAPLAYER_H
+#define ANDROID_IMEDIAPLAYER_H
+
+#include <utils/RefBase.h>
+#include <utils/IInterface.h>
+#include <utils/Parcel.h>
+
+namespace android {
+
+class ISurface;
+
+class IMediaPlayer: public IInterface
+{
+public:
+    DECLARE_META_INTERFACE(MediaPlayer);
+
+    virtual void            disconnect() = 0;
+
+    virtual status_t        setVideoSurface(const sp<ISurface>& surface) = 0;
+    virtual status_t        prepareAsync() = 0;
+    virtual status_t        start() = 0;
+    virtual status_t        stop() = 0;
+    virtual status_t        pause() = 0;
+    virtual status_t        isPlaying(bool* state) = 0;
+    virtual status_t        getVideoSize(int* w, int* h) = 0;
+    virtual status_t        seekTo(int msec) = 0;
+    virtual status_t        getCurrentPosition(int* msec) = 0;
+    virtual status_t        getDuration(int* msec) = 0;
+    virtual status_t        reset() = 0;
+    virtual status_t        setAudioStreamType(int type) = 0;
+    virtual status_t        setLooping(int loop) = 0;
+    virtual status_t        setVolume(float leftVolume, float rightVolume) = 0;
+};
+
+// ----------------------------------------------------------------------------
+
+class BnMediaPlayer: public BnInterface<IMediaPlayer>
+{
+public:
+    virtual status_t    onTransact( uint32_t code,
+                                    const Parcel& data,
+                                    Parcel* reply,
+                                    uint32_t flags = 0);
+};
+
+}; // namespace android
+
+#endif // ANDROID_IMEDIAPLAYER_H
+
diff --git a/include/media/IMediaPlayerClient.h b/include/media/IMediaPlayerClient.h
new file mode 100644
index 0000000..5d32811
--- /dev/null
+++ b/include/media/IMediaPlayerClient.h
@@ -0,0 +1,48 @@
+/*
+ * 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_IMEDIAPLAYERCLIENT_H
+#define ANDROID_IMEDIAPLAYERCLIENT_H
+
+#include <utils/RefBase.h>
+#include <utils/IInterface.h>
+#include <utils/Parcel.h>
+
+namespace android {
+
+class IMediaPlayerClient: public IInterface
+{
+public:
+    DECLARE_META_INTERFACE(MediaPlayerClient);
+
+    virtual void notify(int msg, int ext1, int ext2) = 0;
+};
+
+// ----------------------------------------------------------------------------
+
+class BnMediaPlayerClient: public BnInterface<IMediaPlayerClient>
+{
+public:
+    virtual status_t    onTransact( uint32_t code,
+                                    const Parcel& data,
+                                    Parcel* reply,
+                                    uint32_t flags = 0);
+};
+
+}; // namespace android
+
+#endif // ANDROID_IMEDIAPLAYERCLIENT_H
+
diff --git a/include/media/IMediaPlayerService.h b/include/media/IMediaPlayerService.h
new file mode 100644
index 0000000..63c7a00
--- /dev/null
+++ b/include/media/IMediaPlayerService.h
@@ -0,0 +1,54 @@
+/*
+ * 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_IMEDIAPLAYERSERVICE_H
+#define ANDROID_IMEDIAPLAYERSERVICE_H
+
+#include <utils/RefBase.h>
+#include <utils/IInterface.h>
+#include <utils/Parcel.h>
+
+#include <media/IMediaPlayerClient.h>
+#include <media/IMediaPlayer.h>
+
+namespace android {
+
+class IMediaPlayerService: public IInterface
+{
+public:
+    DECLARE_META_INTERFACE(MediaPlayerService);
+
+    virtual sp<IMediaPlayer>    create(pid_t pid, const sp<IMediaPlayerClient>& client, const char* url) = 0;
+    virtual sp<IMediaPlayer>    create(pid_t pid, const sp<IMediaPlayerClient>& client, int fd, int64_t offset, int64_t length) = 0;
+    virtual sp<IMemory>         decode(const char* url, uint32_t *pSampleRate, int* pNumChannels) = 0;
+    virtual sp<IMemory>         decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels) = 0;
+};
+
+// ----------------------------------------------------------------------------
+
+class BnMediaPlayerService: public BnInterface<IMediaPlayerService>
+{
+public:
+    virtual status_t    onTransact( uint32_t code,
+                                    const Parcel& data,
+                                    Parcel* reply,
+                                    uint32_t flags = 0);
+};
+
+}; // namespace android
+
+#endif // ANDROID_IMEDIAPLAYERSERVICE_H
+
diff --git a/include/media/MediaPlayerInterface.h b/include/media/MediaPlayerInterface.h
new file mode 100644
index 0000000..275e789
--- /dev/null
+++ b/include/media/MediaPlayerInterface.h
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2007 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_MEDIAPLAYERINTERFACE_H
+#define ANDROID_MEDIAPLAYERINTERFACE_H
+
+#include <pthread.h>
+#include <signal.h>
+
+#ifdef __cplusplus
+
+#include <ui/ISurface.h>
+#include <utils/RefBase.h>
+
+#include <media/mediaplayer.h>
+
+namespace android {
+
+enum player_type {
+    PV_PLAYER = 1,
+    SONIVOX_PLAYER = 2,
+    VORBIS_PLAYER = 3
+};
+
+#define DEFAULT_AUDIOSINK_BUFFERCOUNT 4
+
+// callback mechanism for passing messages to MediaPlayer object
+typedef void (*notify_callback_f)(void* cookie, int msg, int ext1, int ext2);
+
+// abstract base class - use MediaPlayerInterface
+class MediaPlayerBase : public RefBase
+{
+public:
+
+    // AudioSink: abstraction layer for audio output
+    class AudioSink : public RefBase {
+    public:
+        virtual             ~AudioSink() {}
+        virtual bool        ready() const = 0; // audio output is open and ready
+        virtual bool        realtime() const = 0; // audio output is real-time output
+        virtual ssize_t     bufferSize() const = 0;
+        virtual ssize_t     frameCount() const = 0;
+        virtual ssize_t     channelCount() const = 0;
+        virtual ssize_t     frameSize() const = 0;
+        virtual uint32_t    latency() const = 0;
+        virtual float       msecsPerFrame() const = 0;
+        virtual status_t    open(uint32_t sampleRate, int channelCount, int bufferCount=DEFAULT_AUDIOSINK_BUFFERCOUNT) = 0;
+        virtual void        start() = 0;
+        virtual ssize_t     write(const void* buffer, size_t size) = 0;
+        virtual void        stop() = 0;
+        virtual void        flush() = 0;
+        virtual void        pause() = 0;
+        virtual void        close() = 0;
+    };
+
+                        MediaPlayerBase() : mCookie(0), mNotify(0) {}
+    virtual             ~MediaPlayerBase() {}
+    virtual status_t    initCheck() = 0;
+    virtual bool        hardwareOutput() = 0;
+    virtual status_t    setSigBusHandlerStructTLSKey(pthread_key_t key) { return 0; }
+    virtual status_t    setDataSource(const char *url) = 0;
+    virtual status_t    setDataSource(int fd, int64_t offset, int64_t length) = 0;
+    virtual status_t    setVideoSurface(const sp<ISurface>& surface) = 0;
+    virtual status_t    prepare() = 0;
+    virtual status_t    prepareAsync() = 0;
+    virtual status_t    start() = 0;
+    virtual status_t    stop() = 0;
+    virtual status_t    pause() = 0;
+    virtual bool        isPlaying() = 0;
+    virtual status_t    getVideoWidth(int *w) {return 0;}
+    virtual status_t    getVideoHeight(int *h) {return 0;}
+    virtual status_t    seekTo(int msec) = 0;
+    virtual status_t    getCurrentPosition(int *msec) = 0;
+    virtual status_t    getDuration(int *msec) = 0;
+    virtual status_t    reset() = 0;
+    virtual status_t    setLooping(int loop) = 0;
+    virtual player_type playerType() = 0;
+    virtual void        setNotifyCallback(void* cookie, notify_callback_f notifyFunc) {
+                            mCookie = cookie; mNotify = notifyFunc; }
+
+protected:
+    virtual void        sendEvent(int msg, int ext1=0, int ext2=0) { if (mNotify) mNotify(mCookie, msg, ext1, ext2); }
+
+    void*               mCookie;
+    notify_callback_f   mNotify;
+};
+
+// Implement this class for media players that use the AudioFlinger software mixer
+class MediaPlayerInterface : public MediaPlayerBase
+{
+public:
+    virtual             ~MediaPlayerInterface() { }
+    virtual bool        hardwareOutput() { return false; }
+    virtual void        setAudioSink(const sp<AudioSink>& audioSink) { mAudioSink = audioSink; }
+protected:
+    sp<AudioSink>       mAudioSink;
+};
+
+// Implement this class for media players that output directo to hardware
+class MediaPlayerHWInterface : public MediaPlayerBase
+{
+public:
+    virtual             ~MediaPlayerHWInterface() {}
+    virtual bool        hardwareOutput() { return true; }
+    virtual status_t    setVolume(float leftVolume, float rightVolume) = 0;
+    virtual status_t    setAudioStreamType(int streamType) = 0;
+};
+
+}; // namespace android
+
+#endif // __cplusplus
+
+// A thread can set the thread local variable identified by the pthread_key_t
+// that was passed to the player using the setSigBusHandlerStructTLSKey()
+// method to the address of the following structure.
+// If 'handlesigbus' is non-NULL, the function it points to will be called,
+// and if it returns 0, the signal will be assumed to have been handled,
+// and no other action will be taken. If it returns non-zero, the old SIGBUS
+// handler will be called.
+// If 'handlesigbus is NULL, then sigbusvar must be non NULL. The system's
+// SIGBUS handler will map an accessible page filled with zeroes at the
+// location that caused the original fault, set the variable pointed to by
+// sigbusvar to a non-zero value, and exit (which causes the operation to
+// be retried, which should now succeed).
+// If base and len are non zero, which is strongly recommended, they will
+// be used as additional constraints on the signal handler. That is, when
+// specified, the fault address must be in the range specified by base and
+// len in order for handlesigbus() to be called or sigbusvar to be set.
+// If the fault address is outside of the range, the old SIGBUS handler
+// will be called.
+struct mediasigbushandler {
+    int (*handlesigbus)(siginfo_t *, struct mediasigbushandler *);
+    int  *sigbusvar;
+    char *base;
+    int len;
+    // these next two are free for application use
+    struct mediasigbushandler *next;
+    void *data;
+};
+
+
+#endif // ANDROID_MEDIAPLAYERINTERFACE_H
+
diff --git a/include/media/PVPlayer.h b/include/media/PVPlayer.h
new file mode 100644
index 0000000..8164d8c
--- /dev/null
+++ b/include/media/PVPlayer.h
@@ -0,0 +1,75 @@
+/*
+ * 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_PVPLAYER_H
+#define ANDROID_PVPLAYER_H
+
+#include <utils/Errors.h>
+#include <media/MediaPlayerInterface.h>
+
+class PlayerDriver;
+
+namespace android {
+
+class PVPlayer : public MediaPlayerInterface
+{
+public:
+                        PVPlayer();
+    virtual             ~PVPlayer();
+
+    virtual status_t    initCheck();
+    virtual status_t    setSigBusHandlerStructTLSKey(pthread_key_t key);
+    virtual status_t    setDataSource(const char *url);
+    virtual status_t    setDataSource(int fd, int64_t offset, int64_t length);
+    virtual status_t    setVideoSurface(const sp<ISurface>& surface);
+    virtual status_t    prepare();
+    virtual status_t    prepareAsync();
+    virtual status_t    start();
+    virtual status_t    stop();
+    virtual status_t    pause();
+    virtual bool        isPlaying();
+    virtual status_t    getVideoWidth(int *w);
+    virtual status_t    getVideoHeight(int *h);
+    virtual status_t    seekTo(int msec);
+    virtual status_t    getCurrentPosition(int *msec);
+    virtual status_t    getDuration(int *msec);
+    virtual status_t    reset();
+    virtual status_t    setLooping(int loop);
+    virtual player_type playerType() { return PV_PLAYER; }
+
+            // make available to PlayerDriver
+            void        sendEvent(int msg, int ext1=0, int ext2=0) { MediaPlayerBase::sendEvent(msg, ext1, ext2); }
+
+private:
+    static void         do_nothing(status_t s, void *cookie) { }
+    static void         run_init(status_t s, void *cookie);
+    static void         run_set_video_surface(status_t s, void *cookie);
+    static void         run_set_audio_output(status_t s, void *cookie);
+    static void         run_prepare(status_t s, void *cookie);
+
+    PlayerDriver*               mPlayerDriver;
+    char *                      mDataSourcePath;
+    bool                        mIsDataSourceSet;
+    sp<ISurface>                mSurface;
+    void *                      mMemBase;
+    off_t                       mMemSize;
+    status_t                    mInit;
+    int                         mDuration;
+};
+
+}; // namespace android
+
+#endif // ANDROID_PVPLAYER_H
diff --git a/include/media/ToneGenerator.h b/include/media/ToneGenerator.h
new file mode 100644
index 0000000..bc27d35
--- /dev/null
+++ b/include/media/ToneGenerator.h
@@ -0,0 +1,175 @@
+/*
+ * 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_TONEGENERATOR_H_
+#define ANDROID_TONEGENERATOR_H_
+
+#include <utils/RefBase.h>
+#include <utils/Vector.h>
+#include <utils/threads.h>
+#include <media/AudioSystem.h>
+#include <media/AudioTrack.h>
+
+namespace android {
+
+class ToneGenerator {
+public:
+
+    // List of all available tones
+    // This enum must be kept consistant with constants in ToneGenerator JAVA class
+    enum tone_type {
+        // DTMF tones  ITU-T Recommendation Q.23
+        TONE_DTMF_0 = 0,  // 0 key: 1336Hz, 941Hz
+        TONE_DTMF_1,  // 1 key: 1209Hz, 697Hz
+        TONE_DTMF_2,  // 2 key: 1336Hz, 697Hz
+        TONE_DTMF_3,  // 3 key: 1477Hz, 697Hz
+        TONE_DTMF_4,  // 4 key: 1209Hz, 770Hz
+        TONE_DTMF_5,  // 5 key: 1336Hz, 770Hz
+        TONE_DTMF_6,  // 6 key: 1477Hz, 770Hz
+        TONE_DTMF_7,  // 7 key: 1209Hz, 852Hz
+        TONE_DTMF_8,  // 8 key: 1336Hz, 852Hz
+        TONE_DTMF_9,  // 9 key: 1477Hz, 852Hz
+        TONE_DTMF_S,  // * key: 1209Hz, 941Hz
+        TONE_DTMF_P,  // # key: 1477Hz, 941Hz
+        TONE_DTMF_A,  // A key: 1633Hz, 697Hz
+        TONE_DTMF_B,  // B key: 1633Hz, 770Hz
+        TONE_DTMF_C,  // C key: 1633Hz, 852Hz
+        TONE_DTMF_D,  // D key: 1633Hz, 941Hz
+        // Call supervisory tones:  3GPP TS 22.001 (CEPT)
+        TONE_SUP_DIAL,  // Dial tone: 425Hz, continuous
+        TONE_SUP_BUSY,  // Busy tone: 425Hz, 500ms ON, 500ms OFF...
+        TONE_SUP_CONGESTION,  // Congestion tone: 425Hz, 200ms ON, 200ms OFF...
+        TONE_SUP_RADIO_ACK,  // Radio path acknowlegment: 425Hz, 200ms ON
+        TONE_SUP_RADIO_NOTAVAIL,  // Radio path not available: 425Hz, 200ms ON, 200 OFF 3 bursts
+        TONE_SUP_ERROR,  // Error/Special info:  950Hz+1400Hz+1800Hz, 330ms ON, 1s OFF...
+        TONE_SUP_CALL_WAITING,  // Call Waiting:  425Hz, 200ms ON, 600ms OFF, 200ms ON, 3s OFF...
+        TONE_SUP_RINGTONE,  // Ring Tone:  425Hz, 1s ON, 4s OFF...
+        // Proprietary tones:  3GPP TS 31.111
+        TONE_PROP_BEEP,  // General beep: 400Hz+1200Hz, 35ms ON
+        TONE_PROP_ACK,  // Positive Acknowlgement: 1200Hz, 100ms ON, 100ms OFF 2 bursts
+        TONE_PROP_NACK,  // Negative Acknowlgement: 300Hz+400Hz+500Hz, 400ms ON 
+        TONE_PROP_PROMPT,  // Prompt tone: 400Hz+1200Hz, 200ms ON
+        TONE_PROP_BEEP2,  // General double beep: 400Hz+1200Hz, 35ms ON, 200ms OFF, 35ms on
+        NUM_TONES
+    };
+
+    ToneGenerator(int streamType, float volume);
+    ~ToneGenerator();
+
+    bool startTone(int toneType);
+    void stopTone();
+
+    bool isInited() { return (mState == TONE_IDLE)?false:true;}
+
+private:
+
+    enum tone_state {
+        TONE_IDLE,  // ToneGenerator is being initialized or initialization failed
+        TONE_INIT,  // ToneGenerator has been successfully initialized and is not playing
+        TONE_STARTING,  // ToneGenerator is starting playing
+        TONE_PLAYING,  // ToneGenerator is playing
+        TONE_STOPPING,  // ToneGenerator is stoping
+        TONE_RESTARTING  //
+    };
+
+    static const unsigned int NUM_PCM_BUFFERS = 2; // number of pcm buffers of audio track
+    
+    static const unsigned int TONEGEN_MAX_WAVES = 3;
+    static const unsigned int TONEGEN_MAX_SEGMENTS = 4;  // Maximun number of elenemts in
+    static const unsigned int TONEGEN_INF = 0xFFFFFFFF;  // Represents infinite time duration
+    static const float TONEGEN_GAIN = 0.9;  // Default gain passed to  WaveGenerator().
+
+    // ToneDescriptor class contains all parameters needed to generate a tone:
+    //    - The array waveFreq[] contains the frequencies of all individual waves making the multi-tone.
+    //        The number of sine waves varies from 1 to TONEGEN_MAX_WAVES.
+    //        The first null value indicates that no more waves are needed.
+    //    - The array segments[] is used to generate the tone pulses. A segment is a period of time
+    //        during which the tone is ON or OFF.    Segments with even index (starting from 0)
+    //        correspond to tone ON state and segments with odd index to OFF state.
+    //        The data stored in segments[] is the duration of the corresponding period in ms.
+    //        The first segment encountered with a 0 duration    indicates that no more segment follows.
+    //    - repeatCnt indicates the number of times the sequence described by segments[] array must be repeated.
+    //        When the tone generator    encounters the first 0 duration segment, it will compare repeatCnt to mCurCount.
+    //        If mCurCount > repeatCnt, the tone is stopped automatically.
+
+    class ToneDescriptor {
+    public:
+        unsigned short waveFreq[TONEGEN_MAX_WAVES+1];
+        unsigned long segments[TONEGEN_MAX_SEGMENTS+1];
+        unsigned long repeatCnt;
+    };
+
+    static const ToneDescriptor toneDescriptors[NUM_TONES];
+
+    unsigned int mTotalSmp;  // Total number of audio samples played (gives current time)
+    unsigned int mNextSegSmp;  // Position of next segment transition expressed in samples
+    // NOTE: because mTotalSmp, mNextSegSmp are stored on 32 bit, current design will operate properly
+    // only if tone duration is less than about 27 Hours(@44100Hz sampling rate). If this time is exceeded,
+    // no crash will occur but tone sequence will show a glitch.
+
+    unsigned short mCurSegment;  // Current segment index in ToneDescriptor segments[]
+    unsigned short mCurCount;  // Current sequence repeat count
+    volatile unsigned short mState;  // ToneGenerator state (tone_state)
+    const ToneDescriptor *mpToneDesc;  // pointer to active tone descriptor
+    const ToneDescriptor *mpNewToneDesc;  // pointer to next active tone descriptor
+
+    unsigned int mSamplingRate;  // Sampling rate
+    AudioTrack *mpAudioTrack;  // Pointer to audio track used for playback
+    Mutex mLock;  // Mutex to control concurent access to ToneGenerator object from audio callback and application API
+    Mutex mCbkCondLock; // Mutex associated to mWaitCbkCond
+    Condition mWaitCbkCond; // condition enabling interface to wait for audio callback completion after a change is requested
+    float mVolume;  // Volume applied to audio track
+
+    static void audioCallback(void* user, const AudioTrack::Buffer& info);
+    bool prepareWave();
+    unsigned int numWaves();
+    void clearWaveGens();
+
+    // WaveGenerator generates a single sine wave
+    class WaveGenerator {
+    public:
+        enum gen_command {
+            WAVEGEN_START,  // Start/restart wave from phase 0
+            WAVEGEN_CONT,  // Continue wave from current phase
+            WAVEGEN_STOP  // Stop wave on zero crossing
+        };
+
+        WaveGenerator(unsigned short samplingRate, unsigned short frequency,
+                float volume);
+        ~WaveGenerator();
+
+        void getSamples(short *outBuffer, unsigned int count,
+                unsigned int command);
+
+    private:
+        static const short GEN_AMP = 32000;  // amplitude of generator
+        static const short S_Q14 = 14;  // shift for Q14
+        static const short S_Q15 = 15;  // shift for Q15
+
+        short mA1_Q14;  // Q14 coefficient
+        // delay line of full amplitude generator
+        short mS1, mS2;  // delay line S2 oldest
+        short mS2_0;  // saved value for reinitialisation
+        short mAmplitude_Q15;  // Q15 amplitude
+    };
+
+    Vector<WaveGenerator *> mWaveGens;  // list of active wave generators.
+};
+
+}
+;  // namespace android
+
+#endif /*ANDROID_TONEGENERATOR_H_*/
diff --git a/include/media/mediametadataretriever.h b/include/media/mediametadataretriever.h
new file mode 100644
index 0000000..586dda1
--- /dev/null
+++ b/include/media/mediametadataretriever.h
@@ -0,0 +1,101 @@
+/*
+ * 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 MEDIAMETADATARETRIEVER_H
+#define MEDIAMETADATARETRIEVER_H
+
+#include <graphics/SkBitmap.h>      // for SkBitmap
+
+namespace android {
+
+// Keep these in synch with the constants defined in MediaMetadataRetriever.java
+// class.
+enum {
+    METADATA_KEY_CD_TRACK_NUMBER = 0,
+    METADATA_KEY_ALBUM           = 1,
+    METADATA_KEY_ARTIST          = 2,
+    METADATA_KEY_AUTHOR          = 3,
+    METADATA_KEY_COMPOSER        = 4,
+    METADATA_KEY_DATE            = 5,
+    METADATA_KEY_GENRE           = 6,
+    METADATA_KEY_TITLE           = 7,
+    METADATA_KEY_YEAR            = 8,
+    METADATA_KEY_DURATION        = 9,
+    METADATA_KEY_NUM_TRACKS      = 10,
+    METADATA_KEY_IS_DRM_CRIPPLED = 11,
+    METADATA_KEY_CODEC           = 12,
+    // Add more here...
+};
+
+// A utility class that holds the size and actual data in album art.
+class MediaAlbumArt {
+public:
+    MediaAlbumArt(): length(0), data(NULL) {}
+    MediaAlbumArt(const MediaAlbumArt& copy) { 
+        // Don't be caught by uninitialized variables!!
+        length = 0; 
+        data = NULL; 
+        setData(copy.length, copy.data);
+    }
+    MediaAlbumArt(const char* url);
+    ~MediaAlbumArt() { clearData(); }
+
+    void clearData();
+    status_t setData(unsigned int len, const char* buf);
+    char *getData() const { return copyData(length, data); }
+    unsigned int getLength() const { return length; }
+    
+private:
+    // Disable copy assignment operator!
+    MediaAlbumArt& operator=(const MediaAlbumArt& rhs);
+    static char* copyData(unsigned int len, const char* buf);
+    
+    unsigned int length;    // Number of bytes in data.
+    char *data;             // Actual binary data.
+};
+
+class MediaMetadataRetrieverImpl
+{
+public:
+    virtual ~MediaMetadataRetrieverImpl() {};
+    virtual status_t setDataSource(const char* dataSourceUrl) = 0;
+    virtual SkBitmap *captureFrame() = 0;
+    virtual const char* extractMetadata(int keyCode) = 0;
+    virtual MediaAlbumArt* extractAlbumArt() = 0;
+    virtual void setMode(int mode) = 0;
+};
+
+class MediaMetadataRetriever
+{
+public:
+    static status_t setDataSource(const char* dataSourceUrl);
+    static SkBitmap *captureFrame();
+    static const char* extractMetadata(int keyCode);
+    static MediaAlbumArt* extractAlbumArt();
+    static void setMode(int mode);
+    static void release();
+    static void create();
+
+private:
+    MediaMetadataRetriever() {}
+    static MediaMetadataRetrieverImpl *mRetriever;
+    static void                       *mLibHandler;
+};
+
+}; // namespace android
+
+#endif // MEDIAMETADATARETRIEVER_H
diff --git a/include/media/mediaplayer.h b/include/media/mediaplayer.h
new file mode 100644
index 0000000..aadfc32
--- /dev/null
+++ b/include/media/mediaplayer.h
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2007 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_MEDIAPLAYER_H
+#define ANDROID_MEDIAPLAYER_H
+
+#include <ui/Surface.h>
+#include <media/AudioTrack.h>
+#include <media/IMediaPlayerClient.h>
+#include <media/IMediaPlayer.h>
+#include <media/IMediaPlayerService.h>
+
+namespace android {
+
+enum media_event_type {
+    MEDIA_NOP               = 0, // interface test message
+    MEDIA_PREPARED          = 1,
+    MEDIA_PLAYBACK_COMPLETE = 2,
+    MEDIA_BUFFERING_UPDATE  = 3,
+    MEDIA_SEEK_COMPLETE     = 4,
+    MEDIA_ERROR             = 100,
+};
+
+typedef int media_error_type;
+const media_error_type MEDIA_ERROR_UNKNOWN = 1;
+const media_error_type MEDIA_ERROR_SERVER_DIED = 100;
+
+enum media_player_states {
+    MEDIA_PLAYER_STATE_ERROR        = 0,
+    MEDIA_PLAYER_IDLE               = 1 << 0,
+    MEDIA_PLAYER_INITIALIZED        = 1 << 1,
+    MEDIA_PLAYER_PREPARING          = 1 << 2,
+    MEDIA_PLAYER_PREPARED           = 1 << 3,
+    MEDIA_PLAYER_STARTED            = 1 << 4,
+    MEDIA_PLAYER_PAUSED             = 1 << 5,
+    MEDIA_PLAYER_STOPPED            = 1 << 6,
+    MEDIA_PLAYER_PLAYBACK_COMPLETE  = 1 << 7
+};
+
+// ----------------------------------------------------------------------------
+// ref-counted object for callbacks
+class MediaPlayerListener: public RefBase
+{
+public:
+    virtual void notify(int msg, int ext1, int ext2) = 0;
+};
+
+class MediaPlayer : public BnMediaPlayerClient, public IBinder::DeathRecipient
+{
+public:
+    MediaPlayer();
+    ~MediaPlayer();
+
+            void            disconnect();
+            status_t        setDataSource(const char *url);
+            status_t        setDataSource(int fd, int64_t offset, int64_t length);
+            status_t        setVideoSurface(const sp<Surface>& surface);
+            status_t        setListener(const sp<MediaPlayerListener>& listener);
+            status_t        prepare();
+            status_t        prepareAsync();
+            status_t        start();
+            status_t        stop();
+            status_t        pause();
+            bool            isPlaying();
+            status_t        getVideoWidth(int *w);
+            status_t        getVideoHeight(int *h);
+            status_t        seekTo(int msec);
+            status_t        getCurrentPosition(int *msec);
+            status_t        getDuration(int *msec);
+            status_t        reset();
+            status_t        setAudioStreamType(int type);
+            status_t        setLooping(int loop);
+            status_t        setVolume(float leftVolume, float rightVolume);
+            void            notify(int msg, int ext1, int ext2);
+    static  sp<IMemory>     decode(const char* url, uint32_t *pSampleRate, int* pNumChannels);
+    static  sp<IMemory>     decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels);
+
+private:
+            void            clear_l();
+            status_t        seekTo_l(int msec);
+            status_t        prepareAsync_l();
+            status_t        getDuration_l(int *msec);
+            status_t        setDataSource(const sp<IMediaPlayer>& player);
+
+    static const sp<IMediaPlayerService>& getMediaPlayerService();
+    virtual void binderDied(const wp<IBinder>& who);
+
+    class DeathNotifier: public IBinder::DeathRecipient
+    {
+    public:
+                DeathNotifier() {}
+        virtual ~DeathNotifier();
+
+        virtual void binderDied(const wp<IBinder>& who);
+    };
+
+    static sp<DeathNotifier> mDeathNotifier;
+
+    sp<IMediaPlayer>            mPlayer;
+    Mutex                       mLock;
+    Mutex                       mNotifyLock;
+    Condition                   mSignal;
+    sp<MediaPlayerListener>     mListener;
+    void*                       mCookie;
+    media_player_states         mCurrentState;
+    int                         mDuration;
+    int                         mCurrentPosition;
+    int                         mSeekPosition;
+    bool                        mPrepareSync;
+    status_t                    mPrepareStatus;
+    int                         mStreamType;
+    bool                        mLoop;
+    float                       mLeftVolume;
+    float                       mRightVolume;
+
+    friend class DeathNotifier;
+
+    static  Mutex               mServiceLock;
+    static  sp<IMediaPlayerService>    mMediaPlayerService;
+};
+
+}; // namespace android
+
+#endif // ANDROID_MEDIAPLAYER_H
+
diff --git a/include/media/mediarecorder.h b/include/media/mediarecorder.h
new file mode 100644
index 0000000..f247424
--- /dev/null
+++ b/include/media/mediarecorder.h
@@ -0,0 +1,120 @@
+/*
+ * 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 MEDIARECORDER_H
+#define MEDIARECORDER_H
+
+#include <utils.h>
+#include <ui/SurfaceComposerClient.h>
+
+namespace android {
+
+class AuthorDriverWrapper;
+
+typedef void (*media_completion_f)(status_t status, void *cookie);
+
+/* Do not change these values without updating their counterparts
+ * in java/android/android/media/MediaRecorder.java!
+ */
+enum audio_source {
+    AUDIO_SOURCE_DEFAULT = 0,
+    AUDIO_SOURCE_MIC = 1, 
+};
+
+enum video_source {
+    VIDEO_SOURCE_DEFAULT = 0,
+    VIDEO_SOURCE_CAMERA = 1,
+};
+
+enum output_format {
+    OUTPUT_FORMAT_DEFAULT = 0,
+    OUTPUT_FORMAT_THREE_GPP = 1,
+    OUTPUT_FORMAT_MPEG_4 = 2,
+};
+
+enum audio_encoder {
+    AUDIO_ENCODER_DEFAULT = 0,
+    AUDIO_ENCODER_AMR_NB = 1,
+};
+
+enum video_encoder {
+    VIDEO_ENCODER_DEFAULT = 0,
+    VIDEO_ENCODER_H263 = 1,
+    VIDEO_ENCODER_H264 = 2,
+    VIDEO_ENCODER_MPEG_4_SP = 3,
+};
+
+/*
+ * 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_PREPARING
+ *    MEDIA_RECORDER_PREPARED              INITIALIZED
+ *    MEDIA_RECORDER_RECORDING             RECORDING
+ */
+enum media_recorder_states {
+    MEDIA_RECORDER_ERROR =         0,
+    MEDIA_RECORDER_IDLE =          1 << 0,
+    MEDIA_RECORDER_INITIALIZED =   1 << 1,
+    MEDIA_RECORDER_PREPARING =     1 << 2,
+    MEDIA_RECORDER_PREPARED =      1 << 3,
+    MEDIA_RECORDER_RECORDING =     1 << 4,
+};
+
+class MediaRecorder
+{
+public:
+    MediaRecorder();
+    ~MediaRecorder();
+
+    status_t init();
+
+    status_t setAudioSource(audio_source as);
+    status_t setVideoSource(video_source vs);
+    status_t setOutputFormat(output_format of);
+    status_t setAudioEncoder(audio_encoder ae);
+    status_t setVideoEncoder(video_encoder ve);
+    status_t setVideoSize(int width, int height);
+    status_t setVideoFrameRate(int frames_per_second);
+    status_t setPreviewSurface(const sp<Surface>& surface);
+
+    status_t setOutputFile(const char *path);
+    // XXX metadata setup
+
+    status_t prepare();
+    status_t start();
+    status_t stop();
+    status_t reset();
+    status_t getIfOutputFormatSpecified();
+
+    status_t getMaxAmplitude(int *max);
+
+private:
+    AuthorDriverWrapper            *mAuthorDriverWrapper;
+    bool                           mOutputFormatSpecified;
+    media_recorder_states          mCurrentState;
+
+};
+
+}; // namespace android
+
+#endif // MEDIAPLAYER_H
+
diff --git a/include/media/mediascanner.h b/include/media/mediascanner.h
new file mode 100644
index 0000000..5d0122d
--- /dev/null
+++ b/include/media/mediascanner.h
@@ -0,0 +1,63 @@
+/*
+ * 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 MEDIASCANNER_H
+#define MEDIASCANNER_H
+
+#include <utils.h>
+#include <pthread.h>
+
+namespace android {
+
+class MediaScannerClient;
+
+class MediaScanner 
+{
+public:
+    MediaScanner();
+    ~MediaScanner();
+    
+    typedef bool (*ExceptionCheck)(void* env);
+
+    status_t processFile(const char *path, const char *mimeType, MediaScannerClient& client);
+    status_t processDirectory(const char *path, const char* extensions, 
+            MediaScannerClient& client, ExceptionCheck exceptionCheck, void* exceptionEnv);
+    
+    // extracts album art as a block of data
+    char* extractAlbumArt(int fd);
+    
+    static void uninitializeForThread();
+
+private:
+    status_t doProcessDirectory(char *path, int pathRemaining, const char* extensions, 
+            MediaScannerClient& client, ExceptionCheck exceptionCheck, void* exceptionEnv);
+    void initializeForThread();
+};
+
+
+class MediaScannerClient
+{
+public:
+	virtual ~MediaScannerClient() {}
+	virtual bool scanFile(const char* path, long long lastModified, long long fileSize) = 0;
+	virtual bool handleStringTag(const char* name, const char* value) = 0;
+	virtual bool setMimeType(const char* mimeType) = 0;
+};
+
+}; // namespace android
+
+#endif // MEDIASCANNER_H
+
diff --git a/include/media/thread_init.h b/include/media/thread_init.h
new file mode 100644
index 0000000..2c0c1f1
--- /dev/null
+++ b/include/media/thread_init.h
@@ -0,0 +1,25 @@
+/*
+ * 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 THREAD_INIT_H
+#define THREAD_INIT_H
+
+bool InitializeForThread();
+void UninitializeForThread();
+void keydestructor(void*);
+
+#endif /* THREAD_INIT_H*/
+	
diff --git a/include/private/media/AudioTrackShared.h b/include/private/media/AudioTrackShared.h
new file mode 100644
index 0000000..1878f3c
--- /dev/null
+++ b/include/private/media/AudioTrackShared.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2007 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_AUDIO_TRACK_SHARED_H
+#define ANDROID_AUDIO_TRACK_SHARED_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/threads.h>
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+#define MAX_SAMPLE_RATE     65535
+#define THREAD_PRIORITY_AUDIO_CLIENT (ANDROID_PRIORITY_AUDIO)
+
+struct audio_track_cblk_t
+{
+    enum {
+        SEQUENCE_MASK   = 0xFFFFFF00,
+        BUFFER_MASK     = 0x000000FF
+    };
+
+                Mutex       lock;
+                Condition   cv;
+    volatile    uint32_t    user;
+    volatile    uint32_t    server;
+    volatile    union {
+                    uint16_t    volume[2];
+                    uint32_t    volumeLR;
+                };
+                uint16_t    sampleRate;
+                uint16_t    reserved;
+
+                void*       buffers;
+                size_t      size;
+            
+                            audio_track_cblk_t();
+                uint32_t    stepUser(int bufferCount);
+                bool        stepServer(int bufferCount);
+                void*       buffer(int id) const;
+};
+
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_AUDIO_TRACK_SHARED_H
diff --git a/include/private/opengles/gl_context.h b/include/private/opengles/gl_context.h
new file mode 100644
index 0000000..67d50fd
--- /dev/null
+++ b/include/private/opengles/gl_context.h
@@ -0,0 +1,624 @@
+/*
+ * Copyright (C) 2006 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_OPENGLES_CONTEXT_H
+#define ANDROID_OPENGLES_CONTEXT_H
+
+#include <stdint.h>
+#include <stddef.h>
+#include <sys/types.h>
+#include <pthread.h>
+#ifdef HAVE_ANDROID_OS
+#include <sys/tls.h>
+#endif
+
+#include <private/pixelflinger/ggl_context.h>
+
+#include <GLES/gl.h>
+
+namespace android {
+
+const unsigned int OGLES_NUM_COMPRESSED_TEXTURE_FORMATS = 10;
+
+class EGLTextureObject;
+class EGLSurfaceManager;
+class EGLBufferObjectManager;
+
+namespace gl {
+ 
+struct ogles_context_t;
+struct matrixx_t;
+struct transform_t;
+struct buffer_t;
+
+ogles_context_t* getGlContext();
+
+template<typename T>
+static inline void swap(T& a, T& b) {
+    T t(a); a = b; b = t;
+}
+template<typename T>
+inline T max(T a, T b) {
+    return a<b ? b : a;
+}
+template<typename T>
+inline T max(T a, T b, T c) {
+    return max(a, max(b, c));
+}
+template<typename T>
+inline T min(T a, T b) {
+    return a<b ? a : b;
+}
+template<typename T>
+inline T min(T a, T b, T c) {
+    return min(a, min(b, c));
+}
+template<typename T>
+inline T min(T a, T b, T c, T d) {
+    return min(min(a,b), min(c,d));
+}
+
+// ----------------------------------------------------------------------------
+// vertices
+// ----------------------------------------------------------------------------
+
+struct vec3_t {
+    union {
+        struct { GLfixed x, y, z; };
+        struct { GLfixed r, g, b; };
+        struct { GLfixed S, T, R; };
+        GLfixed v[3];
+    };
+};
+
+struct vec4_t {
+    union {
+        struct { GLfixed x, y, z, w; };
+        struct { GLfixed r, g, b, a; };
+        struct { GLfixed S, T, R, Q; };
+        GLfixed v[4];
+    };
+};
+
+struct vertex_t {
+    enum {
+        // these constant matter for our clipping 
+        CLIP_L          = 0x0001,   // clipping flags
+        CLIP_R          = 0x0002,
+        CLIP_B          = 0x0004,
+        CLIP_T          = 0x0008,
+        CLIP_N          = 0x0010,
+        CLIP_F          = 0x0020,
+
+        EYE             = 0x0040,
+        RESERVED        = 0x0080,
+        
+        USER_CLIP_0     = 0x0100,   // user clipping flags
+        USER_CLIP_1     = 0x0200,
+        USER_CLIP_2     = 0x0400,
+        USER_CLIP_3     = 0x0800,
+        USER_CLIP_4     = 0x1000,
+        USER_CLIP_5     = 0x2000,
+
+        LIT             = 0x4000,   // lighting has been applied
+        TT              = 0x8000,   // texture coords transformed
+
+        FRUSTUM_CLIP_ALL= 0x003F,
+        USER_CLIP_ALL   = 0x3F00,
+        CLIP_ALL        = 0x3F3F,
+    };
+    
+    // the fields below are arranged to minimize d-cache usage
+    // we group together, by cache-line, the fields most likely to be used
+
+    union {
+    vec4_t          obj;
+    vec4_t          eye;
+    };
+    vec4_t          clip;
+    
+    uint32_t        flags;
+    size_t          index;  // cache tag, and vertex index
+    GLfixed         fog;
+    uint8_t         locked;
+    uint8_t         mru;
+    uint8_t         reserved[2];
+    vec4_t          window;
+
+    vec4_t          color;
+    vec4_t          texture[GGL_TEXTURE_UNIT_COUNT];
+    uint32_t        reserved1[4];
+    
+    inline void clear() {
+        flags = index = locked = mru = 0;
+    }
+};
+
+struct point_size_t {
+    GGLcoord    size;
+    GLboolean   smooth;
+};
+
+struct line_width_t {
+    GGLcoord    width;
+    GLboolean   smooth;
+};
+
+struct polygon_offset_t {
+    GLfixed     factor;
+    GLfixed     units;
+    GLboolean   enable;
+};
+
+// ----------------------------------------------------------------------------
+// arrays
+// ----------------------------------------------------------------------------
+
+struct array_t {
+    typedef void (*fetcher_t)(ogles_context_t*, GLfixed*, const GLvoid*);
+    fetcher_t       fetch;
+    GLvoid const*   physical_pointer;
+    GLint           size;
+    GLsizei         stride;
+    GLvoid const*   pointer;
+    buffer_t const* bo;
+    uint16_t        type;
+    GLboolean       enable;
+    GLboolean       pad;
+    GLsizei         bounds;
+    void init(GLint, GLenum, GLsizei, const GLvoid *, const buffer_t*, GLsizei);
+    inline void resolve();
+    inline const GLubyte* element(GLint i) const {
+        return (const GLubyte*)physical_pointer + i * stride;
+    }
+};
+
+struct array_machine_t {
+    array_t         vertex;
+    array_t         normal;
+    array_t         color;
+    array_t         texture[GGL_TEXTURE_UNIT_COUNT];
+    uint8_t         activeTexture;
+    uint8_t         tmu;
+    uint16_t        cull;
+    uint32_t        flags;
+    GLenum          indicesType;
+    buffer_t const* array_buffer;
+    buffer_t const* element_array_buffer;
+    
+    void (*compileElements)(ogles_context_t*, vertex_t*, GLint, GLsizei);
+    void (*compileElement)(ogles_context_t*, vertex_t*, GLint);
+
+    void (*mvp_transform)(transform_t const*, vec4_t*, vec4_t const*);
+    void (*mv_transform)(transform_t const*, vec4_t*, vec4_t const*);
+    void (*tex_transform[2])(transform_t const*, vec4_t*, vec4_t const*);
+    void (*perspective)(ogles_context_t*c, vertex_t* v);
+    void (*clipVertex)(ogles_context_t* c, vertex_t* nv,
+            GGLfixed t, const vertex_t* s, const vertex_t* p);
+    void (*clipEye)(ogles_context_t* c, vertex_t* nv,
+            GGLfixed t, const vertex_t* s, const vertex_t* p);
+};
+
+struct vertex_cache_t {
+    enum {
+        // must be at least 4
+        // 3 vertice for triangles
+        // or 2 + 2 for indexed triangles w/ cache contention
+        VERTEX_BUFFER_SIZE  = 8,
+        // must be a power of two and at least 3
+        VERTEX_CACHE_SIZE   = 64,   // 8 KB
+
+        INDEX_BITS      = 16,
+        INDEX_MASK      = ((1LU<<INDEX_BITS)-1),
+        INDEX_SEQ       = 1LU<<INDEX_BITS,
+    };
+    vertex_t*       vBuffer;
+    vertex_t*       vCache;
+    uint32_t        sequence;
+    void*           base;
+    uint32_t        total;
+    uint32_t        misses;
+    int64_t         startTime;
+    void init();
+    void uninit();
+    void clear();
+    void dump_stats(GLenum mode);
+};
+
+// ----------------------------------------------------------------------------
+// fog
+// ----------------------------------------------------------------------------
+
+struct fog_t {
+    GLfixed     density;
+    GLfixed     start;
+    GLfixed     end;
+    GLfixed     invEndMinusStart;
+    GLenum      mode;
+    GLfixed     (*fog)(ogles_context_t* c, GLfixed z);
+};
+
+// ----------------------------------------------------------------------------
+// user clip planes
+// ----------------------------------------------------------------------------
+
+const unsigned int OGLES_MAX_CLIP_PLANES = 6;
+
+struct clip_plane_t {
+    vec4_t      equation;
+};
+
+struct user_clip_planes_t {
+    clip_plane_t    plane[OGLES_MAX_CLIP_PLANES];
+    uint32_t        enable;
+};
+
+// ----------------------------------------------------------------------------
+// lighting
+// ----------------------------------------------------------------------------
+
+const unsigned int OGLES_MAX_LIGHTS = 8;
+
+struct light_t {
+    vec4_t      ambient;
+    vec4_t      diffuse;
+    vec4_t      specular;
+    vec4_t      implicitAmbient;
+    vec4_t      implicitDiffuse;
+    vec4_t      implicitSpecular;
+    vec4_t      position;       // position in eye space
+    vec4_t      objPosition;
+    vec4_t      normalizedObjPosition;
+    vec4_t      spotDir;
+    vec4_t      normalizedSpotDir;
+    GLfixed     spotExp;
+    GLfixed     spotCutoff;
+    GLfixed     spotCutoffCosine;
+    GLfixed     attenuation[3];
+    GLfixed     rConstAttenuation;
+    GLboolean   enable;
+};
+
+struct material_t {
+    vec4_t      ambient;
+    vec4_t      diffuse;
+    vec4_t      specular;
+    vec4_t      emission;
+    GLfixed     shininess;
+};
+
+struct light_model_t {
+    vec4_t      ambient;
+    GLboolean   twoSide;
+};
+
+struct color_material_t {
+    GLenum      face;
+    GLenum      mode;
+    GLboolean   enable;
+};
+
+struct lighting_t {
+    light_t             lights[OGLES_MAX_LIGHTS];
+    material_t          front;
+    light_model_t       lightModel;
+    color_material_t    colorMaterial;
+    uint32_t            enabledLights;
+    GLboolean           enable;
+    vec4_t              implicitSceneEmissionAndAmbient;
+    GLenum              shadeModel;
+    typedef void (*light_fct_t)(ogles_context_t*, vertex_t*);
+    void (*lightVertex)(ogles_context_t* c, vertex_t* v);
+    void (*lightTriangle)(ogles_context_t* c,
+            vertex_t* v0, vertex_t* v1, vertex_t* v2);
+};
+
+struct culling_t {
+    GLenum      cullFace;
+    GLenum      frontFace;
+    GLboolean   enable;
+};
+
+// ----------------------------------------------------------------------------
+// textures
+// ----------------------------------------------------------------------------
+
+struct texture_unit_t {
+    GLuint              name;
+    EGLTextureObject*   texture;
+    uint8_t             dirty;
+};
+
+struct texture_state_t
+{
+    texture_unit_t      tmu[GGL_TEXTURE_UNIT_COUNT];
+    int                 active;     // active tmu
+    EGLTextureObject*   defaultTexture;
+    GGLContext*         ggl;
+    uint8_t             packAlignment;
+    uint8_t             unpackAlignment;
+};
+
+// ----------------------------------------------------------------------------
+// transformation and matrices
+// ----------------------------------------------------------------------------
+
+struct matrixf_t;
+
+struct matrixx_t {
+    GLfixed m[16];
+    void load(const matrixf_t& rhs);
+};
+
+struct matrix_stack_t;
+
+
+struct matrixf_t {
+    void loadIdentity();
+    void load(const matrixf_t& rhs);
+
+    inline GLfloat* editElements() { return m; }
+    inline GLfloat const* elements() const { return m; }
+
+    void set(const GLfixed* rhs);
+    void set(const GLfloat* rhs);
+
+    static void multiply(matrixf_t& r,
+            const matrixf_t& lhs, const matrixf_t& rhs);
+
+    void dump(const char* what);
+
+private:
+    friend struct matrix_stack_t;
+    GLfloat     m[16];
+    void load(const GLfixed* rhs);
+    void load(const GLfloat* rhs);
+    void multiply(const matrixf_t& rhs);
+    void translate(GLfloat x, GLfloat y, GLfloat z);
+    void scale(GLfloat x, GLfloat y, GLfloat z);
+    void rotate(GLfloat a, GLfloat x, GLfloat y, GLfloat z);
+};
+
+enum {
+    OP_IDENTITY         = 0x00,
+    OP_TRANSLATE        = 0x01,
+    OP_UNIFORM_SCALE    = 0x02,
+    OP_SCALE            = 0x05,
+    OP_ROTATE           = 0x08,
+    OP_SKEW             = 0x10,
+    OP_ALL              = 0x1F
+};
+
+struct transform_t {
+    enum {
+        FLAGS_2D_PROJECTION = 0x1
+    };
+    matrixx_t       matrix;
+    uint32_t        flags;
+    uint32_t        ops;
+    
+    union {
+        struct {
+            void (*point2)(transform_t const* t, vec4_t*, vec4_t const*);
+            void (*point3)(transform_t const* t, vec4_t*, vec4_t const*);
+            void (*point4)(transform_t const* t, vec4_t*, vec4_t const*);
+        };
+        void (*pointv[3])(transform_t const* t, vec4_t*, vec4_t const*);
+    };
+
+    void loadIdentity();
+    void picker();
+    void dump(const char* what);
+};
+
+struct mvui_transform_t : public transform_t
+{
+    void picker();
+};
+
+struct matrix_stack_t {
+    enum {
+        DO_PICKER           = 0x1,
+        DO_FLOAT_TO_FIXED   = 0x2
+    };
+    transform_t     transform;
+    uint8_t         maxDepth;
+    uint8_t         depth;
+    uint8_t         dirty;
+    uint8_t         reserved;
+    matrixf_t       *stack;
+    uint8_t         *ops;
+    void init(int depth);
+    void uninit();
+    void loadIdentity();
+    void load(const GLfixed* rhs);
+    void load(const GLfloat* rhs);
+    void multiply(const matrixf_t& rhs);
+    void translate(GLfloat x, GLfloat y, GLfloat z);
+    void scale(GLfloat x, GLfloat y, GLfloat z);
+    void rotate(GLfloat a, GLfloat x, GLfloat y, GLfloat z);
+    GLint push();
+    GLint pop();
+    void validate();
+    matrixf_t& top() { return stack[depth]; }
+    const matrixf_t& top() const { return stack[depth]; }
+    const uint32_t top_ops() const { return ops[depth]; }
+    inline bool isRigidBody() const {
+        return !(ops[depth] & ~(OP_TRANSLATE|OP_UNIFORM_SCALE|OP_ROTATE));
+    }
+};
+
+struct vp_transform_t {
+    transform_t     transform;
+    matrixf_t       matrix;
+    GLfloat         zNear;
+    GLfloat         zFar;
+    void loadIdentity();
+};
+
+struct transform_state_t {
+    enum {
+        MODELVIEW           = 0x01,
+        PROJECTION          = 0x02,
+        VIEWPORT            = 0x04,
+        TEXTURE             = 0x08,
+        MVUI                = 0x10,
+        MVIT                = 0x20,
+        MVP                 = 0x40,
+    };
+    matrix_stack_t      *current;
+    matrix_stack_t      modelview;
+    matrix_stack_t      projection;
+    matrix_stack_t      texture[GGL_TEXTURE_UNIT_COUNT];
+
+    // modelview * projection
+    transform_t         mvp     __attribute__((aligned(32)));
+    // viewport transformation
+    vp_transform_t      vpt     __attribute__((aligned(32)));
+    // same for 4-D vertices
+    transform_t         mvp4;
+    // full modelview inverse transpose
+    transform_t         mvit4;
+    // upper 3x3 of mv-inverse-transpose (for normals)
+    mvui_transform_t    mvui;
+
+    GLenum              matrixMode;
+    GLenum              rescaleNormals;
+    uint32_t            dirty;
+    void invalidate();
+    void update_mvp();
+    void update_mvit();
+    void update_mvui();
+};
+
+struct viewport_t {
+    GLint       x;
+    GLint       y;
+    GLsizei     w;
+    GLsizei     h; 
+    struct {
+        GLint       x;
+        GLint       y;
+    } surfaceport;  
+    struct {
+        GLint       x;
+        GLint       y;
+        GLsizei     w;
+        GLsizei     h; 
+    } scissor;  
+};
+
+// ----------------------------------------------------------------------------
+// Lerping
+// ----------------------------------------------------------------------------
+
+struct compute_iterators_t
+{
+    void initTriangle(
+            vertex_t const* v0,
+            vertex_t const* v1,
+            vertex_t const* v2);
+
+    inline void initLerp(vertex_t const* v0, uint32_t enables);
+
+    int iteratorsScale(int32_t it[3],
+            int32_t c0, int32_t c1, int32_t c2) const;
+
+    void iterators1616(GGLfixed it[3],
+            GGLfixed c0, GGLfixed c1, GGLfixed c2) const;
+
+    void iterators0032(int32_t it[3],
+            int32_t c0, int32_t c1, int32_t c2) const;
+
+    GGLcoord area() const { return m_area; }
+
+private:
+    // don't change order of members here -- used by iterators.S
+    GGLcoord m_dx01, m_dy10, m_dx20, m_dy02;
+    GGLcoord m_x0, m_y0;
+    GGLcoord m_area;
+    uint8_t m_scale;
+    uint8_t m_area_scale;
+    uint8_t m_reserved[2];
+
+};
+
+// ----------------------------------------------------------------------------
+// state
+// ----------------------------------------------------------------------------
+
+#ifdef HAVE_ANDROID_OS
+    // We have a dedicated TLS slot in bionic
+    inline void setGlThreadSpecific(ogles_context_t *value) {
+        ((uint32_t *)__get_tls())[TLS_SLOT_OPENGL] = (uint32_t)value;
+    }
+    inline ogles_context_t* getGlThreadSpecific() {
+        return (ogles_context_t *)(((unsigned *)__get_tls())[TLS_SLOT_OPENGL]);
+    }
+#else
+    extern pthread_key_t gGLKey;
+    inline void setGlThreadSpecific(ogles_context_t *value) {
+        pthread_setspecific(gGLKey, value);
+    }
+    inline ogles_context_t* getGlThreadSpecific() {
+        return static_cast<ogles_context_t*>(pthread_getspecific(gGLKey));
+    }
+#endif
+
+
+struct prims_t {
+    typedef ogles_context_t* GL;
+    void (*renderPoint)(GL, vertex_t*);
+    void (*renderLine)(GL, vertex_t*, vertex_t*);
+    void (*renderTriangle)(GL, vertex_t*, vertex_t*, vertex_t*);
+};
+
+struct ogles_context_t {
+    context_t               rasterizer;
+    array_machine_t         arrays         __attribute__((aligned(32)));
+    texture_state_t         textures;
+    transform_state_t       transforms;
+    vertex_cache_t          vc;
+    prims_t                 prims;
+    culling_t               cull;
+    lighting_t              lighting;
+    user_clip_planes_t      clipPlanes;
+    compute_iterators_t     lerp;           __attribute__((aligned(32)));
+    vertex_t                current;
+    vec4_t                  currentColorClamped;
+    vec3_t                  currentNormal;
+    viewport_t              viewport;
+    point_size_t            point;
+    line_width_t            line;
+    polygon_offset_t        polygonOffset;
+    fog_t                   fog;
+    uint32_t                perspective : 1;
+    uint32_t                transformTextures : 1;
+    EGLSurfaceManager*      surfaceManager;
+    EGLBufferObjectManager* bufferObjectManager;
+    GLenum                  error;
+
+    static inline ogles_context_t* get() {
+        return getGlThreadSpecific();
+    }
+
+};
+
+}; // namespace gl
+}; // namespace android
+
+#endif // ANDROID_OPENGLES_CONTEXT_H
+
diff --git a/include/private/ui/LayerState.h b/include/private/ui/LayerState.h
new file mode 100644
index 0000000..b6fcd80
--- /dev/null
+++ b/include/private/ui/LayerState.h
@@ -0,0 +1,75 @@
+/*
+ * 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_COMPOSER_LAYER_STATE_H
+#define ANDROID_COMPOSER_LAYER_STATE_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/Errors.h>
+
+#include <ui/ISurfaceFlingerClient.h>
+#include <ui/Region.h>
+
+#include <private/ui/SharedState.h>
+
+namespace android {
+
+class Parcel;
+
+struct layer_state_t {
+
+    layer_state_t()
+        :   surface(0), what(0),
+            x(0), y(0), z(0), w(0), h(0),
+            alpha(0), tint(0), flags(0), mask(0),
+            reserved(0)
+    {
+        matrix.dsdx = matrix.dtdy = 1.0f;
+        matrix.dsdy = matrix.dtdx = 0.0f;
+    }
+
+    status_t    write(Parcel& output) const;
+    status_t    read(const Parcel& input);
+
+            struct matrix22_t {
+                float   dsdx;
+                float   dtdx;
+                float   dsdy;
+                float   dtdy;
+            };
+            SurfaceID       surface;
+            uint32_t        what;
+            int32_t         x;
+            int32_t         y;
+            uint32_t        z;
+            uint32_t        w;
+            uint32_t        h;
+            float           alpha;
+            uint32_t        tint;
+            uint8_t         flags;
+            uint8_t         mask;
+            uint8_t         reserved;
+            matrix22_t      matrix;
+            // non POD must be last. see write/read
+            Region          transparentRegion;
+};
+
+}; // namespace android
+
+#endif // ANDROID_COMPOSER_LAYER_STATE_H
+
diff --git a/include/private/ui/SharedState.h b/include/private/ui/SharedState.h
new file mode 100644
index 0000000..546d0ad
--- /dev/null
+++ b/include/private/ui/SharedState.h
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2007 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_UI_SHARED_STATE_H
+#define ANDROID_UI_SHARED_STATE_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/threads.h>
+
+namespace android {
+
+/*
+ * These structures are shared between the composer process and its clients
+ */
+
+// ---------------------------------------------------------------------------
+
+struct surface_info_t { // 4 longs, 16 bytes
+    enum {
+        eBufferDirty    = 0x01
+    };
+    uint16_t    w;
+    uint16_t    h;
+    uint16_t    stride;
+    uint16_t    bpr;
+    uint16_t    reserved;
+    uint8_t     format;
+    uint8_t     flags;
+    ssize_t     bits_offset;
+};
+
+// ---------------------------------------------------------------------------
+
+const uint32_t NUM_LAYERS_MAX = 31;
+
+enum { // layer_cblk_t swapState
+    eIndex              = 0x00000001,
+    eFlipRequested      = 0x00000002,
+    
+    eResizeBuffer0      = 0x00000004,
+    eResizeBuffer1      = 0x00000008,    
+    eResizeRequested    = eResizeBuffer0 | eResizeBuffer1,
+    
+    eBusy               = 0x00000010,
+    eLocked             = 0x00000020,
+    eNextFlipPending    = 0x00000040,    
+    eInvalidSurface     = 0x00000080
+};
+
+enum { // layer_cblk_t flags
+    eLayerNotPosted     = 0x00000001,
+    eNoCopyBack         = 0x00000002,
+    eReserved           = 0x0000007C,
+    eBufferIndexShift   = 7,
+    eBufferIndex        = 1<<eBufferIndexShift,
+};
+
+struct flat_region_t    // 40 bytes
+{
+    int32_t     count;
+    int16_t     l;
+    int16_t     t;
+    int16_t     r;
+    int16_t     b;
+    uint16_t    runs[14];
+};
+
+struct layer_cblk_t     // (128 bytes)
+{
+    volatile    int32_t             swapState;      //  4
+    volatile    int32_t             flags;          //  4
+    volatile    int32_t             identity;       //  4
+                int32_t             reserved;       //  4
+                surface_info_t      surface[2];     // 32
+                flat_region_t       region[2];      // 80
+
+    static inline int backBuffer(uint32_t state) {
+        return ((state & eIndex) ^ ((state & eFlipRequested)>>1));
+    }
+    static inline int frontBuffer(uint32_t state) {
+        return 1 - backBuffer(state);
+    }
+};
+
+// ---------------------------------------------------------------------------
+
+struct per_client_cblk_t   // 4KB max
+{
+                Mutex           lock;
+                Condition       cv;
+                layer_cblk_t    layers[NUM_LAYERS_MAX] __attribute__((aligned(32)));
+
+    enum {
+        BLOCKING = 0x00000001,
+        INSPECT  = 0x00000002
+    };
+
+    per_client_cblk_t();
+
+    // these functions are used by the clients
+    status_t validate(size_t i) const;
+    int32_t lock_layer(size_t i, uint32_t flags);
+    uint32_t unlock_layer_and_post(size_t i);
+    void unlock_layer(size_t i);
+};
+// ---------------------------------------------------------------------------
+
+const uint32_t NUM_DISPLAY_MAX = 4;
+
+struct display_cblk_t
+{
+    uint16_t    w;
+    uint16_t    h;
+    uint8_t     format;
+    uint8_t     orientation;
+    uint8_t     reserved[2];
+    float       fps;
+    float       density;
+    float       xdpi;
+    float       ydpi;
+    uint32_t    pad[2];
+};
+
+struct surface_flinger_cblk_t   // 4KB max
+{
+    surface_flinger_cblk_t();
+    
+    uint8_t         connected;
+    uint8_t         reserved[3];
+    uint32_t        pad[7];
+ 
+    display_cblk_t  displays[NUM_DISPLAY_MAX];
+};
+
+// ---------------------------------------------------------------------------
+
+template<bool> struct CTA;
+template<> struct CTA<true> { };
+
+// compile-time assertions. just to avoid catastrophes.
+inline void compile_time_asserts() {
+    CTA<sizeof(layer_cblk_t) == 128> sizeof__layer_cblk_t__eq_128;
+    (void)sizeof__layer_cblk_t__eq_128; // we don't want a warning
+    CTA<sizeof(per_client_cblk_t) <= 4096> sizeof__per_client_cblk_t__le_4096;
+    (void)sizeof__per_client_cblk_t__le_4096;  // we don't want a warning
+    CTA<sizeof(surface_flinger_cblk_t) <= 4096> sizeof__surface_flinger_cblk_t__le_4096;
+    (void)sizeof__surface_flinger_cblk_t__le_4096;  // we don't want a warning
+}
+
+}; // namespace android
+
+#endif // ANDROID_UI_SHARED_STATE_H
+
diff --git a/include/private/ui/SurfaceFlingerSynchro.h b/include/private/ui/SurfaceFlingerSynchro.h
new file mode 100644
index 0000000..ff91b61
--- /dev/null
+++ b/include/private/ui/SurfaceFlingerSynchro.h
@@ -0,0 +1,76 @@
+/*
+ * 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_SURFACE_FLINGER_SYNCHRO_H
+#define ANDROID_SURFACE_FLINGER_SYNCHRO_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <utils/Errors.h>
+#include <utils/threads.h>
+#include <ui/ISurfaceComposer.h>
+
+namespace android {
+
+class SurfaceFlinger;
+
+class SurfaceFlingerSynchro
+{
+public:
+
+                // client constructor
+                SurfaceFlingerSynchro(const sp<ISurfaceComposer>& flinger);
+                ~SurfaceFlingerSynchro();
+    
+                // signal surfaceflinger for some work
+    status_t    signal();
+    
+private:
+    class Barrier {
+    public:
+        Barrier();
+        ~Barrier();
+        void open();
+        void close();
+        void waitAndClose();
+        status_t waitAndClose(nsecs_t timeout);
+    private:
+        enum { OPENED, CLOSED };
+        mutable     Mutex       lock;
+        mutable     Condition   cv;
+        volatile    int         state;
+    };
+
+    friend class SurfaceFlinger;
+
+                // server constructor
+                SurfaceFlingerSynchro();
+                
+    void        open();
+    
+                // wait until there is some work to do
+    status_t    wait();
+    status_t    wait(nsecs_t timeout);
+    
+    sp<ISurfaceComposer> mSurfaceComposer;
+    Barrier              mBarrier;
+};
+
+}; // namespace android
+
+#endif // ANDROID_SURFACE_FLINGER_SYNCHRO_H
+
diff --git a/include/private/utils/Static.h b/include/private/utils/Static.h
new file mode 100644
index 0000000..f1439b7
--- /dev/null
+++ b/include/private/utils/Static.h
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+// All static variables go here, to control initialization and
+// destruction order in the library.
+
+#include <utils/threads.h>
+#include <utils/KeyedVector.h>
+
+#ifndef LIBUTILS_NATIVE
+#include <utils/IBinder.h>
+#include <utils/IMemory.h>
+#include <utils/ProcessState.h>
+#include <utils/IPermissionController.h>
+#include <utils/IServiceManager.h>
+#endif
+
+namespace android {
+// For TextStream.cpp
+extern Vector<int32_t> gTextBuffers;
+
+// For String8.cpp
+extern void initialize_string8();
+extern void terminate_string8();
+
+// For String16.cpp
+extern void initialize_string16();
+extern void terminate_string16();
+
+
+
+#ifndef LIBUTILS_NATIVE
+
+// For ProcessState.cpp
+extern Mutex gProcessMutex;
+extern sp<ProcessState> gProcess;
+
+// For ServiceManager.cpp
+extern Mutex gDefaultServiceManagerLock;
+extern sp<IServiceManager> gDefaultServiceManager;
+extern sp<IPermissionController> gPermissionController;
+
+#endif
+
+}   // namespace android
diff --git a/include/private/utils/binder_module.h b/include/private/utils/binder_module.h
new file mode 100644
index 0000000..fdf327e
--- /dev/null
+++ b/include/private/utils/binder_module.h
@@ -0,0 +1,148 @@
+/*
+ * 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 _BINDER_MODULE_H_
+#define _BINDER_MODULE_H_
+
+#ifdef __cplusplus
+namespace android {
+#endif
+
+#if defined(HAVE_ANDROID_OS)
+
+/* obtain structures and constants from the kernel header */
+
+#include <sys/ioctl.h>
+#include <linux/binder.h>
+
+#else
+
+/* Some parts of the simulator need fake versions of this 
+ * stuff in order to compile.  Really this should go away
+ * entirely...
+ */
+
+#define BINDER_CURRENT_PROTOCOL_VERSION 7
+
+#define BINDER_TYPE_BINDER 1
+#define BINDER_TYPE_WEAK_BINDER 2
+#define BINDER_TYPE_HANDLE 3
+#define BINDER_TYPE_WEAK_HANDLE 4
+#define BINDER_TYPE_FD 5
+
+struct flat_binder_object {
+    unsigned long type;
+    unsigned long flags;
+    union {
+        void *binder;
+        signed long handle;
+    };
+    void *cookie;
+};
+
+struct binder_write_read {
+    signed long write_size;
+    signed long write_consumed;
+    unsigned long write_buffer;
+    signed long read_size;
+    signed long read_consumed;
+    unsigned long read_buffer;
+};
+
+struct binder_transaction_data {
+    union {
+        size_t handle;
+        void *ptr;
+    } target;
+    void *cookie;
+    unsigned int code;
+    
+    unsigned int flags;
+    pid_t sender_pid;
+    uid_t sender_euid;
+    size_t data_size;
+    size_t offsets_size;
+    
+    union {
+        struct {
+            const void *buffer;
+            const void *offsets;
+        } ptr;
+        uint8_t buf[8];
+    } data;
+};
+
+enum transaction_flags {
+    TF_ONE_WAY = 0x01,
+    TF_ROOT_OBJECT = 0x04,
+    TF_STATUS_CODE = 0x08,
+    TF_ACCEPT_FDS = 0x10,
+};
+
+
+enum {
+    FLAT_BINDER_FLAG_PRIORITY_MASK = 0xff,
+    FLAT_BINDER_FLAG_ACCEPTS_FDS = 0x100,
+};
+
+enum BinderDriverReturnProtocol {
+    BR_ERROR,
+    BR_OK,
+    BR_TRANSACTION,
+    BR_REPLY,
+    BR_ACQUIRE_RESULT,
+    BR_DEAD_REPLY,
+    BR_TRANSACTION_COMPLETE,
+    BR_INCREFS,
+    BR_ACQUIRE,
+    BR_RELEASE,
+    BR_DECREFS,
+    BR_ATTEMPT_ACQUIRE,
+    BR_NOOP,
+    BR_SPAWN_LOOPER,
+    BR_FINISHED,
+    BR_DEAD_BINDER,
+    BR_CLEAR_DEATH_NOTIFICATION_DONE,
+    BR_FAILED_REPLY,
+};
+
+enum BinderDriverCommandProtocol {
+    BC_TRANSACTION,
+    BC_REPLY,
+    BC_ACQUIRE_RESULT,
+    BC_FREE_BUFFER,
+    BC_INCREFS,
+    BC_ACQUIRE,
+    BC_RELEASE,
+    BC_DECREFS,
+    BC_INCREFS_DONE,
+    BC_ACQUIRE_DONE,
+    BC_ATTEMPT_ACQUIRE,
+    BC_REGISTER_LOOPER,
+    BC_ENTER_LOOPER,
+    BC_EXIT_LOOPER,
+    BC_REQUEST_DEATH_NOTIFICATION,
+    BC_CLEAR_DEATH_NOTIFICATION,
+    BC_DEAD_BINDER_DONE,
+};
+
+#endif
+
+#ifdef __cplusplus
+}   // namespace android
+#endif
+
+#endif // _BINDER_MODULE_H_
diff --git a/include/private/utils/futex_synchro.h b/include/private/utils/futex_synchro.h
new file mode 100644
index 0000000..ac2ab19
--- /dev/null
+++ b/include/private/utils/futex_synchro.h
@@ -0,0 +1,60 @@
+/*
+ * 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 _FUTEX_SYNCHRO_H
+#define _FUTEX_SYNCHRO_H
+
+#ifndef HAVE_FUTEX
+#error "HAVE_FUTEX not defined"
+#endif
+
+#define FUTEX_WAIT_INFINITE (0)
+
+typedef struct futex_mutex_t futex_mutex_t;
+
+struct futex_mutex_t 
+{
+    volatile int value;
+};
+
+typedef struct futex_cond_t futex_cond_t;
+
+struct futex_cond_t 
+{
+    volatile int value;
+};
+
+
+#if __cplusplus
+extern "C" {
+#endif
+
+void futex_mutex_init(futex_mutex_t *m);
+int futex_mutex_lock(futex_mutex_t *m, unsigned msec);
+void futex_mutex_unlock(futex_mutex_t *m);
+int futex_mutex_trylock(futex_mutex_t *m);
+
+void futex_cond_init(futex_cond_t *c);
+int futex_cond_wait(futex_cond_t *c, futex_mutex_t *m, unsigned msec);
+void futex_cond_signal(futex_cond_t *c);
+void futex_cond_broadcast(futex_cond_t *c);
+
+#if __cplusplus
+} // extern "C"
+#endif
+
+#endif // _FUTEX_SYNCHRO_H
+
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk
new file mode 100644
index 0000000..cfa837a
--- /dev/null
+++ b/media/libmedia/Android.mk
@@ -0,0 +1,34 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+	AudioTrack.cpp \
+	IAudioFlinger.cpp \
+	IAudioTrack.cpp \
+	IAudioRecord.cpp \
+	AudioRecord.cpp \
+	AudioSystem.cpp \
+	mediaplayer.cpp \
+	IMediaPlayerService.cpp \
+	IMediaPlayerClient.cpp \
+	IMediaPlayer.cpp \
+	mediametadataretriever.cpp \
+	ToneGenerator.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+	libui libcutils libutils
+
+LOCAL_MODULE:= libmedia
+
+ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true)
+LOCAL_LDLIBS += -ldl
+endif
+
+ifneq ($(TARGET_SIMULATOR),true)
+LOCAL_SHARED_LIBRARIES += libdl
+endif
+
+LOCAL_C_INCLUDES := \
+	$(call include-path-for, graphics corecg)
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
new file mode 100644
index 0000000..f3e4123
--- /dev/null
+++ b/media/libmedia/AudioRecord.cpp
@@ -0,0 +1,397 @@
+/*
+**
+** Copyright 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_TAG "AudioRecord"
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <sched.h>
+#include <sys/resource.h>
+
+#include <private/media/AudioTrackShared.h>
+
+#include <media/AudioSystem.h>
+#include <media/AudioRecord.h>
+
+#include <utils/IServiceManager.h>
+#include <utils/Log.h>
+#include <utils/MemoryDealer.h>
+#include <utils/Parcel.h>
+#include <utils/IPCThreadState.h>
+#include <utils/Timers.h>
+#include <cutils/atomic.h>
+
+#define LIKELY( exp )       (__builtin_expect( (exp) != 0, true  ))
+#define UNLIKELY( exp )     (__builtin_expect( (exp) != 0, false ))
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+AudioRecord::AudioRecord()
+    : mStatus(NO_INIT)
+{
+}
+
+AudioRecord::AudioRecord(
+        int streamType,
+        uint32_t sampleRate,
+        int format,
+        int channelCount,
+        int bufferCount,
+        uint32_t flags,
+        callback_t cbf, void* user)
+    : mStatus(NO_INIT)
+{
+    mStatus = set(streamType, sampleRate, format, channelCount,
+            bufferCount, flags, cbf, user);
+}
+
+AudioRecord::~AudioRecord()
+{
+    if (mStatus == NO_ERROR) {
+        if (mPosition) {
+            releaseBuffer(&mAudioBuffer);
+        }
+        // obtainBuffer() will give up with an error
+        mAudioRecord->stop();
+        if (mClientRecordThread != 0) {
+            mClientRecordThread->requestExitAndWait();
+            mClientRecordThread.clear();
+        }
+        mAudioRecord.clear();
+        IPCThreadState::self()->flushCommands();
+    }
+}
+
+status_t AudioRecord::set(
+        int streamType,
+        uint32_t sampleRate,
+        int format,
+        int channelCount,
+        int bufferCount,
+        uint32_t flags,
+        callback_t cbf, void* user)
+{
+
+    if (mAudioFlinger != 0) {
+        return INVALID_OPERATION;
+    }
+
+    const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
+    if (audioFlinger == 0) {
+        return NO_INIT;
+    }
+
+    if (streamType == DEFAULT_INPUT) {
+        streamType = MIC_INPUT;
+    }
+
+    if (sampleRate == 0) {
+        sampleRate = DEFAULT_SAMPLE_RATE;
+    }
+    // these below should probably come from the audioFlinger too...
+    if (format == 0) {
+        format = AudioSystem::PCM_16_BIT;
+    }
+    if (channelCount == 0) {
+        channelCount = 1;
+    }
+    if (bufferCount == 0) {
+        bufferCount = 2;
+    } else if (bufferCount < 2) {
+        return BAD_VALUE;
+    }
+
+    // validate parameters
+    if (format != AudioSystem::PCM_16_BIT) {
+        return BAD_VALUE;
+    }
+    if (channelCount != 1 && channelCount != 2) {
+        return BAD_VALUE;
+    }
+    if (bufferCount < 2) {
+        return BAD_VALUE;
+    }
+
+    // open record channel
+    sp<IAudioRecord> record = audioFlinger->openRecord(getpid(), streamType,
+            sampleRate, format, channelCount, bufferCount, flags);
+    if (record == 0) {
+        return NO_INIT;
+    }
+    sp<IMemory> cblk = record->getCblk();
+    if (cblk == 0) {
+        return NO_INIT;
+    }
+    if (cbf != 0) {
+        mClientRecordThread = new ClientRecordThread(*this);
+        if (mClientRecordThread == 0) {
+            return NO_INIT;
+        }
+    }
+
+    mStatus = NO_ERROR;
+
+    mAudioFlinger = audioFlinger;
+    mAudioRecord = record;
+    mCblkMemory = cblk;
+    mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer());
+    mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
+    mSampleRate = sampleRate;
+    mFrameCount = audioFlinger->frameCount();
+    mFormat = format;
+    mBufferCount = bufferCount;
+    mChannelCount = channelCount;
+    mActive = 0;
+    mCbf = cbf;
+    mUserData = user;
+    mLatency = seconds(mFrameCount) / mSampleRate;
+    mPosition = 0;
+    return NO_ERROR;
+}
+
+status_t AudioRecord::initCheck() const
+{
+    return mStatus;
+}
+
+// -------------------------------------------------------------------------
+
+nsecs_t AudioRecord::latency() const
+{
+    return mLatency;
+}
+
+uint32_t AudioRecord::sampleRate() const
+{
+    return mSampleRate;
+}
+
+int AudioRecord::format() const
+{
+    return mFormat;
+}
+
+int AudioRecord::channelCount() const
+{
+    return mChannelCount;
+}
+
+int AudioRecord::bufferCount() const
+{
+    return mBufferCount;
+}
+
+// -------------------------------------------------------------------------
+
+status_t AudioRecord::start()
+{
+    status_t ret = NO_ERROR;
+    
+    // If using record thread, protect start sequence to make sure that
+    // no stop command is processed before the thread is started
+    if (mClientRecordThread != 0) {
+        mRecordThreadLock.lock();        
+    }
+
+    if (android_atomic_or(1, &mActive) == 0) {
+        setpriority(PRIO_PROCESS, 0, THREAD_PRIORITY_AUDIO_CLIENT);
+        ret = mAudioRecord->start();
+        if (ret == NO_ERROR) {
+            if (mClientRecordThread != 0) {
+                mClientRecordThread->run("ClientRecordThread", THREAD_PRIORITY_AUDIO_CLIENT);
+            }
+        }
+    }
+    
+    if (mClientRecordThread != 0) {
+        mRecordThreadLock.unlock();        
+    }
+    
+    return ret;
+}
+
+status_t AudioRecord::stop()
+{
+    // If using record thread, protect stop sequence to make sure that
+    // no start command is processed before requestExit() is called
+    if (mClientRecordThread != 0) {
+        mRecordThreadLock.lock();        
+    }
+
+    if (android_atomic_and(~1, &mActive) == 1) {
+        if (mPosition) {
+            mPosition = 0;
+            releaseBuffer(&mAudioBuffer);
+        }
+        mAudioRecord->stop();
+        setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_NORMAL);
+        if (mClientRecordThread != 0) {
+            mClientRecordThread->requestExit();
+        }
+    }
+    
+    if (mClientRecordThread != 0) {
+        mRecordThreadLock.unlock();        
+    }
+    
+    return NO_ERROR;
+}
+
+bool AudioRecord::stopped() const
+{
+    return !mActive;
+}
+
+// -------------------------------------------------------------------------
+
+status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, bool blocking)
+{
+    int active = mActive;
+    int timeout = 0;
+    status_t result;
+    audio_track_cblk_t* cblk = mCblk;
+
+    const uint32_t u = cblk->user;
+    uint32_t s = cblk->server;
+
+    if (u == s) {
+        Mutex::Autolock _l(cblk->lock);
+        goto start_loop_here;
+        while (u == s) {
+            active = mActive;
+            if (UNLIKELY(!active))
+                return NO_MORE_BUFFERS;
+            if (UNLIKELY(!blocking))
+                return WOULD_BLOCK;
+            timeout = 0;
+            result = cblk->cv.waitRelative(cblk->lock, seconds(1));
+            if (__builtin_expect(result!=NO_ERROR, false)) {
+                LOGW(   "obtainBuffer timed out (is the CPU pegged?) "
+                        "user=%08x, server=%08x", u, s);
+                timeout = 1;
+            }
+            // read the server count again
+        start_loop_here:
+            s = cblk->server;
+        }
+    }
+
+    LOGW_IF(timeout,
+        "*** SERIOUS WARNING *** obtainBuffer() timed out "
+        "but didn't need to be locked. We recovered, but "
+        "this shouldn't happen (user=%08x, server=%08x)", u, s);
+
+    audioBuffer->flags       = 0;
+    audioBuffer->channelCount= mChannelCount;
+    audioBuffer->format      = mFormat;
+    audioBuffer->frameCount  = mFrameCount;
+    audioBuffer->size        = cblk->size;
+    audioBuffer->raw         = (int8_t*)
+            cblk->buffer(cblk->user & audio_track_cblk_t::BUFFER_MASK);
+    return active ? status_t(NO_ERROR) : status_t(STOPPED);
+}
+
+void AudioRecord::releaseBuffer(Buffer* audioBuffer)
+{
+    // next buffer...
+    if (UNLIKELY(mPosition)) {
+        // clean the remaining part of the buffer
+        size_t capacity = mAudioBuffer.size - mPosition;
+        memset(mAudioBuffer.i8 + mPosition, 0, capacity);
+    }
+    audio_track_cblk_t* cblk = mCblk;
+    cblk->stepUser(mBufferCount);
+}
+
+// -------------------------------------------------------------------------
+
+ssize_t AudioRecord::read(void* buffer, size_t userSize)
+{
+    ssize_t read = 0;
+    do {
+        if (mPosition == 0) {
+            status_t err = obtainBuffer(&mAudioBuffer, true);
+            if (err < 0) {
+                // out of buffers, return #bytes written
+                if (err == status_t(NO_MORE_BUFFERS))
+                    break;
+                return ssize_t(err);
+            }
+        }
+
+        size_t capacity = mAudioBuffer.size - mPosition;
+        size_t toRead = userSize < capacity ? userSize : capacity;
+
+        memcpy(buffer, mAudioBuffer.i8 + mPosition, toRead);
+
+        buffer = static_cast<int8_t*>(buffer) + toRead;
+        mPosition += toRead;
+        userSize -= toRead;
+        capacity -= toRead;
+        read += toRead;
+
+        if (capacity == 0) {
+            mPosition = 0;
+            releaseBuffer(&mAudioBuffer);
+        }
+    } while (userSize);
+
+    return read;
+}
+
+// -------------------------------------------------------------------------
+
+bool AudioRecord::processAudioBuffer(const sp<ClientRecordThread>& thread)
+{
+    Buffer audioBuffer;
+    bool more;
+
+    do {
+        status_t err = obtainBuffer(&audioBuffer, true); 
+        if (err < NO_ERROR) {
+            LOGE("Error obtaining an audio buffer, giving up.");
+            return false;
+        }
+        more = mCbf(mUserData, audioBuffer);
+        releaseBuffer(&audioBuffer);
+    } while (more && !thread->exitPending());
+
+    // stop the track automatically
+    this->stop();
+
+    return true;
+}
+
+// =========================================================================
+
+AudioRecord::ClientRecordThread::ClientRecordThread(AudioRecord& receiver)
+    : Thread(false), mReceiver(receiver)
+{
+}
+
+bool AudioRecord::ClientRecordThread::threadLoop()
+{
+    return mReceiver.processAudioBuffer(this);
+}
+
+// -------------------------------------------------------------------------
+
+}; // namespace android
+
diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp
new file mode 100644
index 0000000..22de463
--- /dev/null
+++ b/media/libmedia/AudioSystem.cpp
@@ -0,0 +1,255 @@
+/*
+ * Copyright (C) 2006-2007 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_TAG "AudioSystem"
+#include <utils/Log.h>
+#include <utils/IServiceManager.h>
+#include <media/AudioSystem.h>
+#include <media/AudioTrack.h>
+#include <math.h>
+
+namespace android {
+
+// client singleton for AudioFlinger binder interface
+Mutex AudioSystem::gLock;
+sp<IAudioFlinger> AudioSystem::gAudioFlinger;
+sp<AudioSystem::DeathNotifier> AudioSystem::gDeathNotifier;
+audio_error_callback AudioSystem::gAudioErrorCallback = NULL;
+
+// establish binder interface to AudioFlinger service
+const sp<IAudioFlinger>& AudioSystem::get_audio_flinger()
+{
+    Mutex::Autolock _l(gLock);
+    if (gAudioFlinger.get() == 0) {
+        sp<IServiceManager> sm = defaultServiceManager();
+        sp<IBinder> binder;
+        do {
+            binder = sm->getService(String16("media.audio_flinger"));
+            if (binder != 0)
+                break;
+            LOGW("AudioFlinger not published, waiting...");
+            usleep(500000); // 0.5 s
+        } while(true);
+        if (gDeathNotifier == NULL) {
+            gDeathNotifier = new DeathNotifier();
+        } else {
+            if (gAudioErrorCallback) {
+                gAudioErrorCallback(NO_ERROR);               
+            }
+         }
+        binder->linkToDeath(gDeathNotifier);
+        gAudioFlinger = interface_cast<IAudioFlinger>(binder);
+    }
+    LOGE_IF(gAudioFlinger==0, "no AudioFlinger!?");
+    return gAudioFlinger;
+}
+
+// routing helper functions
+status_t AudioSystem::speakerphone(bool state) {
+    uint32_t routes = state ? ROUTE_SPEAKER : ROUTE_EARPIECE;
+    return setRouting(MODE_IN_CALL, routes, ROUTE_ALL);
+}
+
+status_t AudioSystem::isSpeakerphoneOn(bool* state) {
+    uint32_t routes = 0;
+    status_t s = getRouting(MODE_IN_CALL, &routes);
+    *state = !!(routes & ROUTE_SPEAKER);
+    return s;
+}
+
+status_t AudioSystem::bluetoothSco(bool state) {
+    uint32_t mask = ROUTE_BLUETOOTH;
+    uint32_t routes = state ? mask : ROUTE_EARPIECE;
+    return setRouting(MODE_IN_CALL, routes, ROUTE_ALL);
+}
+
+status_t AudioSystem::isBluetoothScoOn(bool* state) {
+    uint32_t routes = 0;
+    status_t s = getRouting(MODE_IN_CALL, &routes);
+    *state = !!(routes & ROUTE_BLUETOOTH);
+    return s;
+}
+
+status_t AudioSystem::muteMicrophone(bool state) {
+    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+    if (af == 0) return PERMISSION_DENIED;
+    return af->setMicMute(state);
+}
+
+status_t AudioSystem::isMicrophoneMuted(bool* state) {
+    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+    if (af == 0) return PERMISSION_DENIED;
+    *state = af->getMicMute();
+    return NO_ERROR;
+}
+
+status_t AudioSystem::setMasterVolume(float value)
+{
+    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+    if (af == 0) return PERMISSION_DENIED;
+    af->setMasterVolume(value);
+    return NO_ERROR;
+}
+
+status_t AudioSystem::setMasterMute(bool mute)
+{
+    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+    if (af == 0) return PERMISSION_DENIED;
+    af->setMasterMute(mute);
+    return NO_ERROR;
+}
+
+status_t AudioSystem::getMasterVolume(float* volume)
+{
+    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+    if (af == 0) return PERMISSION_DENIED;
+    *volume = af->masterVolume();
+    return NO_ERROR;
+}
+
+status_t AudioSystem::getMasterMute(bool* mute)
+{
+    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+    if (af == 0) return PERMISSION_DENIED;
+    *mute = af->masterMute();
+    return NO_ERROR;
+}
+
+status_t AudioSystem::setStreamVolume(int stream, float value)
+{
+    if (uint32_t(stream) >= AudioTrack::NUM_STREAM_TYPES) return BAD_VALUE;
+    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+    if (af == 0) return PERMISSION_DENIED;
+    af->setStreamVolume(stream, value);
+    return NO_ERROR;
+}
+
+status_t AudioSystem::setStreamMute(int stream, bool mute)
+{
+    if (uint32_t(stream) >= AudioTrack::NUM_STREAM_TYPES) return BAD_VALUE;
+    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+    if (af == 0) return PERMISSION_DENIED;
+    af->setStreamMute(stream, mute);
+    return NO_ERROR;
+}
+
+status_t AudioSystem::getStreamVolume(int stream, float* volume)
+{
+    if (uint32_t(stream) >= AudioTrack::NUM_STREAM_TYPES) return BAD_VALUE;
+    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+    if (af == 0) return PERMISSION_DENIED;
+    *volume = af->streamVolume(stream);
+    return NO_ERROR;
+}
+
+status_t AudioSystem::getStreamMute(int stream, bool* mute)
+{
+    if (uint32_t(stream) >= AudioTrack::NUM_STREAM_TYPES) return BAD_VALUE;
+    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+    if (af == 0) return PERMISSION_DENIED;
+    *mute = af->streamMute(stream);
+    return NO_ERROR;
+}
+
+status_t AudioSystem::setMode(int mode)
+{
+    if (mode >= NUM_MODES) return BAD_VALUE;
+    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+    if (af == 0) return PERMISSION_DENIED;
+    return af->setMode(mode);
+}
+
+status_t AudioSystem::getMode(int* mode)
+{
+    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+    if (af == 0) return PERMISSION_DENIED;
+    *mode = af->getMode();
+    return NO_ERROR;
+}
+
+status_t AudioSystem::setRouting(int mode, uint32_t routes, uint32_t mask)
+{
+    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+    if (af == 0) return PERMISSION_DENIED;
+    return af->setRouting(mode, routes, mask);
+}
+
+status_t AudioSystem::getRouting(int mode, uint32_t* routes)
+{
+    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+    if (af == 0) return PERMISSION_DENIED;
+    uint32_t r = af->getRouting(mode);
+    *routes = r;
+    return NO_ERROR;
+}
+
+status_t AudioSystem::isMusicActive(bool* state) {
+    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+    if (af == 0) return PERMISSION_DENIED;
+    *state = af->isMusicActive();
+    return NO_ERROR;
+}
+
+// Temporary interface, do not use
+// TODO: Replace with a more generic key:value get/set mechanism
+status_t AudioSystem::setParameter(const char* key, const char* value) {
+    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+    if (af == 0) return PERMISSION_DENIED;
+    return af->setParameter(key, value);
+}
+
+// convert volume steps to natural log scale
+
+// change this value to change volume scaling
+static const float dBPerStep = 0.5f;
+// shouldn't need to touch these
+static const float dBConvert = -dBPerStep * 2.302585093f / 20.0f;
+static const float dBConvertInverse = 1.0f / dBConvert;
+
+float AudioSystem::linearToLog(int volume)
+{
+    // float v = volume ? exp(float(100 - volume) * dBConvert) : 0;
+    // LOGD("linearToLog(%d)=%f", volume, v);
+    // return v;
+    return volume ? exp(float(100 - volume) * dBConvert) : 0;
+}
+
+int AudioSystem::logToLinear(float volume)
+{
+    // int v = volume ? 100 - int(dBConvertInverse * log(volume) + 0.5) : 0;
+    // LOGD("logTolinear(%d)=%f", v, volume);
+    // return v;
+    return volume ? 100 - int(dBConvertInverse * log(volume) + 0.5) : 0;
+}
+
+// ---------------------------------------------------------------------------
+
+void AudioSystem::DeathNotifier::binderDied(const wp<IBinder>& who) {    
+    Mutex::Autolock _l(AudioSystem::gLock);
+    AudioSystem::gAudioFlinger.clear();
+    if (gAudioErrorCallback) {
+        gAudioErrorCallback(DEAD_OBJECT);
+    }
+    LOGW("AudioFlinger server died!");
+}
+
+void AudioSystem::setErrorCallback(audio_error_callback cb) {
+    Mutex::Autolock _l(AudioSystem::gLock);
+    gAudioErrorCallback = cb;
+}
+
+}; // namespace android
+
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
new file mode 100644
index 0000000..298170a
--- /dev/null
+++ b/media/libmedia/AudioTrack.cpp
@@ -0,0 +1,596 @@
+/* //device/extlibs/pv/android/AudioTrack.cpp
+**
+** Copyright 2007, 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 "AudioTrack"
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <sched.h>
+#include <sys/resource.h>
+
+#include <private/media/AudioTrackShared.h>
+
+#include <media/AudioSystem.h>
+#include <media/AudioTrack.h>
+
+#include <utils/Log.h>
+#include <utils/MemoryDealer.h>
+#include <utils/Parcel.h>
+#include <utils/IPCThreadState.h>
+#include <utils/Timers.h>
+#include <cutils/atomic.h>
+
+#define LIKELY( exp )       (__builtin_expect( (exp) != 0, true  ))
+#define UNLIKELY( exp )     (__builtin_expect( (exp) != 0, false ))
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+static volatile size_t gFrameCount = 0;
+
+size_t AudioTrack::frameCount()
+{
+    if (gFrameCount) return gFrameCount;
+    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+    if (af == 0) return PERMISSION_DENIED;
+    gFrameCount = af->frameCount();
+    return gFrameCount;
+}
+
+// ---------------------------------------------------------------------------
+
+AudioTrack::AudioTrack()
+    : mStatus(NO_INIT)
+{
+}
+
+AudioTrack::AudioTrack(
+        int streamType,
+        uint32_t sampleRate,
+        int format,
+        int channelCount,
+        int bufferCount,
+        uint32_t flags,
+        callback_t cbf, void* user)
+    : mStatus(NO_INIT)
+{
+    mStatus = set(streamType, sampleRate, format, channelCount,
+            bufferCount, flags, cbf, user);
+}
+
+AudioTrack::~AudioTrack()
+{
+    if (mStatus == NO_ERROR) {
+        if (mPosition) {
+            releaseBuffer(&mAudioBuffer);
+        }
+        // obtainBuffer() will give up with an error
+        mAudioTrack->stop();
+        if (mAudioTrackThread != 0) {
+            mAudioTrackThread->requestExitAndWait();
+            mAudioTrackThread.clear();
+        }
+        mAudioTrack.clear();
+        IPCThreadState::self()->flushCommands();
+    }
+}
+
+status_t AudioTrack::set(
+        int streamType,
+        uint32_t sampleRate,
+        int format,
+        int channelCount,
+        int bufferCount,
+        uint32_t flags,
+        callback_t cbf, void* user)
+{
+
+    if (mAudioFlinger != 0) {
+        LOGE("Track already in use");
+        return INVALID_OPERATION;
+    }
+
+    const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
+    if (audioFlinger == 0) {
+       LOGE("Could not get audioflinger");
+       return NO_INIT;
+    }
+
+    // handle default values first.
+    if (streamType == DEFAULT) {
+        streamType = MUSIC;
+    }
+    if (sampleRate == 0) {
+        sampleRate = audioFlinger->sampleRate();
+    }
+    // these below should probably come from the audioFlinger too...
+    if (format == 0) {
+        format = AudioSystem::PCM_16_BIT;
+    }
+    if (channelCount == 0) {
+        channelCount = 2;
+    }
+    if (bufferCount == 0) {
+        bufferCount = 2;
+    }
+
+    // validate parameters
+    if (format != AudioSystem::PCM_16_BIT) {
+        LOGE("Invalid format");
+        return BAD_VALUE;
+    }
+    if (channelCount != 1 && channelCount != 2) {
+        LOGE("Invalid channel number");
+        return BAD_VALUE;
+    }
+    if (bufferCount < 2) {
+       LOGE("Invalid buffer count");
+       return BAD_VALUE;
+    }
+
+    // create the track
+    sp<IAudioTrack> track = audioFlinger->createTrack(getpid(),
+            streamType, sampleRate, format, channelCount, bufferCount, flags);
+    if (track == 0) {
+        LOGE("AudioFlinger could not create track");
+        return NO_INIT;
+    }
+    sp<IMemory> cblk = track->getCblk();
+    if (cblk == 0) {
+        LOGE("Could not get control block");
+        return NO_INIT;
+    }
+    if (cbf != 0) {
+        mAudioTrackThread = new AudioTrackThread(*this);
+        if (mAudioTrackThread == 0) {
+          LOGE("Could not create callback thread");
+          return NO_INIT;
+        }
+    }
+
+    mStatus = NO_ERROR;
+
+    mAudioFlinger = audioFlinger;
+    mAudioTrack = track;
+    mCblkMemory = cblk;
+    mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer());
+    mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
+    mCblk->volume[0] = mCblk->volume[1] = 0x1000;
+    mVolume[LEFT] = 1.0f;
+    mVolume[RIGHT] = 1.0f;
+    mSampleRate = sampleRate;
+    mFrameCount = audioFlinger->frameCount();
+    mStreamType = streamType;
+    mFormat = format;
+    mBufferCount = bufferCount;
+    mChannelCount = channelCount;
+    mMuted = false;
+    mActive = 0;
+    mReserved = 0;
+    mCbf = cbf;
+    mUserData = user;
+    mLatency = seconds(mFrameCount) / mSampleRate;
+    mPosition = 0;
+    return NO_ERROR;
+}
+
+status_t AudioTrack::initCheck() const
+{
+    return mStatus;
+}
+
+// -------------------------------------------------------------------------
+
+nsecs_t AudioTrack::latency() const
+{
+    return mLatency;
+}
+
+int AudioTrack::streamType() const
+{
+    return mStreamType;
+}
+
+uint32_t AudioTrack::sampleRate() const
+{
+    return mSampleRate;
+}
+
+int AudioTrack::format() const
+{
+    return mFormat;
+}
+
+int AudioTrack::channelCount() const
+{
+    return mChannelCount;
+}
+
+int AudioTrack::bufferCount() const
+{
+    return mBufferCount;
+}
+
+// -------------------------------------------------------------------------
+
+void AudioTrack::start()
+{
+    sp<AudioTrackThread> t = mAudioTrackThread;
+
+    LOGV("start");
+    if (t != 0) {
+        if (t->exitPending()) {
+            if (t->requestExitAndWait() == WOULD_BLOCK) {
+                LOGE("AudioTrack::start called from thread");
+                return;
+            }
+        }
+        t->mLock.lock();
+     }
+
+    if (android_atomic_or(1, &mActive) == 0) {
+        if (t != 0) {
+           t->run("AudioTrackThread", THREAD_PRIORITY_AUDIO_CLIENT);
+        } else {
+            setpriority(PRIO_PROCESS, 0, THREAD_PRIORITY_AUDIO_CLIENT);
+        }
+        mAudioTrack->start();
+    }
+
+    if (t != 0) {
+        t->mLock.unlock();
+    }
+}
+
+void AudioTrack::stop()
+{
+    sp<AudioTrackThread> t = mAudioTrackThread;
+
+    LOGV("stop");
+    if (t != 0) {
+        t->mLock.lock();
+    }
+
+    if (android_atomic_and(~1, &mActive) == 1) {
+        if (mPosition) {
+            releaseBuffer(&mAudioBuffer);
+        }
+        mAudioTrack->stop();
+       if (t != 0) {
+           t->requestExit();
+       } else {
+           setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_NORMAL);
+       }
+    }
+
+    if (t != 0) {
+        t->mLock.unlock();
+    }
+}
+
+bool AudioTrack::stopped() const
+{
+    return !mActive;
+}
+
+void AudioTrack::flush()
+{
+    LOGV("flush");
+    if (!mActive) {
+        mCblk->lock.lock();
+        mAudioTrack->flush();
+        // Release AudioTrack callback thread in case it was waiting for new buffers
+        // in AudioTrack::obtainBuffer()
+        mCblk->cv.signal();
+        mCblk->lock.unlock();
+    }
+}
+
+void AudioTrack::pause()
+{
+    LOGV("pause");
+    if (android_atomic_and(~1, &mActive) == 1) {
+        mActive = 0;
+        mAudioTrack->pause();
+    }
+}
+
+void AudioTrack::mute(bool e)
+{
+    mAudioTrack->mute(e);
+    mMuted = e;
+}
+
+bool AudioTrack::muted() const
+{
+    return mMuted;
+}
+
+void AudioTrack::setVolume(float left, float right)
+{
+    mVolume[LEFT] = left;
+    mVolume[RIGHT] = right;
+
+    // write must be atomic
+    mCblk->volumeLR = (int32_t(int16_t(left * 0x1000)) << 16) | int16_t(right * 0x1000);
+}
+
+void AudioTrack::getVolume(float* left, float* right)
+{
+    *left  = mVolume[LEFT];
+    *right = mVolume[RIGHT];
+}
+
+void AudioTrack::setSampleRate(int rate)
+{
+    if (rate > MAX_SAMPLE_RATE) rate = MAX_SAMPLE_RATE;
+    mCblk->sampleRate = rate;
+}
+
+uint32_t AudioTrack::getSampleRate()
+{
+    return uint32_t(mCblk->sampleRate);
+}
+
+// -------------------------------------------------------------------------
+
+status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, bool blocking)
+{
+    int active;
+    int timeout = 0;
+    status_t result;
+    audio_track_cblk_t* cblk = mCblk;
+
+    uint32_t u = cblk->user;
+    uint32_t u_seq = u & audio_track_cblk_t::SEQUENCE_MASK;
+    uint32_t u_buf = u & audio_track_cblk_t::BUFFER_MASK;
+
+    uint32_t s = cblk->server;
+    uint32_t s_seq = s & audio_track_cblk_t::SEQUENCE_MASK;
+    uint32_t s_buf = s & audio_track_cblk_t::BUFFER_MASK;
+
+    LOGW_IF(u_seq < s_seq, "user doesn't fill buffers fast enough");
+
+    if (u_seq > s_seq && u_buf == s_buf) {
+        Mutex::Autolock _l(cblk->lock);
+        goto start_loop_here;
+        while (u_seq > s_seq && u_buf == s_buf) {
+            active = mActive;
+            if (UNLIKELY(!active)) {
+                LOGV("Not active and NO_MORE_BUFFERS");
+                return NO_MORE_BUFFERS;
+            }
+            if (UNLIKELY(!blocking))
+                return WOULD_BLOCK;
+            timeout = 0;
+            result = cblk->cv.waitRelative(cblk->lock, seconds(1));
+            if (__builtin_expect(result!=NO_ERROR, false)) {
+                LOGW(   "obtainBuffer timed out (is the CPU pegged?) "
+                        "user=%08x, server=%08x", u, s);
+                mAudioTrack->start(); // FIXME: Wake up audioflinger
+                timeout = 1;
+            }
+            // Read user count in case a flush has reset while we where waiting on cv.
+            u = cblk->user;
+            u_seq = u & audio_track_cblk_t::SEQUENCE_MASK;
+            u_buf = u & audio_track_cblk_t::BUFFER_MASK;
+
+            // read the server count again
+        start_loop_here:
+            s = cblk->server;
+            s_seq = s & audio_track_cblk_t::SEQUENCE_MASK;
+            s_buf = s & audio_track_cblk_t::BUFFER_MASK;
+        }
+    }
+
+    LOGW_IF(timeout,
+        "*** SERIOUS WARNING *** obtainBuffer() timed out "
+        "but didn't need to be locked. We recovered, but "
+        "this shouldn't happen (user=%08x, server=%08x)", u, s);
+
+    audioBuffer->flags       = mMuted ? Buffer::MUTE : 0;
+    audioBuffer->channelCount= mChannelCount;
+    audioBuffer->format      = mFormat;
+    audioBuffer->frameCount  = mFrameCount;
+    audioBuffer->size        = cblk->size;
+    audioBuffer->raw         = (int8_t *)cblk->buffer(u_buf);
+    active = mActive;
+    return active ? status_t(NO_ERROR) : status_t(STOPPED);
+}
+
+void AudioTrack::releaseBuffer(Buffer* audioBuffer)
+{
+    // next buffer...
+    if (UNLIKELY(mPosition)) {
+        // clean the remaining part of the buffer
+        size_t capacity = mAudioBuffer.size - mPosition;
+        memset(mAudioBuffer.i8 + mPosition, 0, capacity);
+        mPosition = 0;
+    }
+    audio_track_cblk_t* cblk = mCblk;
+    cblk->stepUser(mBufferCount);
+}
+
+// -------------------------------------------------------------------------
+
+ssize_t AudioTrack::write(const void* buffer, size_t userSize)
+{
+    if (ssize_t(userSize) < 0) {
+        // sanity-check. user is most-likely passing an error code.
+        LOGE("AudioTrack::write(buffer=%p, size=%u (%d)", 
+                buffer, userSize, userSize);
+        return BAD_VALUE;
+    }
+
+    LOGV("write %d bytes, mActive=%d", userSize, mActive);
+    ssize_t written = 0;
+    do {
+        if (mPosition == 0) {
+            status_t err = obtainBuffer(&mAudioBuffer, true);
+            if (err < 0) {
+                // out of buffers, return #bytes written
+                if (err == status_t(NO_MORE_BUFFERS))
+                    break;
+                return ssize_t(err);
+            }
+        }
+
+        size_t capacity = mAudioBuffer.size - mPosition;
+        size_t toWrite = userSize < capacity ? userSize : capacity;
+
+        memcpy(mAudioBuffer.i8 + mPosition, buffer, toWrite);
+        buffer = static_cast<const int8_t*>(buffer) + toWrite;
+        mPosition += toWrite;
+        userSize -= toWrite;
+        capacity -= toWrite;
+        written += toWrite;
+
+        if (capacity == 0) {
+            mPosition = 0;
+            releaseBuffer(&mAudioBuffer);
+        }
+    } while (userSize);
+
+    return written;
+}
+
+// -------------------------------------------------------------------------
+
+bool AudioTrack::processAudioBuffer(const sp<AudioTrackThread>& thread)
+{
+    Buffer audioBuffer;
+
+    status_t err = obtainBuffer(&audioBuffer, true);
+    if (err < NO_ERROR) {
+        LOGE("Error obtaining an audio buffer, giving up.");
+        return false;
+    }
+    if (err == status_t(STOPPED)) return false;
+    mCbf(mUserData, audioBuffer);
+    releaseBuffer(&audioBuffer);
+
+    return true;
+}
+
+status_t AudioTrack::dump(int fd, const Vector<String16>& args) const
+{
+
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+
+    result.append(" AudioTrack::dump\n");
+    snprintf(buffer, 255, "  stream type(%d), left - right volume(%f, %f)\n", mStreamType, mVolume[0], mVolume[1]);
+    result.append(buffer);
+    snprintf(buffer, 255, "  format(%d), channel count(%d), frame count(%d), buffer count(%d)\n", mFormat, mChannelCount, mFrameCount, mBufferCount);
+    result.append(buffer);
+    snprintf(buffer, 255, "  sample rate(%d), status(%d), muted(%d), reserved(%d)\n", mSampleRate, mStatus, mMuted, mReserved);
+    result.append(buffer);
+    snprintf(buffer, 255, "  active(%d), latency (%lld), position(%d)\n", mActive, mLatency, mPosition);
+    result.append(buffer);
+    ::write(fd, result.string(), result.size());
+    return NO_ERROR;
+}
+
+// =========================================================================
+
+AudioTrack::AudioTrackThread::AudioTrackThread(AudioTrack& receiver)
+    : Thread(false), mReceiver(receiver)
+{
+}
+
+bool AudioTrack::AudioTrackThread::threadLoop()
+{
+    return mReceiver.processAudioBuffer(this);
+}
+
+status_t AudioTrack::AudioTrackThread::readyToRun()
+{
+    return NO_ERROR;
+}
+
+void AudioTrack::AudioTrackThread::onFirstRef()
+{
+}
+
+// =========================================================================
+
+audio_track_cblk_t::audio_track_cblk_t()
+    : user(0), server(0), volumeLR(0), buffers(0), size(0)
+{
+}
+
+uint32_t audio_track_cblk_t::stepUser(int bufferCount)
+{
+    uint32_t u = this->user;
+    uint32_t u_seq = u & audio_track_cblk_t::SEQUENCE_MASK;
+    uint32_t u_buf = u & audio_track_cblk_t::BUFFER_MASK;
+    if (++u_buf >= uint32_t(bufferCount)) {
+        u_seq += 0x100;
+        u_buf = 0;
+    }
+    u = u_seq | u_buf;
+    this->user = u; 
+    return u;
+}
+
+bool audio_track_cblk_t::stepServer(int bufferCount)
+{
+    // the code below simulates lock-with-timeout
+    // we MUST do this to protect the AudioFlinger server
+    // as this lock is shared with the client.
+    status_t err;
+
+    err = lock.tryLock();
+    if (err == -EBUSY) { // just wait a bit
+        usleep(1000);
+        err = lock.tryLock();
+    }
+    if (err != NO_ERROR) {
+        // probably, the client just died.
+        return false;
+    }
+
+    uint32_t s = this->server;
+    uint32_t s_seq = s & audio_track_cblk_t::SEQUENCE_MASK;
+    uint32_t s_buf = s & audio_track_cblk_t::BUFFER_MASK;
+    s_buf++;
+    if (s_buf >= uint32_t(bufferCount)) {
+        s_seq += 0x100;
+        s_buf = 0;
+    }
+    s = s_seq | s_buf;
+
+    this->server = s; 
+    cv.signal();
+    lock.unlock();
+    return true;
+}
+
+void* audio_track_cblk_t::buffer(int id) const
+{
+    return (char*)this->buffers + id * this->size;
+}
+
+// -------------------------------------------------------------------------
+
+}; // namespace android
+
diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp
new file mode 100644
index 0000000..474381b
--- /dev/null
+++ b/media/libmedia/IAudioFlinger.cpp
@@ -0,0 +1,450 @@
+/* //device/extlibs/pv/android/IAudioflinger.cpp
+**
+** Copyright 2007, 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_TAG "IAudioFlinger"
+#include <utils/Log.h>
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/Parcel.h>
+
+#include <media/IAudioFlinger.h>
+
+namespace android {
+
+enum {
+    CREATE_TRACK = IBinder::FIRST_CALL_TRANSACTION,
+    OPEN_RECORD,
+    SAMPLE_RATE,
+    CHANNEL_COUNT,
+    FORMAT,
+    FRAME_COUNT,
+    SET_MASTER_VOLUME,
+    SET_MASTER_MUTE,
+    MASTER_VOLUME,
+    MASTER_MUTE,
+    SET_STREAM_VOLUME,
+    SET_STREAM_MUTE,
+    STREAM_VOLUME,
+    STREAM_MUTE,
+    SET_MODE,
+    GET_MODE,
+    SET_ROUTING,
+    GET_ROUTING,
+    SET_MIC_MUTE,
+    GET_MIC_MUTE,
+    IS_MUSIC_ACTIVE,
+    SET_PARAMETER,
+};
+
+class BpAudioFlinger : public BpInterface<IAudioFlinger>
+{
+public:
+    BpAudioFlinger(const sp<IBinder>& impl)
+        : BpInterface<IAudioFlinger>(impl)
+    {
+    }
+
+    virtual sp<IAudioTrack> createTrack(
+                                pid_t pid,
+                                int streamType,
+                                uint32_t sampleRate,
+                                int format,
+                                int channelCount,
+                                int bufferCount,
+                                uint32_t flags)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        data.writeInt32(pid);
+        data.writeInt32(streamType);
+        data.writeInt32(sampleRate);
+        data.writeInt32(format);
+        data.writeInt32(channelCount);
+        data.writeInt32(bufferCount);
+        data.writeInt32(flags);
+        status_t status = remote()->transact(CREATE_TRACK, data, &reply);
+        if ( status != NO_ERROR) {
+            LOGE("createTrack error: %s", strerror(-status));
+        }
+        
+        return interface_cast<IAudioTrack>(reply.readStrongBinder());
+    }
+
+    virtual sp<IAudioRecord> openRecord(
+                                pid_t pid,
+                                int streamType,
+                                uint32_t sampleRate,
+                                int format,
+                                int channelCount,
+                                int bufferCount,
+                                uint32_t flags)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        data.writeInt32(pid);
+        data.writeInt32(streamType);
+        data.writeInt32(sampleRate);
+        data.writeInt32(format);
+        data.writeInt32(channelCount);
+        data.writeInt32(bufferCount);
+        data.writeInt32(flags);
+        remote()->transact(OPEN_RECORD, data, &reply);
+        return interface_cast<IAudioRecord>(reply.readStrongBinder());
+    }
+
+    virtual uint32_t sampleRate() const
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        remote()->transact(SAMPLE_RATE, data, &reply);
+        return reply.readInt32();
+    }
+
+    virtual int channelCount() const
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        remote()->transact(CHANNEL_COUNT, data, &reply);
+        return reply.readInt32();
+    }
+
+    virtual int format() const
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        remote()->transact(FORMAT, data, &reply);
+        return reply.readInt32();
+    }
+
+    virtual size_t frameCount() const
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        remote()->transact(FRAME_COUNT, data, &reply);
+        return reply.readInt32();
+    }
+
+    virtual status_t setMasterVolume(float value)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        data.writeFloat(value);
+        remote()->transact(SET_MASTER_VOLUME, data, &reply);
+        return reply.readInt32();
+    }
+
+    virtual status_t setMasterMute(bool muted)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        data.writeInt32(muted);
+        remote()->transact(SET_MASTER_MUTE, data, &reply);
+        return reply.readInt32();
+    }
+
+    virtual float masterVolume() const
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        remote()->transact(MASTER_VOLUME, data, &reply);
+        return reply.readFloat();
+    }
+
+    virtual bool masterMute() const
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        remote()->transact(MASTER_MUTE, data, &reply);
+        return reply.readInt32();
+    }
+
+    virtual status_t setStreamVolume(int stream, float value)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        data.writeInt32(stream);
+        data.writeFloat(value);
+        remote()->transact(SET_STREAM_VOLUME, data, &reply);
+        return reply.readInt32();
+    }
+
+    virtual status_t setStreamMute(int stream, bool muted)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        data.writeInt32(stream);
+        data.writeInt32(muted);
+        remote()->transact(SET_STREAM_MUTE, data, &reply);
+        return reply.readInt32();
+    }
+
+    virtual float streamVolume(int stream) const
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        data.writeInt32(stream);
+        remote()->transact(STREAM_VOLUME, data, &reply);
+        return reply.readFloat();
+    }
+
+    virtual bool streamMute(int stream) const
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        data.writeInt32(stream);
+        remote()->transact(STREAM_MUTE, data, &reply);
+        return reply.readInt32();
+    }
+
+    virtual status_t setRouting(int mode, uint32_t routes, uint32_t mask)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        data.writeInt32(mode);
+        data.writeInt32(routes);
+        data.writeInt32(mask);
+        remote()->transact(SET_ROUTING, data, &reply);
+        return reply.readInt32();
+    }
+
+    virtual uint32_t getRouting(int mode) const
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        data.writeInt32(mode);
+        remote()->transact(GET_ROUTING, data, &reply);
+        return reply.readInt32();
+    }
+
+    virtual status_t setMode(int mode)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        data.writeInt32(mode);
+        remote()->transact(SET_MODE, data, &reply);
+        return reply.readInt32();
+    }
+
+    virtual int getMode() const
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        remote()->transact(GET_MODE, data, &reply);
+        return reply.readInt32();
+    }
+
+    virtual status_t setMicMute(bool state)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        data.writeInt32(state);
+        remote()->transact(SET_MIC_MUTE, data, &reply);
+        return reply.readInt32();
+    }
+
+    virtual bool getMicMute() const
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        remote()->transact(GET_MIC_MUTE, data, &reply);
+        return reply.readInt32();
+    }
+
+    virtual bool isMusicActive() const
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        remote()->transact(IS_MUSIC_ACTIVE, data, &reply);
+        return reply.readInt32();
+    }
+
+    virtual status_t setParameter(const char* key, const char* value)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        data.writeCString(key);
+        data.writeCString(value);
+        remote()->transact(SET_PARAMETER, data, &reply);
+        return reply.readInt32();
+    }
+};
+
+IMPLEMENT_META_INTERFACE(AudioFlinger, "android.media.IAudioFlinger");
+
+// ----------------------------------------------------------------------
+
+#define CHECK_INTERFACE(interface, data, reply) \
+        do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \
+            LOGW("Call incorrectly routed to " #interface); \
+            return PERMISSION_DENIED; \
+        } } while (0)
+
+status_t BnAudioFlinger::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    switch(code) {
+        case CREATE_TRACK: {
+            CHECK_INTERFACE(IAudioFlinger, data, reply);
+            pid_t pid = data.readInt32();
+            int streamType = data.readInt32();
+            uint32_t sampleRate = data.readInt32();
+            int format = data.readInt32();
+            int channelCount = data.readInt32();
+            size_t bufferCount = data.readInt32();
+            uint32_t flags = data.readInt32();
+            sp<IAudioTrack> track = createTrack(pid, 
+                    streamType, sampleRate, format,
+                    channelCount, bufferCount, flags);
+            reply->writeStrongBinder(track->asBinder());
+            return NO_ERROR;
+        } break;
+        case OPEN_RECORD: {
+            CHECK_INTERFACE(IAudioFlinger, data, reply);
+            pid_t pid = data.readInt32();
+            int streamType = data.readInt32();
+            uint32_t sampleRate = data.readInt32();
+            int format = data.readInt32();
+            int channelCount = data.readInt32();
+            size_t bufferCount = data.readInt32();
+            uint32_t flags = data.readInt32();
+            sp<IAudioRecord> record = openRecord(pid, streamType,
+                    sampleRate, format, channelCount, bufferCount, flags);
+            reply->writeStrongBinder(record->asBinder());
+            return NO_ERROR;
+        } break;
+        case SAMPLE_RATE: {
+            CHECK_INTERFACE(IAudioFlinger, data, reply);
+            reply->writeInt32( sampleRate() );
+            return NO_ERROR;
+        } break;
+        case CHANNEL_COUNT: {
+            CHECK_INTERFACE(IAudioFlinger, data, reply);
+            reply->writeInt32( channelCount() );
+            return NO_ERROR;
+        } break;
+        case FORMAT: {
+            CHECK_INTERFACE(IAudioFlinger, data, reply);
+            reply->writeInt32( format() );
+            return NO_ERROR;
+        } break;
+        case FRAME_COUNT: {
+            CHECK_INTERFACE(IAudioFlinger, data, reply);
+            reply->writeInt32( frameCount() );
+            return NO_ERROR;
+        } break;
+        case SET_MASTER_VOLUME: {
+            CHECK_INTERFACE(IAudioFlinger, data, reply);
+            reply->writeInt32( setMasterVolume(data.readFloat()) );
+            return NO_ERROR;
+        } break;
+        case SET_MASTER_MUTE: {
+            CHECK_INTERFACE(IAudioFlinger, data, reply);
+            reply->writeInt32( setMasterMute(data.readInt32()) );
+            return NO_ERROR;
+        } break;
+        case MASTER_VOLUME: {
+            CHECK_INTERFACE(IAudioFlinger, data, reply);
+            reply->writeFloat( masterVolume() );
+            return NO_ERROR;
+        } break;
+        case MASTER_MUTE: {
+            CHECK_INTERFACE(IAudioFlinger, data, reply);
+            reply->writeInt32( masterMute() );
+            return NO_ERROR;
+        } break;
+        case SET_STREAM_VOLUME: {
+            CHECK_INTERFACE(IAudioFlinger, data, reply);
+            int stream = data.readInt32();
+            reply->writeInt32( setStreamVolume(stream, data.readFloat()) );
+            return NO_ERROR;
+        } break;
+        case SET_STREAM_MUTE: {
+            CHECK_INTERFACE(IAudioFlinger, data, reply);
+            int stream = data.readInt32();
+            reply->writeInt32( setStreamMute(stream, data.readInt32()) );
+            return NO_ERROR;
+        } break;
+        case STREAM_VOLUME: {
+            CHECK_INTERFACE(IAudioFlinger, data, reply);
+            int stream = data.readInt32();
+            reply->writeFloat( streamVolume(stream) );
+            return NO_ERROR;
+        } break;
+        case STREAM_MUTE: {
+            CHECK_INTERFACE(IAudioFlinger, data, reply);
+            int stream = data.readInt32();
+            reply->writeInt32( streamMute(stream) );
+            return NO_ERROR;
+        } break;
+        case SET_ROUTING: {
+            CHECK_INTERFACE(IAudioFlinger, data, reply);
+            int mode = data.readInt32();
+            uint32_t routes = data.readInt32();
+            uint32_t mask = data.readInt32();
+            reply->writeInt32( setRouting(mode, routes, mask) );
+            return NO_ERROR;
+        } break;
+        case GET_ROUTING: {
+            CHECK_INTERFACE(IAudioFlinger, data, reply);
+            int mode = data.readInt32();
+            reply->writeInt32( getRouting(mode) );
+            return NO_ERROR;
+        } break;
+        case SET_MODE: {
+            CHECK_INTERFACE(IAudioFlinger, data, reply);
+            int mode = data.readInt32();
+            reply->writeInt32( setMode(mode) );
+            return NO_ERROR;
+        } break;
+        case GET_MODE: {
+            CHECK_INTERFACE(IAudioFlinger, data, reply);
+            reply->writeInt32( getMode() );
+            return NO_ERROR;
+        } break;
+        case SET_MIC_MUTE: {
+            CHECK_INTERFACE(IAudioFlinger, data, reply);
+            int state = data.readInt32();
+            reply->writeInt32( setMicMute(state) );
+            return NO_ERROR;
+        } break;
+        case GET_MIC_MUTE: {
+            CHECK_INTERFACE(IAudioFlinger, data, reply);
+            reply->writeInt32( getMicMute() );
+            return NO_ERROR;
+        } break;
+        case IS_MUSIC_ACTIVE: {
+            CHECK_INTERFACE(IAudioFlinger, data, reply);
+            reply->writeInt32( isMusicActive() );
+            return NO_ERROR;
+        } break;
+        case SET_PARAMETER: {
+            CHECK_INTERFACE(IAudioFlinger, data, reply);
+            const char *key = data.readCString();
+            const char *value = data.readCString();
+            reply->writeInt32( setParameter(key, value) );
+            return NO_ERROR;
+        } break;
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
diff --git a/media/libmedia/IAudioRecord.cpp b/media/libmedia/IAudioRecord.cpp
new file mode 100644
index 0000000..6e42dac
--- /dev/null
+++ b/media/libmedia/IAudioRecord.cpp
@@ -0,0 +1,100 @@
+/*
+**
+** Copyright 2007, 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 <stdint.h>
+#include <sys/types.h>
+
+#include <utils/Parcel.h>
+
+#include <media/IAudioRecord.h>
+
+namespace android {
+
+enum {
+    GET_CBLK = IBinder::FIRST_CALL_TRANSACTION,
+    START,
+    STOP
+};
+
+class BpAudioRecord : public BpInterface<IAudioRecord>
+{
+public:
+    BpAudioRecord(const sp<IBinder>& impl)
+        : BpInterface<IAudioRecord>(impl)
+    {
+    }
+    
+    virtual status_t start()
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioRecord::getInterfaceDescriptor());
+        remote()->transact(START, data, &reply);
+        return reply.readInt32();
+    }
+    
+    virtual void stop()
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioRecord::getInterfaceDescriptor());
+        remote()->transact(STOP, data, &reply);
+    }
+    
+    virtual sp<IMemory> getCblk() const
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioRecord::getInterfaceDescriptor());
+        remote()->transact(GET_CBLK, data, &reply);
+        return interface_cast<IMemory>(reply.readStrongBinder());
+    }    
+};
+
+IMPLEMENT_META_INTERFACE(AudioRecord, "android.media.IAudioRecord");
+
+// ----------------------------------------------------------------------
+
+#define CHECK_INTERFACE(interface, data, reply) \
+        do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \
+            LOGW("Call incorrectly routed to " #interface); \
+            return PERMISSION_DENIED; \
+        } } while (0)
+
+status_t BnAudioRecord::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    switch(code) {
+       case GET_CBLK: {
+            CHECK_INTERFACE(IAudioRecord, data, reply);
+            reply->writeStrongBinder(getCblk()->asBinder());
+            return NO_ERROR;
+        } break;
+        case START: {
+            CHECK_INTERFACE(IAudioRecord, data, reply);
+            reply->writeInt32(start());
+            return NO_ERROR;
+        } break;
+        case STOP: {
+            CHECK_INTERFACE(IAudioRecord, data, reply);
+            stop();
+            return NO_ERROR;
+        } break;
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+}; // namespace android
+
diff --git a/media/libmedia/IAudioTrack.cpp b/media/libmedia/IAudioTrack.cpp
new file mode 100644
index 0000000..abc202d
--- /dev/null
+++ b/media/libmedia/IAudioTrack.cpp
@@ -0,0 +1,140 @@
+/* //device/extlibs/pv/android/IAudioTrack.cpp
+**
+** Copyright 2007, 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 <stdint.h>
+#include <sys/types.h>
+
+#include <utils/Parcel.h>
+
+#include <media/IAudioTrack.h>
+
+namespace android {
+
+enum {
+    GET_CBLK = IBinder::FIRST_CALL_TRANSACTION,
+    START,
+    STOP,
+    FLUSH,
+    MUTE,
+    PAUSE
+};
+
+class BpAudioTrack : public BpInterface<IAudioTrack>
+{
+public:
+    BpAudioTrack(const sp<IBinder>& impl)
+        : BpInterface<IAudioTrack>(impl)
+    {
+    }
+    
+    virtual status_t start()
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
+        remote()->transact(START, data, &reply);
+        return reply.readInt32();
+    }
+    
+    virtual void stop()
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
+        remote()->transact(STOP, data, &reply);
+    }
+    
+    virtual void flush()
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
+        remote()->transact(FLUSH, data, &reply);
+    }
+
+    virtual void mute(bool e)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
+        data.writeInt32(e);
+        remote()->transact(MUTE, data, &reply);
+    }
+    
+    virtual void pause()
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
+        remote()->transact(PAUSE, data, &reply);
+    }
+    
+    virtual sp<IMemory> getCblk() const
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
+        remote()->transact(GET_CBLK, data, &reply);
+        return interface_cast<IMemory>(reply.readStrongBinder());
+    }    
+};
+
+IMPLEMENT_META_INTERFACE(AudioTrack, "android.media.IAudioTrack");
+
+// ----------------------------------------------------------------------
+
+#define CHECK_INTERFACE(interface, data, reply) \
+        do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \
+            LOGW("Call incorrectly routed to " #interface); \
+            return PERMISSION_DENIED; \
+        } } while (0)
+
+status_t BnAudioTrack::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    switch(code) {
+       case GET_CBLK: {
+            CHECK_INTERFACE(IAudioTrack, data, reply);
+            reply->writeStrongBinder(getCblk()->asBinder());
+            return NO_ERROR;
+        } break;
+        case START: {
+            CHECK_INTERFACE(IAudioTrack, data, reply);
+            reply->writeInt32(start());
+            return NO_ERROR;
+        } break;
+        case STOP: {
+            CHECK_INTERFACE(IAudioTrack, data, reply);
+            stop();
+            return NO_ERROR;
+        } break;
+        case FLUSH: {
+            CHECK_INTERFACE(IAudioTrack, data, reply);
+            flush();
+            return NO_ERROR;
+        } break;
+        case MUTE: {
+            CHECK_INTERFACE(IAudioTrack, data, reply);
+            mute( data.readInt32() );
+            return NO_ERROR;
+        } break;
+        case PAUSE: {
+            CHECK_INTERFACE(IAudioTrack, data, reply);
+            pause();
+            return NO_ERROR;
+        }
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+}; // namespace android
+
diff --git a/media/libmedia/IMediaPlayer.cpp b/media/libmedia/IMediaPlayer.cpp
new file mode 100644
index 0000000..8385114
--- /dev/null
+++ b/media/libmedia/IMediaPlayer.cpp
@@ -0,0 +1,295 @@
+/*
+**
+** Copyright 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.
+*/
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/Parcel.h>
+
+#include <media/IMediaPlayer.h>
+#include <ui/ISurface.h>
+
+namespace android {
+
+enum {
+    DISCONNECT = IBinder::FIRST_CALL_TRANSACTION,
+    SET_VIDEO_SURFACE,
+    PREPARE_ASYNC,
+    START,
+    STOP,
+    IS_PLAYING,
+    PAUSE,
+    GET_VIDEO_SIZE,
+    SEEK_TO,
+    GET_CURRENT_POSITION,
+    GET_DURATION,
+    RESET,
+    SET_AUDIO_STREAM_TYPE,
+    SET_LOOPING,
+    SET_VOLUME
+};
+
+class BpMediaPlayer: public BpInterface<IMediaPlayer>
+{
+public:
+    BpMediaPlayer(const sp<IBinder>& impl)
+        : BpInterface<IMediaPlayer>(impl)
+    {
+    }
+
+    // disconnect from media player service
+    void disconnect()
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+        remote()->transact(DISCONNECT, data, &reply);
+    }
+
+    status_t setVideoSurface(const sp<ISurface>& surface)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+        data.writeStrongBinder(surface->asBinder());
+        remote()->transact(SET_VIDEO_SURFACE, data, &reply);
+        return reply.readInt32();
+    }
+
+    status_t prepareAsync()
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+        remote()->transact(PREPARE_ASYNC, data, &reply);
+        return reply.readInt32();
+    }
+
+    status_t start()
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+        remote()->transact(START, data, &reply);
+        return reply.readInt32();
+    }
+
+    status_t stop()
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+        remote()->transact(STOP, data, &reply);
+        return reply.readInt32();
+    }
+
+    status_t isPlaying(bool* state)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+        remote()->transact(IS_PLAYING, data, &reply);
+        *state = reply.readInt32();
+        return reply.readInt32();
+    }
+
+    status_t pause()
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+        remote()->transact(PAUSE, data, &reply);
+        return reply.readInt32();
+    }
+
+    status_t getVideoSize(int* w, int* h)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+        remote()->transact(GET_VIDEO_SIZE, data, &reply);
+        *w = reply.readInt32();
+        *h = reply.readInt32();
+        return reply.readInt32();
+    }
+
+    status_t seekTo(int msec)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+        data.writeInt32(msec);
+        remote()->transact(SEEK_TO, data, &reply);
+        return reply.readInt32();
+    }
+
+    status_t getCurrentPosition(int* msec)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+        remote()->transact(GET_CURRENT_POSITION, data, &reply);
+        *msec = reply.readInt32();
+        return reply.readInt32();
+    }
+
+    status_t getDuration(int* msec)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+        remote()->transact(GET_DURATION, data, &reply);
+        *msec = reply.readInt32();
+        return reply.readInt32();
+    }
+
+    status_t reset()
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+        remote()->transact(RESET, data, &reply);
+        return reply.readInt32();
+    }
+
+    status_t setAudioStreamType(int type)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+        data.writeInt32(type);
+        remote()->transact(SET_AUDIO_STREAM_TYPE, data, &reply);
+        return reply.readInt32();
+    }
+
+    status_t setLooping(int loop)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+        data.writeInt32(loop);
+        remote()->transact(SET_LOOPING, data, &reply);
+        return reply.readInt32();
+    }
+
+    status_t setVolume(float leftVolume, float rightVolume)
+    {
+        Parcel data, reply;
+        data.writeFloat(leftVolume);
+        data.writeFloat(rightVolume);
+        remote()->transact(SET_VOLUME, data, &reply);
+        return reply.readInt32();
+    }
+};
+
+IMPLEMENT_META_INTERFACE(MediaPlayer, "android.hardware.IMediaPlayer");
+
+// ----------------------------------------------------------------------
+
+#define CHECK_INTERFACE(interface, data, reply) \
+        do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \
+            LOGW("Call incorrectly routed to " #interface); \
+            return PERMISSION_DENIED; \
+        } } while (0)
+
+status_t BnMediaPlayer::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    switch(code) {
+        case DISCONNECT: {
+            CHECK_INTERFACE(IMediaPlayer, data, reply);
+            disconnect();
+            return NO_ERROR;
+        } break;
+        case SET_VIDEO_SURFACE: {
+            CHECK_INTERFACE(IMediaPlayer, data, reply);
+            sp<ISurface> surface = interface_cast<ISurface>(data.readStrongBinder());
+            reply->writeInt32(setVideoSurface(surface));
+            return NO_ERROR;
+        } break;
+        case PREPARE_ASYNC: {
+            CHECK_INTERFACE(IMediaPlayer, data, reply);
+            reply->writeInt32(prepareAsync());
+            return NO_ERROR;
+        } break;
+        case START: {
+            CHECK_INTERFACE(IMediaPlayer, data, reply);
+            reply->writeInt32(start());
+            return NO_ERROR;
+        } break;
+        case STOP: {
+            CHECK_INTERFACE(IMediaPlayer, data, reply);
+            reply->writeInt32(stop());
+            return NO_ERROR;
+        } break;
+        case IS_PLAYING: {
+            CHECK_INTERFACE(IMediaPlayer, data, reply);
+            bool state;
+            status_t ret = isPlaying(&state);
+            reply->writeInt32(state);
+            reply->writeInt32(ret);
+            return NO_ERROR;
+        } break;
+        case PAUSE: {
+            CHECK_INTERFACE(IMediaPlayer, data, reply);
+            reply->writeInt32(pause());
+            return NO_ERROR;
+        } break;
+        case GET_VIDEO_SIZE: {
+            CHECK_INTERFACE(IMediaPlayer, data, reply);
+            int w, h;
+            status_t ret = getVideoSize(&w, &h);
+            reply->writeInt32(w);
+            reply->writeInt32(h);
+            reply->writeInt32(ret);
+            return NO_ERROR;
+        } break;
+        case SEEK_TO: {
+            CHECK_INTERFACE(IMediaPlayer, data, reply);
+            reply->writeInt32(seekTo(data.readInt32()));
+            return NO_ERROR;
+        } break;
+        case GET_CURRENT_POSITION: {
+            CHECK_INTERFACE(IMediaPlayer, data, reply);
+            int msec;
+            status_t ret = getCurrentPosition(&msec);
+            reply->writeInt32(msec);
+            reply->writeInt32(ret);
+            return NO_ERROR;
+        } break;
+        case GET_DURATION: {
+            CHECK_INTERFACE(IMediaPlayer, data, reply);
+            int msec;
+            status_t ret = getDuration(&msec);
+            reply->writeInt32(msec);
+            reply->writeInt32(ret);
+            return NO_ERROR;
+        } break;
+        case RESET: {
+            CHECK_INTERFACE(IMediaPlayer, data, reply);
+            reply->writeInt32(reset());
+            return NO_ERROR;
+        } break;
+        case SET_AUDIO_STREAM_TYPE: {
+            CHECK_INTERFACE(IMediaPlayer, data, reply);
+            reply->writeInt32(setAudioStreamType(data.readInt32()));
+            return NO_ERROR;
+        } break;
+        case SET_LOOPING: {
+            CHECK_INTERFACE(IMediaPlayer, data, reply);
+            reply->writeInt32(setLooping(data.readInt32()));
+            return NO_ERROR;
+        } break;
+        case SET_VOLUME: {
+            reply->writeInt32(setVolume(data.readFloat(), data.readFloat()));
+            return NO_ERROR;
+        } break;
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
+
diff --git a/media/libmedia/IMediaPlayerClient.cpp b/media/libmedia/IMediaPlayerClient.cpp
new file mode 100644
index 0000000..65022cd
--- /dev/null
+++ b/media/libmedia/IMediaPlayerClient.cpp
@@ -0,0 +1,77 @@
+/*
+**
+** Copyright 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.
+*/
+
+#include <utils/RefBase.h>
+#include <utils/IInterface.h>
+#include <utils/Parcel.h>
+
+#include <media/IMediaPlayerClient.h>
+
+namespace android {
+
+enum {
+    NOTIFY = IBinder::FIRST_CALL_TRANSACTION,
+};
+
+class BpMediaPlayerClient: public BpInterface<IMediaPlayerClient>
+{
+public:
+    BpMediaPlayerClient(const sp<IBinder>& impl)
+        : BpInterface<IMediaPlayerClient>(impl)
+    {
+    }
+
+    virtual void notify(int msg, int ext1, int ext2)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaPlayerClient::getInterfaceDescriptor());
+        data.writeInt32(msg);
+        data.writeInt32(ext1);
+        data.writeInt32(ext2);
+        remote()->transact(NOTIFY, data, &reply, IBinder::FLAG_ONEWAY);
+    }
+};
+
+IMPLEMENT_META_INTERFACE(MediaPlayerClient, "android.hardware.IMediaPlayerClient");
+
+// ----------------------------------------------------------------------
+
+#define CHECK_INTERFACE(interface, data, reply) \
+        do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \
+            LOGW("Call incorrectly routed to " #interface); \
+            return PERMISSION_DENIED; \
+        } } while (0)
+
+status_t BnMediaPlayerClient::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    switch(code) {
+        case NOTIFY: {
+            CHECK_INTERFACE(IMediaPlayerClient, data, reply);
+            int msg = data.readInt32();
+            int ext1 = data.readInt32();
+            int ext2 = data.readInt32();
+            notify(msg, ext1, ext2);
+            return NO_ERROR;
+        } break;
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+}; // namespace android
+
diff --git a/media/libmedia/IMediaPlayerService.cpp b/media/libmedia/IMediaPlayerService.cpp
new file mode 100644
index 0000000..b087100
--- /dev/null
+++ b/media/libmedia/IMediaPlayerService.cpp
@@ -0,0 +1,157 @@
+/*
+**
+** Copyright 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.
+*/
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <utils/Parcel.h>
+
+#include <utils/IMemory.h>
+#include <media/IMediaPlayerService.h>
+
+namespace android {
+
+enum {
+    CREATE_URL = IBinder::FIRST_CALL_TRANSACTION,
+    CREATE_FD,
+    DECODE_URL,
+    DECODE_FD,
+};
+
+class BpMediaPlayerService: public BpInterface<IMediaPlayerService>
+{
+public:
+    BpMediaPlayerService(const sp<IBinder>& impl)
+        : BpInterface<IMediaPlayerService>(impl)
+    {
+    }
+
+    virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client, const char* url)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
+        data.writeInt32(pid);
+        data.writeStrongBinder(client->asBinder());
+        data.writeCString(url);
+        remote()->transact(CREATE_URL, data, &reply);
+        return interface_cast<IMediaPlayer>(reply.readStrongBinder());
+    }
+
+    virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client, int fd, int64_t offset, int64_t length)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
+        data.writeInt32(pid);
+        data.writeStrongBinder(client->asBinder());
+        data.writeFileDescriptor(fd);
+        data.writeInt64(offset);
+        data.writeInt64(length);
+        remote()->transact(CREATE_FD, data, &reply);
+        return interface_cast<IMediaPlayer>(reply.readStrongBinder());
+    }
+
+    virtual sp<IMemory> decode(const char* url, uint32_t *pSampleRate, int* pNumChannels)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
+        data.writeCString(url);
+        remote()->transact(DECODE_URL, data, &reply);
+        *pSampleRate = uint32_t(reply.readInt32());
+        *pNumChannels = reply.readInt32();
+        return interface_cast<IMemory>(reply.readStrongBinder());
+    }
+
+    virtual sp<IMemory> decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
+        data.writeFileDescriptor(fd);
+        data.writeInt64(offset);
+        data.writeInt64(length);
+        remote()->transact(DECODE_FD, data, &reply);
+        *pSampleRate = uint32_t(reply.readInt32());
+        *pNumChannels = reply.readInt32();
+        return interface_cast<IMemory>(reply.readStrongBinder());
+    }
+};
+
+IMPLEMENT_META_INTERFACE(MediaPlayerService, "android.hardware.IMediaPlayerService");
+
+// ----------------------------------------------------------------------
+
+#define CHECK_INTERFACE(interface, data, reply) \
+        do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \
+            LOGW("Call incorrectly routed to " #interface); \
+            return PERMISSION_DENIED; \
+        } } while (0)
+
+status_t BnMediaPlayerService::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    switch(code) {
+        case CREATE_URL: {
+            CHECK_INTERFACE(IMediaPlayerService, data, reply);
+            pid_t pid = data.readInt32();
+            sp<IMediaPlayerClient> client = interface_cast<IMediaPlayerClient>(data.readStrongBinder());
+            const char* url = data.readCString();
+            sp<IMediaPlayer> player = create(pid, client, url);
+            reply->writeStrongBinder(player->asBinder());
+            return NO_ERROR;
+        } break;
+        case CREATE_FD: {
+            CHECK_INTERFACE(IMediaPlayerService, data, reply);
+            pid_t pid = data.readInt32();
+            sp<IMediaPlayerClient> client = interface_cast<IMediaPlayerClient>(data.readStrongBinder());
+            int fd = dup(data.readFileDescriptor());
+            int64_t offset = data.readInt64();
+            int64_t length = data.readInt64();
+            sp<IMediaPlayer> player = create(pid, client, fd, offset, length);
+            reply->writeStrongBinder(player->asBinder());
+            return NO_ERROR;
+        } break;
+        case DECODE_URL: {
+            CHECK_INTERFACE(IMediaPlayerService, data, reply);
+            const char* url = data.readCString();
+            uint32_t sampleRate;
+            int numChannels;
+            sp<IMemory> player = decode(url, &sampleRate, &numChannels);
+            reply->writeInt32(sampleRate);
+            reply->writeInt32(numChannels);
+            reply->writeStrongBinder(player->asBinder());
+            return NO_ERROR;
+        } break;
+        case DECODE_FD: {
+            CHECK_INTERFACE(IMediaPlayerService, data, reply);
+            int fd = dup(data.readFileDescriptor());
+            int64_t offset = data.readInt64();
+            int64_t length = data.readInt64();
+            uint32_t sampleRate;
+            int numChannels;
+            sp<IMemory> player = decode(fd, offset, length, &sampleRate, &numChannels);
+            reply->writeInt32(sampleRate);
+            reply->writeInt32(numChannels);
+            reply->writeStrongBinder(player->asBinder());
+            return NO_ERROR;
+        } break;
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
+
diff --git a/media/libmedia/MODULE_LICENSE_APACHE2 b/media/libmedia/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/media/libmedia/MODULE_LICENSE_APACHE2
diff --git a/media/libmedia/NOTICE b/media/libmedia/NOTICE
new file mode 100644
index 0000000..c5b1efa
--- /dev/null
+++ b/media/libmedia/NOTICE
@@ -0,0 +1,190 @@
+
+   Copyright (c) 2005-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.
+
+   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.
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
diff --git a/media/libmedia/ToneGenerator.cpp b/media/libmedia/ToneGenerator.cpp
new file mode 100644
index 0000000..89ab2be
--- /dev/null
+++ b/media/libmedia/ToneGenerator.cpp
@@ -0,0 +1,662 @@
+/*
+ * 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 "ToneGenerator"
+#include <utils/threads.h>
+
+#include <stdio.h>
+#include <math.h>
+#include <utils/Log.h>
+#include <sys/resource.h>
+#include <utils/RefBase.h>
+#include <utils/Timers.h>
+#include "media/ToneGenerator.h"
+
+namespace android {
+
+// Descriptors for all available tones (See ToneGenerator::ToneDescriptor class declaration for details)
+const ToneGenerator::ToneDescriptor
+    ToneGenerator::toneDescriptors[NUM_TONES] = {
+    // waveFreq[]                     segments[]                         repeatCnt
+        { { 1336, 941, 0 },       { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF },  // TONE_DTMF_0
+        { { 1209, 697, 0 },       { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF },  // TONE_DTMF_1
+        { { 1336, 697, 0 },       { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF },  // TONE_DTMF_2
+        { { 1477, 697, 0 },       { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF },  // TONE_DTMF_3
+        { { 1209, 770, 0 },       { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF },  // TONE_DTMF_4
+        { { 1336, 770, 0 },       { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF },  // TONE_DTMF_5
+        { { 1477, 770, 0 },       { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF },  // TONE_DTMF_6
+        { { 1209, 852, 0 },       { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF },  // TONE_DTMF_7
+        { { 1336, 852, 0 },       { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF },  // TONE_DTMF_8
+        { { 1477, 852, 0 },       { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF },  // TONE_DTMF_9
+        { { 1209, 941, 0 },       { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF },  // TONE_DTMF_S
+        { { 1477, 941, 0 },       { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF },  // TONE_DTMF_P
+        { { 1633, 697, 0 },       { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF },  // TONE_DTMF_A
+        { { 1633, 770, 0 },       { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF },  // TONE_DTMF_B
+        { { 1633, 852, 0 },       { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF },  // TONE_DTMF_C
+        { { 1633, 941, 0 },       { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF },  // TONE_DTMF_D
+        { { 425, 0 },             { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF },  // TONE_SUP_DIAL
+        { { 425, 0 },             { 500, 500, 0 },                   ToneGenerator::TONEGEN_INF },  // TONE_SUP_BUSY
+        { { 425, 0 },             { 200, 200, 0 },                   ToneGenerator::TONEGEN_INF },  // TONE_SUP_CONGESTION
+        { { 425, 0 },             { 200, 0 },                        0 },                           // TONE_SUP_RADIO_ACK
+        { { 425, 0 },             { 200, 200, 0 },                   2 },                           // TONE_SUP_RADIO_NOTAVAIL
+        { { 950, 1400, 1800, 0 }, { 330, 1000, 0 },                  ToneGenerator::TONEGEN_INF },  // TONE_SUP_ERROR
+        { { 425, 0 },             { 200, 600, 200, 3000, 0 },        ToneGenerator::TONEGEN_INF },  // TONE_SUP_CALL_WAITING
+        { { 425, 0 },             { 1000, 4000, 0 },                 ToneGenerator::TONEGEN_INF },  // TONE_SUP_RINGTONE
+        { { 400, 1200, 0 },       { 35, 0 },                         0 },                           // TONE_PROP_BEEP
+        { { 1200, 0 },            { 100, 100, 0 },                   1 },                           // TONE_PROP_ACK
+        { { 300, 400, 500, 0 },   { 400, 0 },                        0 },                           // TONE_PROP_NACK
+        { { 400, 1200, 0 },       { 200, 0 },                        0 },                           // TONE_PROP_PROMPT
+        { { 400, 1200, 0 },       { 35, 200, 35, 0 },                0 }                            // TONE_PROP_BEEP2
+    };
+
+////////////////////////////////////////////////////////////////////////////////
+//                           ToneGenerator class Implementation
+////////////////////////////////////////////////////////////////////////////////
+
+
+//---------------------------------- public methods ----------------------------
+
+
+////////////////////////////////////////////////////////////////////////////////
+//
+//    Method:        ToneGenerator::ToneGenerator()
+//
+//    Description:    Constructor. Initializes the tone sequencer, intantiates required sine wave
+//        generators, instantiates output audio track.
+//
+//    Input:
+//        toneType:        Type of tone generated (values in enum tone_type)
+//        streamType:        Type of stream used for tone playback (enum AudioTrack::stream_type)
+//        volume:            volume applied to tone (0.0 to 1.0)
+//
+//    Output:
+//        none
+//
+////////////////////////////////////////////////////////////////////////////////
+ToneGenerator::ToneGenerator(int streamType, float volume) {
+    const sp<IAudioFlinger>& lpAudioFlinger = AudioSystem::get_audio_flinger();
+
+    LOGV("ToneGenerator constructor: streamType=%d, volume=%f\n", streamType, volume);
+
+    mState = TONE_IDLE;
+    mpAudioTrack = 0;
+    mpToneDesc = 0;
+    mpNewToneDesc = 0;
+
+    if (lpAudioFlinger == 0) {
+        LOGE("Unable to marshal AudioFlinger");
+        goto ToneGenerator_exit;
+    }
+
+    mSamplingRate = lpAudioFlinger->sampleRate();
+
+    mVolume = volume;
+    // Open audio track in mono, PCM 16bit, default sampling rate, 2 buffers
+    mpAudioTrack
+            = new AudioTrack(streamType, 0, AudioSystem::PCM_16_BIT, 1, NUM_PCM_BUFFERS, 0, audioCallback, this);
+
+    if (mpAudioTrack == 0) {
+        LOGE("AudioTrack allocation failed");
+        goto ToneGenerator_exit;
+    }
+    LOGV("Create Track: %p\n", mpAudioTrack);
+
+    if (mpAudioTrack->initCheck() != NO_ERROR) {
+        LOGE("AudioTrack->initCheck failed");
+        goto ToneGenerator_exit;
+    }
+
+    mpAudioTrack->setVolume(volume, volume);
+
+    LOGV("ToneGenerator INIT OK, time: %d\n", (unsigned int)(systemTime()/1000000));
+
+    mState = TONE_INIT;
+
+    return;
+
+ToneGenerator_exit:
+
+    // Cleanup
+    if (mpAudioTrack) {
+        LOGV("Delete Track I: %p\n", mpAudioTrack);
+        delete mpAudioTrack;
+    }
+
+    LOGV("!!!ToneGenerator INIT FAILED!!!\n");
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+//    Method:        ToneGenerator::~ToneGenerator()
+//
+//    Description:    Destructor. Stop sound playback and delete audio track if
+//      needed and delete sine wave generators.
+//
+//    Input:
+//        none
+//
+//    Output:
+//        none
+//
+////////////////////////////////////////////////////////////////////////////////
+ToneGenerator::~ToneGenerator() {
+    LOGV("ToneGenerator destructor\n");
+
+    if (mpAudioTrack) {
+        stopTone();
+        LOGV("Delete Track: %p\n", mpAudioTrack);
+        delete mpAudioTrack;
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+//    Method:        ToneGenerator::startTone()
+//
+//    Description:    Starts tone playback.
+//
+//    Input:
+//        none
+//
+//    Output:
+//        none
+//
+////////////////////////////////////////////////////////////////////////////////
+bool ToneGenerator::startTone(int toneType) {
+    bool lResult = false;
+
+    if (mState == TONE_IDLE || toneType >= NUM_TONES)
+        return lResult;
+
+    LOGV("startTone\n");
+
+    mLock.lock();
+
+    // Get descriptor for requested tone
+    mpNewToneDesc = &toneDescriptors[toneType];
+
+    if (mState == TONE_INIT) {
+        if (prepareWave()) {
+            LOGV("Immediate start, time %d\n", (unsigned int)(systemTime()/1000000));
+
+            mState = TONE_STARTING;
+            mLock.unlock();
+            mpAudioTrack->start();
+            mLock.lock();
+            if (mState == TONE_STARTING) {
+                if (mWaitCbkCond.waitRelative(mLock, seconds(1)) != NO_ERROR)
+                    LOGE("--- timed out");
+            }
+
+            if (mState == TONE_PLAYING)
+                lResult = true;
+        }
+    } else {
+        LOGV("Delayed start\n");
+
+        mState = TONE_RESTARTING;
+        if (mWaitCbkCond.waitRelative(mLock, seconds(1)) == NO_ERROR) {
+            if (mState != TONE_INIT) {
+                lResult = true;
+            }
+            LOGV("cond received");
+        } else {
+            LOGE("--- timed out");
+        }
+    }
+    mLock.unlock();
+
+    LOGV("Tone started, time %d\n", (unsigned int)(systemTime()/1000000));
+
+    return lResult;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+//    Method:        ToneGenerator::stopTone()
+//
+//    Description:    Stops tone playback.
+//
+//    Input:
+//        none
+//
+//    Output:
+//        none
+//
+////////////////////////////////////////////////////////////////////////////////
+void ToneGenerator::stopTone() {
+    LOGV("stopTone");
+
+    mLock.lock();
+    if (mState == TONE_PLAYING || mState == TONE_STARTING || mState == TONE_RESTARTING) {
+        mState = TONE_STOPPING;
+        LOGV("waiting cond");
+        status_t lStatus = mWaitCbkCond.waitRelative(mLock, seconds(1));
+        if (lStatus == NO_ERROR) {
+            LOGV("track stop complete, time %d", (unsigned int)(systemTime()/1000000));
+        } else {
+            LOGE("--- timed out");
+            mState = TONE_INIT;
+        }
+    }
+
+    clearWaveGens();
+
+    mLock.unlock();
+}
+
+//---------------------------------- private methods ---------------------------
+
+
+////////////////////////////////////////////////////////////////////////////////
+//
+//    Method:        ToneGenerator::audioCallback()
+//
+//    Description:    AudioTrack callback implementation. Generates a block of
+//        PCM samples
+//        and manages tone generator sequencer: tones pulses, tone duration...
+//
+//    Input:
+//        user    reference (pointer to our ToneGenerator)
+//        info    audio buffer descriptor
+//
+//    Output:
+//        returned value: always true.
+//
+////////////////////////////////////////////////////////////////////////////////
+void ToneGenerator::audioCallback(void* user, const AudioTrack::Buffer& info) {
+    ToneGenerator *lpToneGen = static_cast<ToneGenerator *>(user);
+    short *lpOut = info.i16;
+    unsigned int lReqSmp = info.size/sizeof(short);
+    unsigned int lGenSmp;
+    unsigned int lWaveCmd = WaveGenerator::WAVEGEN_CONT;
+    bool lSignal = false;
+
+
+    lpToneGen->mLock.lock();
+
+    // Clear output buffer: WaveGenerator accumulates into lpOut buffer
+    memset(lpOut, 0, info.size);
+
+    // Update pcm frame count and end time (current time at the end of this process)
+    lpToneGen->mTotalSmp += lReqSmp;
+
+    // Update tone gen state machine and select wave gen command
+    switch (lpToneGen->mState) {
+    case TONE_PLAYING:
+        lWaveCmd = WaveGenerator::WAVEGEN_CONT;
+        break;
+    case TONE_STARTING:
+        LOGV("Starting Cbk");
+
+        lWaveCmd = WaveGenerator::WAVEGEN_START;
+        break;
+    case TONE_STOPPING:
+    case TONE_RESTARTING:
+        LOGV("Stop/restart Cbk");
+
+        lWaveCmd = WaveGenerator::WAVEGEN_STOP;
+        lpToneGen->mNextSegSmp = TONEGEN_INF; // forced to skip state machine management below
+        break;
+    default:
+        LOGV("Extra Cbk");
+        goto audioCallback_Exit;
+    }
+
+    // Exit if to sequence is over
+    if (lpToneGen->mpToneDesc->segments[lpToneGen->mCurSegment] == 0) {
+        goto audioCallback_Exit;
+    }
+
+    if (lpToneGen->mTotalSmp > lpToneGen->mNextSegSmp) {
+        // Time to go to next sequence segment
+
+        LOGV("End Segment, time: %d\n", (unsigned int)(systemTime()/1000000));
+
+        lGenSmp = lReqSmp; 
+
+        if (lpToneGen->mCurSegment & 0x0001) {
+            // If odd segment,  OFF -> ON transition : reset wave generator
+            lWaveCmd = WaveGenerator::WAVEGEN_START;
+
+            LOGV("OFF->ON, lGenSmp: %d, lReqSmp: %d\n", lGenSmp, lReqSmp);
+        } else {
+            // If even segment,  ON -> OFF transition : ramp volume down
+            lWaveCmd = WaveGenerator::WAVEGEN_STOP;
+
+            LOGV("ON->OFF, lGenSmp: %d, lReqSmp: %d\n", lGenSmp, lReqSmp);
+        }
+
+        // Pre increment segment index and handle loop if last segment reached
+        if (lpToneGen->mpToneDesc->segments[++lpToneGen->mCurSegment] == 0) {
+            LOGV("Last Seg: %d\n", lpToneGen->mCurSegment);
+
+            // Pre increment loop count and restart if total count not reached. Stop sequence otherwise
+            if (++lpToneGen->mCurCount <= lpToneGen->mpToneDesc->repeatCnt) {
+                LOGV("Repeating Count: %d\n", lpToneGen->mCurCount);
+
+                lpToneGen->mCurSegment = 0;
+
+                LOGV("New segment %d, Next Time: %d\n", lpToneGen->mCurSegment,
+                        (lpToneGen->mNextSegSmp*1000)/lpToneGen->mSamplingRate);
+
+            } else {
+                LOGV("End repeat, time: %d\n", (unsigned int)(systemTime()/1000000));
+
+                // Cancel OFF->ON transition in case previous segment tone state was OFF
+                if (!(lpToneGen->mCurSegment & 0x0001)) {
+                    lGenSmp = 0;
+                }
+            }
+        } else {
+            LOGV("New segment %d, Next Time: %d\n", lpToneGen->mCurSegment,
+                    (lpToneGen->mNextSegSmp*1000)/lpToneGen->mSamplingRate);
+        }
+
+        // Update next segment transition position. No harm to do it also for last segment as lpToneGen->mNextSegSmp won't be used any more
+        lpToneGen->mNextSegSmp
+                += (lpToneGen->mpToneDesc->segments[lpToneGen->mCurSegment] * lpToneGen->mSamplingRate) / 1000;
+
+    } else {
+        // Inside a segment keep tone ON or OFF
+        if (lpToneGen->mCurSegment & 0x0001) {
+            lGenSmp = 0;  // If odd segment, tone is currently OFF
+        } else {
+            lGenSmp = lReqSmp;  // If event segment, tone is currently ON
+        }
+    }
+
+    if (lGenSmp) {
+        // If samples must be generated, call all active wave generators and acumulate waves in lpOut
+        unsigned int lWaveIdx;
+
+        for (lWaveIdx = 0; lWaveIdx < (unsigned int)lpToneGen->mWaveGens.size(); lWaveIdx++) {
+            WaveGenerator *lpWaveGen = lpToneGen->mWaveGens[lWaveIdx];
+            lpWaveGen->getSamples(lpOut, lGenSmp, lWaveCmd);
+        }
+    }
+
+audioCallback_Exit:
+
+    switch (lpToneGen->mState) {
+    case TONE_RESTARTING:
+        LOGV("Cbk restarting track\n");
+        if (lpToneGen->prepareWave()) {
+            lpToneGen->mState = TONE_STARTING;
+        } else {
+            lpToneGen->mState = TONE_INIT;
+            lpToneGen->mpAudioTrack->stop();
+        }
+        lSignal = true;
+        break;
+    case TONE_STOPPING:
+        lpToneGen->mState = TONE_INIT;
+        LOGV("Cbk Stopping track\n");
+        lSignal = true;
+        lpToneGen->mpAudioTrack->stop();
+        break;
+    case TONE_STARTING:
+        LOGV("Cbk starting track\n");
+        lpToneGen->mState = TONE_PLAYING;
+        lSignal = true;
+       break;
+    default:
+        break;
+    }
+
+    if (lSignal)
+        lpToneGen->mWaitCbkCond.signal();
+    lpToneGen->mLock.unlock();
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+//
+//    Method:        ToneGenerator::prepareWave()
+//
+//    Description:    Prepare wave generators and reset tone sequencer state machine.
+//      mpNewToneDesc must have been initialized befoire calling this function.
+//    Input:
+//        none
+//
+//    Output:
+//        returned value:   true if wave generators have been created, false otherwise
+//
+////////////////////////////////////////////////////////////////////////////////
+bool ToneGenerator::prepareWave() {
+    unsigned int lCnt = 0;
+    unsigned int lNumWaves;
+
+    if (!mpNewToneDesc) {
+        return false;
+    }
+    // Remove existing wave generators if any
+    clearWaveGens();
+
+    mpToneDesc = mpNewToneDesc;
+
+    // Get total number of sine waves: needed to adapt sine wave gain.
+    lNumWaves = numWaves();
+
+    // Instantiate as many wave generators as listed in descriptor
+    while (lCnt < lNumWaves) {
+        ToneGenerator::WaveGenerator *lpWaveGen =
+                new ToneGenerator::WaveGenerator((unsigned short)mSamplingRate,
+                        mpToneDesc->waveFreq[lCnt],
+                        TONEGEN_GAIN/lNumWaves);
+        if (lpWaveGen == 0) {
+            goto prepareWave_exit;
+        }
+
+        mWaveGens.push(lpWaveGen);
+        LOGV("Create sine: %d\n", mpToneDesc->waveFreq[lCnt]);
+        lCnt++;
+    }
+
+    // Initialize tone sequencer
+    mTotalSmp = 0;
+    mCurSegment = 0;
+    mCurCount = 0;
+    mNextSegSmp = (mpToneDesc->segments[0] * mSamplingRate) / 1000;
+
+    return true;
+
+prepareWave_exit:
+
+    clearWaveGens();
+
+    return false;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+//
+//    Method:        ToneGenerator::numWaves()
+//
+//    Description:    Count number of sine waves needed to generate tone (e.g 2 for DTMF).
+//
+//    Input:
+//        none
+//
+//    Output:
+//        returned value:    nummber of sine waves
+//
+////////////////////////////////////////////////////////////////////////////////
+unsigned int ToneGenerator::numWaves() {
+    unsigned int lCnt = 0;
+
+    while (mpToneDesc->waveFreq[lCnt]) {
+        lCnt++;
+    }
+
+    return lCnt;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+//
+//    Method:        ToneGenerator::clearWaveGens()
+//
+//    Description:    Removes all wave generators.
+//
+//    Input:
+//        none
+//
+//    Output:
+//        none
+//
+////////////////////////////////////////////////////////////////////////////////
+void ToneGenerator::clearWaveGens() {
+    LOGV("Clearing mWaveGens:");
+
+    while (!mWaveGens.isEmpty()) {
+        delete mWaveGens.top();
+        mWaveGens.pop();
+    }
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+//                WaveGenerator::WaveGenerator class    Implementation
+////////////////////////////////////////////////////////////////////////////////
+
+//---------------------------------- public methods ----------------------------
+
+////////////////////////////////////////////////////////////////////////////////
+//
+//    Method:        WaveGenerator::WaveGenerator()
+//
+//    Description:    Constructor.
+//
+//    Input:
+//        samplingRate:    Output sampling rate in Hz
+//        frequency:       Frequency of the sine wave to generate in Hz
+//        volume:          volume (0.0 to 1.0)
+//
+//    Output:
+//        none
+//
+////////////////////////////////////////////////////////////////////////////////
+ToneGenerator::WaveGenerator::WaveGenerator(unsigned short samplingRate,
+        unsigned short frequency, float volume) {
+    double d0;
+    double F_div_Fs;  // frequency / samplingRate
+
+    F_div_Fs = frequency / (double)samplingRate;
+    d0 = - (float)GEN_AMP * sin(2 * M_PI * F_div_Fs);
+    mS2_0 = (short)d0;
+    mS1 = 0;
+    mS2 = mS2_0;
+
+    mAmplitude_Q15 = (short)(32767. * 32767. * volume / GEN_AMP);
+    // take some margin for amplitude fluctuation
+    if (mAmplitude_Q15 > 32500)
+        mAmplitude_Q15 = 32500;
+
+    d0 = 32768.0 * cos(2 * M_PI * F_div_Fs);  // Q14*2*cos()
+    if (d0 > 32767)
+        d0 = 32767;
+    mA1_Q14 = (short) d0;
+
+    LOGV("WaveGenerator init, mA1_Q14: %d, mS2_0: %d, mAmplitude_Q15: %d\n",
+            mA1_Q14, mS2_0, mAmplitude_Q15);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+//    Method:        WaveGenerator::~WaveGenerator()
+//
+//    Description:    Destructor.
+//
+//    Input:
+//        none
+//
+//    Output:
+//        none
+//
+////////////////////////////////////////////////////////////////////////////////
+ToneGenerator::WaveGenerator::~WaveGenerator() {
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+//    Method:        WaveGenerator::getSamples()
+//
+//    Description:    Generates count samples of a sine wave and accumulates
+//        result in outBuffer.
+//
+//    Input:
+//        outBuffer:      Output buffer where to accumulate samples.
+//        count:          number of samples to produce.
+//        command:        special action requested (see enum gen_command).
+//
+//    Output:
+//        none
+//
+////////////////////////////////////////////////////////////////////////////////
+void ToneGenerator::WaveGenerator::getSamples(short *outBuffer,
+        unsigned int count, unsigned int command) {
+    long lS1, lS2;
+    long lA1, lAmplitude;
+    long Sample;  // current sample
+
+    // init local
+    if (command == WAVEGEN_START) {
+        lS1 = (long)0;
+        lS2 = (long)mS2_0;
+    } else {
+        lS1 = (long)mS1;
+        lS2 = (long)mS2;
+    }
+    lA1 = (long)mA1_Q14;
+    lAmplitude = (long)mAmplitude_Q15;
+
+    if (command == WAVEGEN_STOP) {
+        lAmplitude <<= 16;
+        if (count == 0) {
+            return;
+        }
+        long dec = lAmplitude/count;
+        // loop generation
+        while (count--) {
+            Sample = ((lA1 * lS1) >> S_Q14) - lS2;
+            // shift delay
+            lS2 = lS1;
+            lS1 = Sample;
+            Sample = ((lAmplitude>>16) * Sample) >> S_Q15;
+            *(outBuffer++) += (short)Sample;  // put result in buffer
+            lAmplitude -= dec;
+        }
+    } else {
+        // loop generation
+        while (count--) {
+            Sample = ((lA1 * lS1) >> S_Q14) - lS2;
+            // shift delay
+            lS2 = lS1;
+            lS1 = Sample;
+            Sample = (lAmplitude * Sample) >> S_Q15;
+            *(outBuffer++) += (short)Sample;  // put result in buffer
+        }
+    }
+
+    // save status
+    mS1 = (short)lS1;
+    mS2 = (short)lS2;
+}
+
+}  // end namespace android
+
diff --git a/media/libmedia/mediametadataretriever.cpp b/media/libmedia/mediametadataretriever.cpp
new file mode 100644
index 0000000..9cbafbc
--- /dev/null
+++ b/media/libmedia/mediametadataretriever.cpp
@@ -0,0 +1,182 @@
+/*
+**
+** Copyright 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.
+*/
+
+#include <media/mediametadataretriever.h>
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "MediaMetadataRetriever"
+#endif
+
+#include <utils/Log.h>
+#include <dlfcn.h>
+
+namespace android {
+
+// Factory class function in shared libpvplayer.so
+typedef MediaMetadataRetrieverImpl* (*createRetriever_f)();
+
+MediaMetadataRetrieverImpl *MediaMetadataRetriever::mRetriever = NULL;
+void                       *MediaMetadataRetriever::mLibHandler = NULL;
+
+void MediaMetadataRetriever::create()
+{
+    // Load libpvplayer library once and only once.
+    if (!mLibHandler) {
+        mLibHandler = dlopen("libopencoreplayer.so", RTLD_NOW);
+        if (!mLibHandler) {
+            LOGE("setDataSource: dlopen failed on libopencoreplayer.so");
+            return;
+        }
+    }
+    
+    // Each time create a new MediaMetadataRetrieverImpl object.
+    if (mRetriever) {
+        delete mRetriever;
+    }
+    createRetriever_f createRetriever = reinterpret_cast<createRetriever_f>(dlsym(mLibHandler, "createRetriever"));
+    if (!createRetriever) {
+        LOGE("setDataSource: dlsym failed on createRetriever in libpvplayer.so");
+        return;
+    }
+    mRetriever = createRetriever();
+    if (!mRetriever) {
+        LOGE("setDataSource: createRetriever failed in libpvplayer.so");
+    }
+}
+
+status_t MediaMetadataRetriever::setDataSource(const char* srcUrl)
+{
+    if (srcUrl == NULL) {
+        return UNKNOWN_ERROR;
+    }
+    
+    if (mRetriever) {
+        return mRetriever->setDataSource(srcUrl);
+    }
+    return UNKNOWN_ERROR;
+}
+
+const char* MediaMetadataRetriever::extractMetadata(int keyCode)
+{
+    if (mRetriever) {
+        return mRetriever->extractMetadata(keyCode);
+    }
+    return NULL;
+}
+
+MediaAlbumArt* MediaMetadataRetriever::extractAlbumArt()
+{
+    if (mRetriever) {
+        return mRetriever->extractAlbumArt();
+    }
+    return NULL;
+}
+
+SkBitmap* MediaMetadataRetriever::captureFrame()
+{
+    if (mRetriever) {
+        return mRetriever->captureFrame();
+    }
+    return NULL;
+}
+
+void MediaMetadataRetriever::setMode(int mode)
+{
+    if (mRetriever) {
+        mRetriever->setMode(mode);
+    }
+}
+
+void MediaMetadataRetriever::release()
+{
+    if (!mLibHandler) {
+        dlclose(mLibHandler);
+        mLibHandler = NULL;
+    }
+    if (!mRetriever) {
+        delete mRetriever;
+        mRetriever = NULL;
+    }
+}
+
+void MediaAlbumArt::clearData() {
+    if (data != NULL) {
+        delete []data;
+        data = NULL;
+    }
+    length = 0;
+}
+
+
+MediaAlbumArt::MediaAlbumArt(const char* url)
+{
+    length = 0;
+    data = NULL;
+    FILE *in = fopen(url, "r");
+    if (!in) {
+        LOGE("extractExternalAlbumArt: Failed to open external album art url: %s.", url);
+        return;
+    }
+    fseek(in, 0, SEEK_END);
+    length = ftell(in);  // Allocating buffer of size equals to the external file size.
+    if (length == 0 || (data = new char[length]) == NULL) {
+        if (length == 0) {
+            LOGE("extractExternalAlbumArt: External album art url: %s has a size of 0.", url);
+        } else if (data == NULL) {
+            LOGE("extractExternalAlbumArt: No enough memory for storing the retrieved album art.");
+            length = 0;
+        }
+        fclose(in);
+        return;
+    }
+    rewind(in);
+    if (fread(data, 1, length, in) != length) {  // Read failed.
+        length = 0;
+        delete []data;
+        data = NULL;
+        LOGE("extractExternalAlbumArt: Failed to retrieve the contents of an external album art.");
+    }
+    fclose(in);
+}
+
+status_t MediaAlbumArt::setData(unsigned int len, const char* buf) {
+    clearData();
+    length = len;
+    data = copyData(len, buf);
+    return (data != NULL)? OK: UNKNOWN_ERROR;
+}
+
+char* MediaAlbumArt::copyData(unsigned int len, const char* buf) {
+    if (len == 0 || !buf) {
+        if (len == 0) {
+            LOGE("copyData: Length is 0.");
+        } else if (!buf) {
+            LOGE("copyData: buf is NULL pointer");
+        }
+        return NULL;
+    }
+    char* copy = new char[len];
+    if (!copy) {
+        LOGE("copyData: No enough memory to copy out the data.");
+        return NULL;
+    }
+    memcpy(copy, buf, len);
+    return copy;
+}
+
+}; // namespace android
diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp
new file mode 100644
index 0000000..736d84a
--- /dev/null
+++ b/media/libmedia/mediaplayer.cpp
@@ -0,0 +1,582 @@
+/* mediaplayer.cpp
+**
+** Copyright 2006, 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 "MediaPlayer"
+#include <utils/Log.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <utils/IServiceManager.h>
+#include <utils/IPCThreadState.h>
+
+#include <media/mediaplayer.h>
+#include <libsonivox/eas.h>
+
+#include <utils/MemoryBase.h>
+
+namespace android {
+
+// client singleton for binder interface to service
+Mutex MediaPlayer::mServiceLock;
+sp<IMediaPlayerService> MediaPlayer::mMediaPlayerService;
+sp<MediaPlayer::DeathNotifier> MediaPlayer::mDeathNotifier;
+
+// establish binder interface to service
+const sp<IMediaPlayerService>& MediaPlayer::getMediaPlayerService()
+{
+    Mutex::Autolock _l(mServiceLock);
+    if (mMediaPlayerService.get() == 0) {
+        sp<IServiceManager> sm = defaultServiceManager();
+        sp<IBinder> binder;
+        do {
+            binder = sm->getService(String16("media.player"));
+            if (binder != 0)
+                break;
+            LOGW("MediaPlayerService not published, waiting...");
+            usleep(500000); // 0.5 s
+        } while(true);
+        if (mDeathNotifier == NULL) {
+            mDeathNotifier = new DeathNotifier();
+        }
+        binder->linkToDeath(mDeathNotifier);
+        mMediaPlayerService = interface_cast<IMediaPlayerService>(binder);
+    }
+    LOGE_IF(mMediaPlayerService==0, "no MediaPlayerService!?");
+    return mMediaPlayerService;
+}
+
+MediaPlayer::MediaPlayer()
+{
+    LOGV("constructor");
+    mListener = NULL;
+    mCookie = NULL;
+    mDuration = -1;
+    mStreamType = AudioTrack::MUSIC;
+    mCurrentPosition = -1;
+    mSeekPosition = -1;
+    mCurrentState = MEDIA_PLAYER_IDLE;
+    mPrepareSync = false;
+    mPrepareStatus = NO_ERROR;
+    mLoop = false;
+    mLeftVolume = mRightVolume = 1.0;
+}
+
+MediaPlayer::~MediaPlayer()
+{
+    LOGV("destructor");
+    disconnect();
+    IPCThreadState::self()->flushCommands();
+}
+
+void MediaPlayer::disconnect()
+{
+    LOGV("disconnect");
+    sp<IMediaPlayer> p;
+    {
+        Mutex::Autolock _l(mLock);
+        p = mPlayer;
+        mPlayer.clear();
+    }
+
+    if (p != 0) {
+        p->disconnect();
+        p->asBinder()->unlinkToDeath(this);
+    }
+}
+
+// always call with lock held
+void MediaPlayer::clear_l()
+{
+    mDuration = -1;
+    mCurrentPosition = -1;
+    mSeekPosition = -1;
+}
+
+status_t MediaPlayer::setListener(const sp<MediaPlayerListener>& listener)
+{
+    LOGV("setListener");
+    Mutex::Autolock _l(mLock);
+    mListener = listener;
+    return NO_ERROR;
+}
+
+
+status_t MediaPlayer::setDataSource(const sp<IMediaPlayer>& player)
+{
+    status_t err = UNKNOWN_ERROR;
+    sp<IMediaPlayer> p;
+    { // scope for the lock
+        Mutex::Autolock _l(mLock);
+
+        if ( !( mCurrentState & ( MEDIA_PLAYER_IDLE | MEDIA_PLAYER_STATE_ERROR ) ) ) {
+            LOGE("setDataSource called in state %d", mCurrentState);
+            return INVALID_OPERATION;
+        }
+
+        clear_l();
+        p = mPlayer;
+        mPlayer = player;
+        if (player != 0) {
+            mCurrentState = MEDIA_PLAYER_INITIALIZED;
+            player->asBinder()->linkToDeath(this);
+            err = NO_ERROR;
+        } else {
+            LOGE("Unable to to create media player");
+        }
+    }
+
+    if (p != 0) {
+        p->disconnect();
+        p->asBinder()->unlinkToDeath(this);
+    }
+    return err;
+}
+
+status_t MediaPlayer::setDataSource(const char *url)
+{
+    LOGV("setDataSource(%s)", url);
+    status_t err = UNKNOWN_ERROR;
+    if (url != NULL) {
+        const sp<IMediaPlayerService>& service(getMediaPlayerService());
+        if (service != 0) {
+            sp<IMediaPlayer> player(service->create(getpid(), this, url));
+            err = setDataSource(player);
+        }
+    }
+    return err;
+}
+
+status_t MediaPlayer::setDataSource(int fd, int64_t offset, int64_t length)
+{
+    LOGV("setDataSource(%d, %lld, %lld)", fd, offset, length);
+    status_t err = UNKNOWN_ERROR;
+    const sp<IMediaPlayerService>& service(getMediaPlayerService());
+    if (service != 0) {
+        sp<IMediaPlayer> player(service->create(getpid(), this, fd, offset, length));
+        err = setDataSource(player);
+    }
+    return err;
+}
+
+status_t MediaPlayer::setVideoSurface(const sp<Surface>& surface)
+{
+    LOGV("setVideoSurface");
+    Mutex::Autolock _l(mLock);
+    if (mPlayer == 0) return UNKNOWN_ERROR;
+    return  mPlayer->setVideoSurface(surface->getISurface());
+}
+
+// must call with lock held
+status_t MediaPlayer::prepareAsync_l()
+{
+    if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_INITIALIZED | MEDIA_PLAYER_STOPPED) ) ) {
+        mPlayer->setAudioStreamType(mStreamType);
+        mCurrentState = MEDIA_PLAYER_PREPARING;
+        return mPlayer->prepareAsync();
+    }
+    LOGE("prepareAsync called in state %d", mCurrentState);
+    return INVALID_OPERATION;
+}
+
+status_t MediaPlayer::prepare()
+{
+    LOGV("prepare");
+    Mutex::Autolock _l(mLock);
+    if (mPrepareSync) return UNKNOWN_ERROR;
+    mPrepareSync = true;
+    status_t ret = prepareAsync_l();
+    if (ret != NO_ERROR) return ret;
+
+    if (mPrepareSync) {
+        mSignal.wait(mLock);  // wait for prepare done
+        mPrepareSync = false;
+    }
+    LOGV("prepare complete - status=%d", mPrepareStatus);
+    return mPrepareStatus;
+}
+
+status_t MediaPlayer::prepareAsync()
+{
+    LOGV("prepareAsync");
+    Mutex::Autolock _l(mLock);
+    return prepareAsync_l();
+}
+
+status_t MediaPlayer::start()
+{
+    LOGV("start");
+    Mutex::Autolock _l(mLock);
+    if (mCurrentState & MEDIA_PLAYER_STARTED)
+        return NO_ERROR;
+    if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_PREPARED |
+                    MEDIA_PLAYER_PLAYBACK_COMPLETE | MEDIA_PLAYER_PAUSED ) ) ) {
+        mPlayer->setLooping(mLoop);
+        mPlayer->setVolume(mLeftVolume, mRightVolume);
+        mCurrentState = MEDIA_PLAYER_STARTED;
+        status_t ret = mPlayer->start();
+        if (ret != NO_ERROR) {
+            mCurrentState = MEDIA_PLAYER_STATE_ERROR;
+            ret = UNKNOWN_ERROR;
+        } else {
+            if (mCurrentState == MEDIA_PLAYER_PLAYBACK_COMPLETE) {
+                LOGV("playback completed immediately following start()");
+            }
+        }
+        return ret;
+    }
+    LOGE("start called in state %d", mCurrentState);
+    return INVALID_OPERATION;
+}
+
+status_t MediaPlayer::stop()
+{
+    LOGV("stop");
+    Mutex::Autolock _l(mLock);
+    if (mCurrentState & MEDIA_PLAYER_STOPPED) return NO_ERROR;
+    if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_STARTED | MEDIA_PLAYER_PREPARED |
+                    MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE ) ) ) {
+        status_t ret = mPlayer->stop();
+        if (ret != NO_ERROR) {
+            mCurrentState = MEDIA_PLAYER_STATE_ERROR;
+            ret = UNKNOWN_ERROR;
+        } else {
+            mCurrentState = MEDIA_PLAYER_STOPPED;
+        }
+        return ret;
+    }
+    LOGE("stop called in state %d", mCurrentState);
+    return INVALID_OPERATION;
+}
+
+status_t MediaPlayer::pause()
+{
+    LOGV("pause");
+    Mutex::Autolock _l(mLock);
+    if (mCurrentState & MEDIA_PLAYER_PAUSED)
+        return NO_ERROR;
+    if ((mPlayer != 0) && (mCurrentState & MEDIA_PLAYER_STARTED)) {
+        status_t ret = mPlayer->pause();
+        if (ret != NO_ERROR) {
+            mCurrentState = MEDIA_PLAYER_STATE_ERROR;
+            ret = UNKNOWN_ERROR;
+        } else {
+            mCurrentState = MEDIA_PLAYER_PAUSED;
+        }
+        return ret;
+    }
+    LOGE("pause called in state %d", mCurrentState);
+    return INVALID_OPERATION;
+}
+
+bool MediaPlayer::isPlaying()
+{
+    Mutex::Autolock _l(mLock);
+    if (mPlayer != 0) {
+        bool temp = false;
+        mPlayer->isPlaying(&temp);
+        LOGV("isPlaying: %d", temp);
+        if ((mCurrentState & MEDIA_PLAYER_STARTED) && ! temp) {
+            LOGE("internal/external state mismatch corrected");
+            mCurrentState = MEDIA_PLAYER_PAUSED;
+        }
+        return temp;
+    }
+    LOGV("isPlaying: no active player");
+    return false;
+}
+
+status_t MediaPlayer::getVideoWidth(int *w)
+{
+    LOGV("getVideoWidth");
+    Mutex::Autolock _l(mLock);
+    if (mPlayer != 0) {
+        int h;
+        return mPlayer->getVideoSize(w, &h);
+    }
+    return INVALID_OPERATION;
+}
+
+status_t MediaPlayer::getVideoHeight(int *h)
+{
+    LOGV("getVideoHeight");
+    Mutex::Autolock _l(mLock);
+    if (mPlayer != 0) {
+        int w;
+        return mPlayer->getVideoSize(&w, h);
+    }
+    return INVALID_OPERATION;
+}
+
+status_t MediaPlayer::getCurrentPosition(int *msec)
+{
+    LOGV("getCurrentPosition");
+    Mutex::Autolock _l(mLock);
+    if (mPlayer != 0) {
+        if (mCurrentPosition >= 0) {
+            LOGV("Using cached seek position: %d", mCurrentPosition);
+            *msec = mCurrentPosition;
+            return NO_ERROR;
+        }
+        return mPlayer->getCurrentPosition(msec);
+    }
+    return INVALID_OPERATION;
+}
+
+status_t MediaPlayer::getDuration_l(int *msec)
+{
+    LOGV("getDuration");
+    bool isValidState = (mCurrentState & (MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_STARTED | MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_STOPPED | MEDIA_PLAYER_PLAYBACK_COMPLETE));
+    if (mPlayer != 0 && isValidState) {
+        status_t ret = NO_ERROR;
+        if (mDuration <= 0)
+            ret = mPlayer->getDuration(&mDuration);
+        if (msec)
+            *msec = mDuration;
+        return ret;
+    }
+    LOGE("Attempt to call getDuration without a valid mediaplayer");
+    return INVALID_OPERATION;
+}
+
+status_t MediaPlayer::getDuration(int *msec)
+{
+    Mutex::Autolock _l(mLock);
+    return getDuration_l(msec);
+}
+
+status_t MediaPlayer::seekTo_l(int msec)
+{
+    LOGV("seekTo %d", msec);
+    if ((mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_STARTED | MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_PAUSED |  MEDIA_PLAYER_PLAYBACK_COMPLETE) ) ) {
+        if ( msec < 0 ) {
+            LOGW("Attempt to seek to invalid position: %d", msec);
+            msec = 0;
+        } else if ((mDuration > 0) && (msec > mDuration)) {
+            LOGW("Attempt to seek to past end of file: request = %d, EOF = %d", msec, mDuration);
+            msec = mDuration;
+        }
+        // cache duration
+        mCurrentPosition = msec;
+        if (mSeekPosition < 0) {
+            getDuration_l(NULL);
+            mSeekPosition = msec;
+            return mPlayer->seekTo(msec);
+        }
+        else {
+            LOGV("Seek in progress - queue up seekTo[%d]", msec);
+            return NO_ERROR;
+        }
+    }
+    LOGE("Attempt to perform seekTo in wrong state: mPlayer=%p, mCurrentState=%u", mPlayer.get(), mCurrentState);
+    return INVALID_OPERATION;
+}
+
+status_t MediaPlayer::seekTo(int msec)
+{
+    Mutex::Autolock _l(mLock);
+    return seekTo_l(msec);
+}
+
+status_t MediaPlayer::reset()
+{
+    LOGV("reset");
+    Mutex::Autolock _l(mLock);
+    mLoop = false;
+    if (mCurrentState == MEDIA_PLAYER_IDLE) return NO_ERROR;
+    mPrepareSync = false;
+    if (mPlayer != 0) {
+        status_t ret = mPlayer->reset();
+        if (ret != NO_ERROR) {
+            mCurrentState = MEDIA_PLAYER_STATE_ERROR;
+            ret = UNKNOWN_ERROR;
+        } else {
+            mCurrentState = MEDIA_PLAYER_IDLE;
+        }
+        return ret;
+    }
+    clear_l();
+    return NO_ERROR;
+}
+
+status_t MediaPlayer::setAudioStreamType(int type)
+{
+    LOGV("MediaPlayer::setAudioStreamType");
+    Mutex::Autolock _l(mLock);
+    if (mStreamType == type) return NO_ERROR;
+    if (mCurrentState & ( MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_STARTED |
+                MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE ) ) {
+        // Can't change the stream type after prepare
+        LOGE("setAudioStream called in state %d", mCurrentState);
+        return INVALID_OPERATION;
+    }
+    // cache
+    mStreamType = type;
+    return OK;
+}
+
+status_t MediaPlayer::setLooping(int loop)
+{
+    LOGV("MediaPlayer::setLooping");
+    Mutex::Autolock _l(mLock);
+    mLoop = (loop != 0);
+    if (mPlayer != 0) {
+        return mPlayer->setLooping(loop);
+    }
+    return OK;
+}
+
+status_t MediaPlayer::setVolume(float leftVolume, float rightVolume)
+{
+    LOGV("MediaPlayer::setVolume(%f, %f)", leftVolume, rightVolume);
+    Mutex::Autolock _l(mLock);
+    mLeftVolume = leftVolume;
+    mRightVolume = rightVolume;
+    if (mPlayer != 0) {
+        return mPlayer->setVolume(leftVolume, rightVolume);
+    }
+    return OK;
+}
+
+void MediaPlayer::notify(int msg, int ext1, int ext2)
+{
+    LOGV("message received msg=%d, ext1=%d, ext2=%d", msg, ext1, ext2);
+    bool send = true;
+
+    // TODO: In the future, we might be on the same thread if the app is
+    // running in the same process as the media server. In that case,
+    // this will deadlock.
+    mLock.lock();
+    if (mPlayer == 0) {
+        LOGV("notify(%d, %d, %d) callback on disconnected mediaplayer", msg, ext1, ext2);
+        return;
+    }
+
+    switch (msg) {
+    case MEDIA_NOP: // interface test message
+        break;
+    case MEDIA_PREPARED:
+        LOGV("prepared");
+        mCurrentState = MEDIA_PLAYER_PREPARED;
+        if (mPrepareSync) {
+            LOGV("signal application thread");
+            mPrepareSync = false;
+            mPrepareStatus = NO_ERROR;
+            mSignal.signal();
+        }
+        break;
+    case MEDIA_PLAYBACK_COMPLETE:
+        LOGV("playback complete");
+        if (!mLoop) {
+            mCurrentState = MEDIA_PLAYER_PLAYBACK_COMPLETE;
+        }
+        break;
+    case MEDIA_ERROR:
+        LOGV("error (%d, %d)", ext1, ext2);
+        mCurrentState = MEDIA_PLAYER_STATE_ERROR;
+        if (mPrepareSync)
+        {
+            LOGV("signal application thread");
+            mPrepareSync = false;
+            mPrepareStatus = ext1;
+            mSignal.signal();
+            send = false;
+        }
+        break;
+    case MEDIA_SEEK_COMPLETE:
+        LOGV("Received seek complete");
+        if (mSeekPosition != mCurrentPosition) {
+            LOGV("Executing queued seekTo(%d)", mSeekPosition);
+            mSeekPosition = -1;
+            seekTo_l(mCurrentPosition);
+        }
+        else {
+            LOGV("All seeks complete - return to regularly scheduled program");
+            mCurrentPosition = mSeekPosition = -1;
+        }
+        break;
+    case MEDIA_BUFFERING_UPDATE:
+        LOGV("buffering %d", ext1);
+        break;
+    default:
+        LOGV("unrecognized message: (%d, %d, %d)", msg, ext1, ext2);
+        break;
+    }
+
+    sp<MediaPlayerListener> listener = mListener;
+    mLock.unlock();
+
+    // this prevents re-entrant calls into client code
+    if ((listener != 0) && send) {
+        Mutex::Autolock _l(mNotifyLock);
+        LOGV("callback application");
+        listener->notify(msg, ext1, ext2);
+        LOGV("back from callback");
+    }
+}
+
+void MediaPlayer::binderDied(const wp<IBinder>& who) {
+    LOGW("IMediaplayer died");
+    notify(MEDIA_ERROR, MEDIA_ERROR_SERVER_DIED, 0);
+}
+
+void MediaPlayer::DeathNotifier::binderDied(const wp<IBinder>& who) {
+    Mutex::Autolock _l(MediaPlayer::mServiceLock);
+    MediaPlayer::mMediaPlayerService.clear();
+    LOGW("MediaPlayer server died!");
+}
+
+MediaPlayer::DeathNotifier::~DeathNotifier()
+{
+    Mutex::Autolock _l(mServiceLock);
+    if (mMediaPlayerService != 0) {
+        mMediaPlayerService->asBinder()->unlinkToDeath(this);
+    }
+}
+
+/*static*/ sp<IMemory> MediaPlayer::decode(const char* url, uint32_t *pSampleRate, int* pNumChannels)
+{
+    LOGV("decode(%s)", url);
+    sp<IMemory> p;
+    const sp<IMediaPlayerService>& service = getMediaPlayerService();
+    if (service != 0) {
+        p = mMediaPlayerService->decode(url, pSampleRate, pNumChannels);
+    } else {
+        LOGE("Unable to locate media service");
+    }
+    return p;
+
+}
+
+/*static*/ sp<IMemory> MediaPlayer::decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels)
+{
+    LOGV("decode(%d, %lld, %lld)", fd, offset, length);
+    sp<IMemory> p;
+    const sp<IMediaPlayerService>& service = getMediaPlayerService();
+    if (service != 0) {
+        p = mMediaPlayerService->decode(fd, offset, length, pSampleRate, pNumChannels);
+    } else {
+        LOGE("Unable to locate media service");
+    }
+    return p;
+
+}
+
+}; // namespace android
diff --git a/media/libmediaplayerservice/Android.mk b/media/libmediaplayerservice/Android.mk
new file mode 100644
index 0000000..b3a5747
--- /dev/null
+++ b/media/libmediaplayerservice/Android.mk
@@ -0,0 +1,33 @@
+LOCAL_PATH:= $(call my-dir)
+
+#
+# libmediaplayerservice
+#
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:=               \
+	MediaPlayerService.cpp \
+	VorbisPlayer.cpp \
+	MidiFile.cpp
+
+ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true)
+LOCAL_LDLIBS += -ldl -lpthread
+endif
+
+LOCAL_SHARED_LIBRARIES := \
+	libcutils \
+	libutils \
+	libvorbisidec \
+	libsonivox \
+	libopencoreplayer \
+	libmedia \
+	libandroid_runtime
+
+LOCAL_C_INCLUDES := external/tremor/Tremor \
+	$(call include-path-for, graphics corecg)
+
+LOCAL_MODULE:= libmediaplayerservice
+
+include $(BUILD_SHARED_LIBRARY)
+
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
new file mode 100644
index 0000000..fd5f0ed
--- /dev/null
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -0,0 +1,1112 @@
+/*
+**
+** Copyright 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.
+*/
+
+// Proxy for media player implementations
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "MediaPlayerService"
+#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/MediaPlayerInterface.h>
+#include <media/AudioTrack.h>
+
+#include "MediaPlayerService.h"
+#include "MidiFile.h"
+#include "VorbisPlayer.h"
+#include <media/PVPlayer.h>
+
+/* desktop Linux needs a little help with gettid() */
+#if defined(HAVE_GETTID) && !defined(HAVE_ANDROID_OS)
+#define __KERNEL__
+# include <linux/unistd.h>
+#ifdef _syscall0
+_syscall0(pid_t,gettid)
+#else
+pid_t gettid() { return syscall(__NR_gettid);}
+#endif
+#undef __KERNEL__
+#endif
+
+/*
+    When USE_SIGBUS_HANDLER is set to 1, a handler for SIGBUS will be
+    installed, which allows us to recover when there is a read error
+    when accessing an mmap'ed file. However, since the kernel folks
+    don't seem to like it when non kernel folks install signal handlers
+    in their own process, this is currently disabled.
+    Without the handler, the process hosting this service will die and
+    then be restarted. This is mostly OK right now because the process is
+    not being shared with any other services, and clients of the service
+    will be notified of its death in their MediaPlayer.onErrorListener
+    callback, assuming they have installed one, and can then attempt to
+    do their own recovery.
+    It does open us up to a DOS attack against the media server, where
+    a malicious application can trivially force the media server to
+    restart continuously.
+*/
+#define USE_SIGBUS_HANDLER 0
+ 
+// TODO: Temp hack until we can register players
+static const char* MIDI_FILE_EXTS[] =
+{
+        ".mid",
+        ".smf",
+        ".xmf",
+        ".imy",
+        ".rtttl",
+        ".rtx",
+        ".ota"
+};
+
+namespace android {
+
+// TODO: should come from audio driver
+/* static */ const uint32_t MediaPlayerService::AudioOutput::kDriverLatencyInMsecs = 150;
+
+static struct sigaction oldact;
+static pthread_key_t sigbuskey;
+
+static void sigbushandler(int signal, siginfo_t *info, void *context)
+{
+    char *faultaddr = (char*) info->si_addr;
+    LOGE("SIGBUS at %p\n", faultaddr);
+
+    struct mediasigbushandler* h = (struct mediasigbushandler*) pthread_getspecific(sigbuskey);
+
+    if (h) {
+        if (h->len) {
+            if (faultaddr < h->base || faultaddr >= h->base + h->len) {
+                // outside specified range, call old handler
+                if (oldact.sa_flags & SA_SIGINFO) {
+                    oldact.sa_sigaction(signal, info, context);
+                } else {
+                    oldact.sa_handler(signal);
+                }
+                return;
+            }
+        }
+
+        // no range specified or address was in range
+
+        if (h->handlesigbus) {
+            if (h->handlesigbus(info, h)) {
+                // thread's handler didn't handle the signal
+                if (oldact.sa_flags & SA_SIGINFO) {
+                    oldact.sa_sigaction(signal, info, context);
+                } else {
+                    oldact.sa_handler(signal);
+                }
+            }
+            return;
+        }
+
+        if (h->sigbusvar) {
+            // map in a zeroed out page so the operation can succeed
+            long pagesize = sysconf(_SC_PAGE_SIZE);
+            long pagemask = ~(pagesize - 1);
+            void * pageaddr = (void*) (((long)(faultaddr)) & pagemask);
+
+            void * bar = mmap( pageaddr, pagesize, PROT_READ, MAP_ANONYMOUS|MAP_PRIVATE|MAP_FIXED, -1, 0);
+            if (bar == MAP_FAILED) {
+                LOGE("couldn't map zero page at %p: %s", pageaddr, strerror(errno));
+                if (oldact.sa_flags & SA_SIGINFO) {
+                    oldact.sa_sigaction(signal, info, context);
+                } else {
+                    oldact.sa_handler(signal);
+                }
+                return;
+            }
+
+            LOGE("setting sigbusvar at %p", h->sigbusvar);
+            *(h->sigbusvar) = 1;
+            return;
+        }
+    }
+
+    LOGE("SIGBUS: no handler, or improperly configured handler (%p)", h);
+
+    if (oldact.sa_flags & SA_SIGINFO) {
+        oldact.sa_sigaction(signal, info, context);
+    } else {
+        oldact.sa_handler(signal);
+    }
+    return;
+}
+
+void MediaPlayerService::instantiate() {
+    defaultServiceManager()->addService(
+            String16("media.player"), new MediaPlayerService());
+}
+
+MediaPlayerService::MediaPlayerService()
+{
+    LOGV("MediaPlayerService created");
+    mNextConnId = 1;
+
+    pthread_key_create(&sigbuskey, NULL);
+
+  
+#if USE_SIGBUS_HANDLER
+    struct sigaction act;
+    memset(&act,0, sizeof act);
+    act.sa_sigaction = sigbushandler;
+    act.sa_flags = SA_SIGINFO;
+    sigaction(SIGBUS, &act, &oldact);
+#endif
+}
+
+MediaPlayerService::~MediaPlayerService()
+{
+#if USE_SIGBUS_HANDLER
+    sigaction(SIGBUS, &oldact, NULL);
+#endif
+    pthread_key_delete(sigbuskey);
+    LOGV("MediaPlayerService destroyed");
+}
+
+sp<IMediaPlayer> MediaPlayerService::create(pid_t pid, const sp<IMediaPlayerClient>& client, const char* url)
+{
+    int32_t connId = android_atomic_inc(&mNextConnId);
+    sp<Client> c = new Client(this, pid, connId, client);
+    LOGV("Create new client(%d) from pid %d, url=%s, connId=%d", connId, pid, url, connId);
+    if (NO_ERROR != c->setDataSource(url))
+    {
+        c.clear();
+        return c;
+    }
+    wp<Client> w = c;
+    Mutex::Autolock lock(mLock);
+    mClients.add(w);
+    return c;
+}
+
+sp<IMediaPlayer> MediaPlayerService::create(pid_t pid, const sp<IMediaPlayerClient>& client,
+        int fd, int64_t offset, int64_t length)
+{
+    int32_t connId = android_atomic_inc(&mNextConnId);
+    sp<Client> c = new Client(this, pid, connId, client);
+    LOGV("Create new client(%d) from pid %d, fd=%d, offset=%lld, length=%lld",
+            connId, pid, fd, offset, length);
+    if (NO_ERROR != c->setDataSource(fd, offset, length)) {
+        c.clear();
+    } else {
+        wp<Client> w = c;
+        Mutex::Autolock lock(mLock);
+        mClients.add(w);
+    }
+    ::close(fd);
+    return c;
+}
+
+status_t MediaPlayerService::AudioCache::dump(int fd, const Vector<String16>& args) const
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+
+    result.append(" AudioCache\n");
+    if (mHeap != 0) {
+        snprintf(buffer, 255, "  heap base(%p), size(%d), flags(%d), device(%s)\n",
+                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);
+    result.append(buffer);
+    snprintf(buffer, 255, "  sample rate(%d), size(%d), error(%d), command complete(%s)\n",
+            mSampleRate, mSize, mError, mCommandComplete?"true":"false");
+    result.append(buffer);
+    ::write(fd, result.string(), result.size());
+    return NO_ERROR;
+}
+
+status_t MediaPlayerService::AudioOutput::dump(int fd, const Vector<String16>& args) const
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+
+    result.append(" AudioOutput\n");
+    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);
+    result.append(buffer);
+    ::write(fd, result.string(), result.size());
+    if (mTrack != 0) {
+        mTrack->dump(fd, args);
+    }
+    return NO_ERROR;
+}
+
+status_t MediaPlayerService::Client::dump(int fd, const Vector<String16>& args) const
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+    result.append(" Client\n");
+    snprintf(buffer, 255, "  pid(%d), connId(%d), status(%d), looping(%s)\n",
+            mPid, mConnId, mStatus, mLoop?"true": "false");
+    result.append(buffer);
+    write(fd, result.string(), result.size());
+    if (mAudioOutput != 0) {
+        mAudioOutput->dump(fd, args);
+    }
+    write(fd, "\n", 1);
+    return NO_ERROR;
+}
+
+static int myTid() {
+#ifdef HAVE_GETTID
+    return gettid();
+#else
+    return getpid();
+#endif
+}
+
+status_t MediaPlayerService::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 MediaPlayerService from pid=%d, uid=%d\n",
+                IPCThreadState::self()->getCallingPid(),
+                IPCThreadState::self()->getCallingUid());
+        result.append(buffer);
+    } else {
+        Mutex::Autolock lock(mLock);
+        for (int i = 0, n = mClients.size(); i < n; ++i) {
+            sp<Client> c = mClients[i].promote();
+            if (c != 0) c->dump(fd, args);
+        }
+        result.append(" Files opened and/or mapped:\n");
+        snprintf(buffer, SIZE, "/proc/%d/maps", myTid());
+        FILE *f = fopen(buffer, "r");
+        if (f) {
+            while (!feof(f)) {
+                fgets(buffer, SIZE, f);
+                if (strstr(buffer, " /sdcard/") || 
+                    strstr(buffer, " /system/sounds/") ||
+                    strstr(buffer, " /system/media/")) {
+                    result.append("  ");
+                    result.append(buffer);
+                }
+            }
+            fclose(f);
+        } else {
+            result.append("couldn't open ");
+            result.append(buffer);
+            result.append("\n");
+        }
+
+        snprintf(buffer, SIZE, "/proc/%d/fd", myTid());
+        DIR *d = opendir(buffer);
+        if (d) {
+            struct dirent *ent;
+            while((ent = readdir(d)) != NULL) {
+                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) {
+                        if ((s.st_mode & S_IFMT) == S_IFLNK) {
+                            char linkto[256];
+                            int len = readlink(buffer, linkto, sizeof(linkto));
+                            if(len > 0) {
+                                if(len > 255) {
+                                    linkto[252] = '.';
+                                    linkto[253] = '.';
+                                    linkto[254] = '.';
+                                    linkto[255] = 0;
+                                } else {
+                                    linkto[len] = 0;
+                                }
+                                if (strstr(linkto, "/sdcard/") == linkto || 
+                                    strstr(linkto, "/system/sounds/") == linkto ||
+                                    strstr(linkto, "/system/media/") == linkto) {
+                                    result.append("  ");
+                                    result.append(buffer);
+                                    result.append(" -> ");
+                                    result.append(linkto);
+                                    result.append("\n");
+                                }
+                            }
+                        } else {
+                            result.append("  unexpected type for ");
+                            result.append(buffer);
+                            result.append("\n");
+                        }
+                    }
+                }
+            }
+            closedir(d);
+        } else {
+            result.append("couldn't open ");
+            result.append(buffer);
+            result.append("\n");
+        }
+    }
+    write(fd, result.string(), result.size());
+    return NO_ERROR;
+}
+
+void MediaPlayerService::removeClient(wp<Client> client)
+{
+    Mutex::Autolock lock(mLock);
+    mClients.remove(client);
+}
+
+MediaPlayerService::Client::Client(const sp<MediaPlayerService>& service, pid_t pid,
+        int32_t connId, const sp<IMediaPlayerClient>& client)
+{
+    LOGV("Client(%d) constructor", connId);
+    mPid = pid;
+    mConnId = connId;
+    mService = service;
+    mClient = client;
+    mLoop = false;
+    mStatus = NO_INIT;
+#if CALLBACK_ANTAGONIZER
+    LOGD("create Antagonizer");
+    mAntagonizer = new Antagonizer(notify, this);
+#endif
+}
+
+MediaPlayerService::Client::~Client()
+{
+    LOGV("Client(%d) destructor pid = %d", mConnId, mPid);
+    mAudioOutput.clear();
+    wp<Client> client(this);
+    disconnect();
+    mService->removeClient(client);
+}
+
+void MediaPlayerService::Client::disconnect()
+{
+    LOGV("disconnect(%d) from pid %d", mConnId, mPid);
+    // grab local reference and clear main reference to prevent future
+    // access to object
+    sp<MediaPlayerBase> p;
+    {
+        Mutex::Autolock l(mLock);
+        p = mPlayer;
+    }
+    mPlayer.clear();
+
+    // clear the notification to prevent callbacks to dead client
+    // and reset the player. We assume the player will serialize
+    // access to itself if necessary.
+    if (p != 0) {
+        p->setNotifyCallback(0, 0);
+#if CALLBACK_ANTAGONIZER
+        LOGD("kill Antagonizer");
+        mAntagonizer->kill();
+#endif
+        p->reset();
+    }
+
+    IPCThreadState::self()->flushCommands();
+}
+
+static player_type getPlayerType(int fd, int64_t offset, int64_t length)
+{
+    char buf[20];
+    lseek(fd, offset, SEEK_SET);
+    read(fd, buf, sizeof(buf));
+    lseek(fd, offset, SEEK_SET);
+
+    long ident = *((long*)buf);
+
+    // Ogg vorbis?
+    if (ident == 0x5367674f) // 'OggS'
+        return VORBIS_PLAYER;
+
+    // Some kind of MIDI?
+    EAS_DATA_HANDLE easdata;
+    if (EAS_Init(&easdata) == EAS_SUCCESS) {
+        EAS_FILE locator;
+        locator.path = NULL;
+        locator.fd = fd;
+        locator.offset = offset;
+        locator.length = length;
+        EAS_HANDLE  eashandle;
+        if (EAS_OpenFile(easdata, &locator, &eashandle, NULL) == EAS_SUCCESS) {
+            EAS_CloseFile(easdata, eashandle);
+            EAS_Shutdown(easdata);
+            return SONIVOX_PLAYER;
+        }
+        EAS_Shutdown(easdata);
+    }
+
+    // Fall through to PV
+    return PV_PLAYER;
+}
+
+static player_type getPlayerType(const char* url)
+{
+
+    // use MidiFile for MIDI extensions
+    int lenURL = strlen(url);
+    for (int i = 0; i < NELEM(MIDI_FILE_EXTS); ++i) {
+        int len = strlen(MIDI_FILE_EXTS[i]);
+        int start = lenURL - len;
+        if (start > 0) {
+            if (!strncmp(url + start, MIDI_FILE_EXTS[i], len)) {
+                LOGV("Type is MIDI");
+                return SONIVOX_PLAYER;
+            }
+        }
+    }
+
+    if (strcmp(url + strlen(url) - 4, ".ogg") == 0) {
+        LOGV("Type is Vorbis");
+        return VORBIS_PLAYER;
+    }
+
+    // Fall through to PV
+    return PV_PLAYER;
+}
+
+static sp<MediaPlayerBase> createPlayer(player_type playerType, void* cookie,
+        notify_callback_f notifyFunc)
+{
+    sp<MediaPlayerBase> p;
+    switch (playerType) {
+        case PV_PLAYER:
+            LOGV(" create PVPlayer");
+            p = new PVPlayer();
+            break;
+        case SONIVOX_PLAYER:
+            LOGV(" create MidiFile");
+            p = new MidiFile();
+            break;
+        case VORBIS_PLAYER:
+            LOGV(" create VorbisPlayer");
+            p = new VorbisPlayer();
+            break;
+    }
+    if (p != NULL) {
+        if (p->initCheck() == NO_ERROR) {
+            p->setNotifyCallback(cookie, notifyFunc);
+            p->setSigBusHandlerStructTLSKey(sigbuskey);
+        } else {
+            p.clear();
+        }
+    }
+    if (p == NULL) {
+        LOGE("Failed to create player object");
+    }
+    return p;
+}
+
+sp<MediaPlayerBase> MediaPlayerService::Client::createPlayer(player_type playerType)
+{
+    // determine if we have the right player type
+    sp<MediaPlayerBase> p = mPlayer;
+    if ((p != NULL) && (p->playerType() != playerType)) {
+        LOGV("delete player");
+        p.clear();
+    }
+    if (p == NULL) {
+        p = android::createPlayer(playerType, this, notify);
+    }
+    return p;
+}
+
+status_t MediaPlayerService::Client::setDataSource(const char *url)
+{
+    LOGV("setDataSource(%s)", url);
+    if (url == NULL)
+        return UNKNOWN_ERROR;
+
+    if (strncmp(url, "content://", 10) == 0) {
+        // get a filedescriptor for the content Uri and
+        // pass it to the setDataSource(fd) method
+
+        String16 url16(url);
+        int fd = android::openContentProviderFile(url16);
+        if (fd < 0)
+        {
+            LOGE("Couldn't open fd for %s", url);
+            return UNKNOWN_ERROR;
+        }
+        setDataSource(fd, 0, 0x7fffffffffLL); // this sets mStatus
+        close(fd);
+        return mStatus;
+    } else {
+        player_type playerType = getPlayerType(url);
+        LOGV("player type = %d", playerType);
+
+        // create the right type of player
+        sp<MediaPlayerBase> p = createPlayer(playerType);
+        if (p == NULL) return NO_INIT;
+
+        if (!p->hardwareOutput()) {
+            mAudioOutput = new AudioOutput();
+            static_cast<MediaPlayerInterface*>(p.get())->setAudioSink(mAudioOutput);
+        }
+
+        // now set data source
+        LOGV(" setDataSource");
+        mStatus = p->setDataSource(url);
+        if (mStatus == NO_ERROR) mPlayer = p;
+        return mStatus;
+    }
+}
+
+status_t MediaPlayerService::Client::setDataSource(int fd, int64_t offset, int64_t length)
+{
+    LOGV("setDataSource fd=%d, offset=%lld, length=%lld", fd, offset, length);
+    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 error");
+        ::close(fd);
+        return UNKNOWN_ERROR;
+    }
+    if (offset + length > sb.st_size) {
+        length = sb.st_size - offset;
+        LOGV("calculated length = %lld", length);
+    }
+
+    player_type playerType = getPlayerType(fd, offset, length);
+    LOGV("player type = %d", playerType);
+
+    // create the right type of player
+    sp<MediaPlayerBase> p = createPlayer(playerType);
+    if (p == NULL) return NO_INIT;
+
+    if (!p->hardwareOutput()) {
+        mAudioOutput = new AudioOutput();
+        static_cast<MediaPlayerInterface*>(p.get())->setAudioSink(mAudioOutput);
+    }
+
+    // now set data source
+    mStatus = p->setDataSource(fd, offset, length);
+    if (mStatus == NO_ERROR) mPlayer = p;
+    return mStatus;
+}
+
+status_t MediaPlayerService::Client::setVideoSurface(const sp<ISurface>& surface)
+{
+    LOGV("[%d] setVideoSurface(%p)", mConnId, surface.get());
+    sp<MediaPlayerBase> p = getPlayer();
+    if (p == 0) return UNKNOWN_ERROR;
+    return p->setVideoSurface(surface);
+}
+
+status_t MediaPlayerService::Client::prepareAsync()
+{
+    LOGV("[%d] prepareAsync", mConnId);
+    sp<MediaPlayerBase> p = getPlayer();
+    if (p == 0) return UNKNOWN_ERROR;
+    status_t ret = p->prepareAsync();
+#if CALLBACK_ANTAGONIZER
+    LOGD("start Antagonizer");
+    if (ret == NO_ERROR) mAntagonizer->start();
+#endif
+    return ret;
+}
+
+status_t MediaPlayerService::Client::start()
+{
+    LOGV("[%d] start", mConnId);
+    sp<MediaPlayerBase> p = getPlayer();
+    if (p == 0) return UNKNOWN_ERROR;
+    p->setLooping(mLoop);
+    return p->start();
+}
+
+status_t MediaPlayerService::Client::stop()
+{
+    LOGV("[%d] stop", mConnId);
+    sp<MediaPlayerBase> p = getPlayer();
+    if (p == 0) return UNKNOWN_ERROR;
+    return p->stop();
+}
+
+status_t MediaPlayerService::Client::pause()
+{
+    LOGV("[%d] pause", mConnId);
+    sp<MediaPlayerBase> p = getPlayer();
+    if (p == 0) return UNKNOWN_ERROR;
+    return p->pause();
+}
+
+status_t MediaPlayerService::Client::isPlaying(bool* state)
+{
+    *state = false;
+    sp<MediaPlayerBase> p = getPlayer();
+    if (p == 0) return UNKNOWN_ERROR;
+    *state = p->isPlaying();
+    LOGV("[%d] isPlaying: %d", mConnId, *state);
+    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");
+    sp<MediaPlayerBase> p = getPlayer();
+    if (p == 0) return UNKNOWN_ERROR;
+    status_t ret = p->getCurrentPosition(msec);
+    if (ret == NO_ERROR) {
+        LOGV("[%d] getCurrentPosition = %d", mConnId, *msec);
+    } else {
+        LOGE("getCurrentPosition returned %d", ret);
+    }
+    return ret;
+}
+
+status_t MediaPlayerService::Client::getDuration(int *msec)
+{
+    LOGV("getDuration");
+    sp<MediaPlayerBase> p = getPlayer();
+    if (p == 0) return UNKNOWN_ERROR;
+    status_t ret = p->getDuration(msec);
+    if (ret == NO_ERROR) {
+        LOGV("[%d] getDuration = %d", mConnId, *msec);
+    } else {
+        LOGE("getDuration returned %d", ret);
+    }
+    return ret;
+}
+
+status_t MediaPlayerService::Client::seekTo(int msec)
+{
+    LOGV("[%d] seekTo(%d)", mConnId, msec);
+    sp<MediaPlayerBase> p = getPlayer();
+    if (p == 0) return UNKNOWN_ERROR;
+    return p->seekTo(msec);
+}
+
+status_t MediaPlayerService::Client::reset()
+{
+    LOGV("[%d] reset", mConnId);
+    sp<MediaPlayerBase> p = getPlayer();
+    if (p == 0) return UNKNOWN_ERROR;
+    return p->reset();
+}
+
+status_t MediaPlayerService::Client::setAudioStreamType(int type)
+{
+    LOGV("[%d] setAudioStreamType(%d)", mConnId, type);
+    // TODO: for hardware output, call player instead
+    Mutex::Autolock l(mLock);
+    if (mAudioOutput != 0) mAudioOutput->setAudioStreamType(type);
+    return NO_ERROR;
+}
+
+status_t MediaPlayerService::Client::setLooping(int loop)
+{
+    LOGV("[%d] setLooping(%d)", mConnId, loop);
+    mLoop = loop;
+    sp<MediaPlayerBase> p = getPlayer();
+    if (p != 0) return p->setLooping(loop);
+    return NO_ERROR;
+}
+
+status_t MediaPlayerService::Client::setVolume(float leftVolume, float rightVolume)
+{
+    LOGV("[%d] setVolume(%f, %f)", mConnId, leftVolume, rightVolume);
+    // TODO: for hardware output, call player instead
+    Mutex::Autolock l(mLock);
+    if (mAudioOutput != 0) mAudioOutput->setVolume(leftVolume, rightVolume);
+    return NO_ERROR;
+}
+
+void MediaPlayerService::Client::notify(void* cookie, int msg, int ext1, int ext2)
+{
+    Client* client = static_cast<Client*>(cookie);
+    LOGV("[%d] notify (%p, %d, %d, %d)", client->mConnId, cookie, msg, ext1, ext2);
+    client->mClient->notify(msg, ext1, ext2);
+}
+
+#if CALLBACK_ANTAGONIZER
+const int Antagonizer::interval = 10000; // 10 msecs
+
+Antagonizer::Antagonizer(notify_callback_f cb, void* client) :
+    mExit(false), mActive(false), mClient(client), mCb(cb)
+{
+    createThread(callbackThread, this);
+}
+
+void Antagonizer::kill()
+{
+    Mutex::Autolock _l(mLock);
+    mActive = false;
+    mExit = true;
+    mCondition.wait(mLock);
+}
+
+int Antagonizer::callbackThread(void* user)
+{
+    LOGD("Antagonizer started");
+    Antagonizer* p = reinterpret_cast<Antagonizer*>(user);
+    while (!p->mExit) {
+        if (p->mActive) {
+            LOGV("send event");
+            p->mCb(p->mClient, 0, 0, 0);
+        }
+        usleep(interval);
+    }
+    Mutex::Autolock _l(p->mLock);
+    p->mCondition.signal();
+    LOGD("Antagonizer stopped");
+    return 0;
+}
+#endif
+
+static size_t kDefaultHeapSize = 1024 * 1024; // 1MB
+
+sp<IMemory> MediaPlayerService::decode(const char* url, uint32_t *pSampleRate, int* pNumChannels)
+{
+    LOGV("decode(%s)", url);
+    sp<MemoryBase> mem;
+    sp<MediaPlayerBase> player;
+
+    // Protect our precious, precious DRMd ringtones by only allowing
+    // decoding of http, but not filesystem paths or content Uris.
+    // If the application wants to decode those, it should open a
+    // filedescriptor for them and use that.
+    if (url != NULL && strncmp(url, "http://", 7) != 0) {
+        LOGD("Can't decode %s by path, use filedescriptor instead", url);
+        return mem;
+    }
+
+    player_type playerType = getPlayerType(url);
+    LOGV("player type = %d", playerType);
+
+    // create the right type of player
+    sp<AudioCache> cache = new AudioCache(url);
+    player = android::createPlayer(playerType, cache.get(), cache->notify);
+    if (player == NULL) goto Exit;
+    if (player->hardwareOutput()) goto Exit;
+
+    static_cast<MediaPlayerInterface*>(player.get())->setAudioSink(cache);
+
+    // set data source
+    if (player->setDataSource(url) != NO_ERROR) goto Exit;
+
+    LOGV("prepare");
+    player->prepareAsync();
+
+    LOGV("wait for prepare");
+    if (cache->wait() != NO_ERROR) goto Exit;
+
+    LOGV("start");
+    player->start();
+
+    LOGV("wait for playback complete");
+    if (cache->wait() != NO_ERROR) goto Exit;
+
+    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);
+
+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)
+{
+    LOGV("decode(%d, %lld, %lld)", fd, offset, length);
+    sp<MemoryBase> mem;
+    sp<MediaPlayerBase> player;
+
+    player_type playerType = getPlayerType(fd, offset, length);
+    LOGV("player type = %d", playerType);
+
+    // create the right type of player
+    sp<AudioCache> cache = new AudioCache("decode_fd");
+    player = android::createPlayer(playerType, cache.get(), cache->notify);
+    if (player == NULL) goto Exit;
+    if (player->hardwareOutput()) goto Exit;
+
+    static_cast<MediaPlayerInterface*>(player.get())->setAudioSink(cache);
+
+    // set data source
+    if (player->setDataSource(fd, offset, length) != NO_ERROR) goto Exit;
+
+    LOGV("prepare");
+    player->prepareAsync();
+
+    LOGV("wait for prepare");
+    if (cache->wait() != NO_ERROR) goto Exit;
+
+    LOGV("start");
+    player->start();
+
+    LOGV("wait for playback complete");
+    if (cache->wait() != NO_ERROR) goto Exit;
+
+    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);
+
+Exit:
+    if (player != 0) player->reset();
+    ::close(fd);
+    return mem;
+}
+
+#undef LOG_TAG
+#define LOG_TAG "AudioSink"
+MediaPlayerService::AudioOutput::AudioOutput()
+{
+    mTrack = 0;
+    mStreamType = AudioTrack::MUSIC;
+    mLeftVolume = 1.0;
+    mRightVolume = 1.0;
+    mLatency = 0;
+    mMsecsPerFrame = 0;
+}
+
+MediaPlayerService::AudioOutput::~AudioOutput()
+{
+    close();
+}
+
+ssize_t MediaPlayerService::AudioOutput::bufferSize() const
+{
+    if (mTrack == 0) return NO_INIT;
+    return mTrack->frameCount() * mTrack->channelCount() * sizeof(int16_t);
+}
+
+ssize_t MediaPlayerService::AudioOutput::frameCount() const
+{
+    if (mTrack == 0) return NO_INIT;
+    return mTrack->frameCount();
+}
+
+ssize_t MediaPlayerService::AudioOutput::channelCount() const
+{
+    if (mTrack == 0) return NO_INIT;
+    return mTrack->channelCount();
+}
+
+ssize_t MediaPlayerService::AudioOutput::frameSize() const
+{
+    if (mTrack == 0) return NO_INIT;
+    return mTrack->channelCount() * sizeof(int16_t);
+}
+
+uint32_t MediaPlayerService::AudioOutput::latency () const
+{
+    return mLatency;
+}
+
+float MediaPlayerService::AudioOutput::msecsPerFrame() const
+{
+    return mMsecsPerFrame;
+}
+
+status_t MediaPlayerService::AudioOutput::open(uint32_t sampleRate, int channelCount, int bufferCount)
+{
+    LOGV("open(%u, %d, %d)", sampleRate, channelCount, bufferCount);
+    if (mTrack) close();
+
+    AudioTrack *t = new AudioTrack(mStreamType, sampleRate, AudioSystem::PCM_16_BIT, channelCount, bufferCount);
+    if ((t == 0) || (t->initCheck() != NO_ERROR)) {
+        LOGE("Unable to create audio track");
+        delete t;
+        return NO_INIT;
+    }
+
+    LOGV("setVolume");
+    t->setVolume(mLeftVolume, mRightVolume);
+    mMsecsPerFrame = 1.e3 / (float) sampleRate;
+    mLatency = (mMsecsPerFrame * bufferCount * t->frameCount()) + kDriverLatencyInMsecs;
+    mTrack = t;
+    return NO_ERROR;
+}
+
+void MediaPlayerService::AudioOutput::start()
+{
+    LOGV("start");
+    if (mTrack) {
+        mTrack->setVolume(mLeftVolume, mRightVolume);
+        mTrack->start();
+    }
+}
+
+ssize_t MediaPlayerService::AudioOutput::write(const void* buffer, size_t size)
+{
+    //LOGV("write(%p, %u)", buffer, size);
+    if (mTrack) return mTrack->write(buffer, size);
+    return NO_INIT;
+}
+
+void MediaPlayerService::AudioOutput::stop()
+{
+    LOGV("stop");
+    if (mTrack) mTrack->stop();
+}
+
+void MediaPlayerService::AudioOutput::flush()
+{
+    LOGV("flush");
+    if (mTrack) mTrack->flush();
+}
+
+void MediaPlayerService::AudioOutput::pause()
+{
+    LOGV("pause");
+    if (mTrack) mTrack->pause();
+}
+
+void MediaPlayerService::AudioOutput::close()
+{
+    LOGV("close");
+    delete mTrack;
+    mTrack = 0;
+}
+
+void MediaPlayerService::AudioOutput::setVolume(float left, float right)
+{
+    LOGV("setVolume(%f, %f)", left, right);
+    mLeftVolume = left;
+    mRightVolume = right;
+    if (mTrack) {
+        mTrack->setVolume(left, right);
+    }
+}
+
+#undef LOG_TAG
+#define LOG_TAG "AudioCache"
+MediaPlayerService::AudioCache::AudioCache(const char* name) :
+    mChannelCount(0), mFrameCount(0), mSampleRate(0), mSize(0),
+    mError(NO_ERROR), mCommandComplete(false)
+{
+    // create ashmem heap
+    mHeap = new MemoryHeapBase(kDefaultHeapSize, 0, name);
+}
+
+uint32_t MediaPlayerService::AudioCache::latency () const
+{
+    return 0;
+}
+
+float MediaPlayerService::AudioCache::msecsPerFrame() const
+{
+    return mMsecsPerFrame;
+}
+
+status_t MediaPlayerService::AudioCache::open(uint32_t sampleRate, int channelCount, int bufferCount)
+{
+    LOGV("open(%u, %d, %d)", sampleRate, channelCount, bufferCount);
+   if (mHeap->getHeapID() < 0) return NO_INIT;
+   mSampleRate = sampleRate;
+   mChannelCount = channelCount;
+    mMsecsPerFrame = 1.e3 / (float) sampleRate;
+    return NO_ERROR;
+}
+
+ssize_t MediaPlayerService::AudioCache::write(const void* buffer, size_t size)
+{
+    LOGV("write(%p, %u)", buffer, size);
+    if ((buffer == 0) || (size == 0)) return size;
+
+    uint8_t* p = static_cast<uint8_t*>(mHeap->getBase());
+    if (p == NULL) return NO_INIT;
+    p += mSize;
+    LOGV("memcpy(%p, %p, %u)", p, buffer, size);
+    memcpy(p, buffer, size);
+    mSize += size;
+    return size;
+}
+
+// call with lock held
+status_t MediaPlayerService::AudioCache::wait()
+{
+    Mutex::Autolock lock(mLock);
+    if (!mCommandComplete) {
+        mSignal.wait(mLock);
+    }
+    mCommandComplete = false;
+
+    if (mError == NO_ERROR) {
+        LOGV("wait - success");
+    } else {
+        LOGV("wait - error");
+    }
+    return mError;
+}
+
+void MediaPlayerService::AudioCache::notify(void* cookie, int msg, int ext1, int ext2)
+{
+    LOGV("notify(%p, %d, %d, %d)", cookie, msg, ext1, ext2);
+    AudioCache* p = static_cast<AudioCache*>(cookie);
+
+    // ignore buffering messages
+    if (msg == MEDIA_BUFFERING_UPDATE) return;
+
+    // set error condition
+    if (msg == MEDIA_ERROR) {
+        LOGE("Error %d, %d occurred", ext1, ext2);
+        p->mError = ext1;
+    }
+
+    // wake up thread
+    LOGV("wakeup thread");
+    p->mCommandComplete = true;
+    p->mSignal.signal();
+}
+
+}; // namespace android
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
new file mode 100644
index 0000000..c2007cb
--- /dev/null
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -0,0 +1,222 @@
+/*
+**
+** Copyright 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_MEDIAPLAYERSERVICE_H
+#define ANDROID_MEDIAPLAYERSERVICE_H
+
+#include <utils.h>
+#include <utils/KeyedVector.h>
+#include <ui/SurfaceComposerClient.h>
+
+#include <media/IMediaPlayerService.h>
+#include <media/MediaPlayerInterface.h>
+
+class SkBitmap;
+
+namespace android {
+
+#define CALLBACK_ANTAGONIZER 0
+#if CALLBACK_ANTAGONIZER
+class Antagonizer {
+public:
+    Antagonizer(notify_callback_f cb, void* client);
+    void start() { mActive = true; }
+    void stop() { mActive = false; }
+    void kill();
+private:
+    static const int interval;
+    Antagonizer();
+    static int callbackThread(void* cookie);
+    Mutex               mLock;
+    Condition           mCondition;
+    bool                mExit;
+    bool                mActive;
+    void*               mClient;
+    notify_callback_f   mCb;
+};
+#endif
+
+class MediaPlayerService : public BnMediaPlayerService
+{
+    class Client;
+
+    class AudioOutput : public MediaPlayerBase::AudioSink
+    {
+    public:
+                                AudioOutput();
+        virtual                 ~AudioOutput();
+
+        virtual bool            ready() const { return mTrack != NULL; }
+        virtual bool            realtime() const { return true; }
+        virtual ssize_t         bufferSize() const;
+        virtual ssize_t         frameCount() const;
+        virtual ssize_t         channelCount() const;
+        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 void            start();
+        virtual ssize_t         write(const void* buffer, size_t size);
+        virtual void            stop();
+        virtual void            flush();
+        virtual void            pause();
+        virtual void            close();
+                void            setAudioStreamType(int streamType) { mStreamType = streamType; }
+                void            setVolume(float left, float right);
+        virtual status_t        dump(int fd, const Vector<String16>& args) const;
+    private:
+        AudioTrack*             mTrack;
+        int                     mStreamType;
+        float                   mLeftVolume;
+        float                   mRightVolume;
+        float                   mMsecsPerFrame;
+        uint32_t                mLatency;
+        static const uint32_t   kDriverLatencyInMsecs;
+    };
+
+    class AudioCache : public MediaPlayerBase::AudioSink
+    {
+    public:
+                                AudioCache(const char* name);
+        virtual                 ~AudioCache() {}
+
+        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         frameCount() const { return mFrameCount; }
+        virtual ssize_t         channelCount() const { return mChannelCount; }
+        virtual ssize_t         frameSize() const { return ssize_t(mChannelCount * sizeof(int16_t)); }
+        virtual uint32_t        latency() const;
+        virtual float           msecsPerFrame() const;
+        virtual status_t        open(uint32_t sampleRate, int channelCount, int bufferCount=1);
+        virtual void            start() {}
+        virtual ssize_t         write(const void* buffer, size_t size);
+        virtual void            stop() {}
+        virtual void            flush() {}
+        virtual void            pause() {}
+        virtual void            close() {}
+                void            setAudioStreamType(int streamType) {}
+                void            setVolume(float left, float right) {}
+                uint32_t        sampleRate() const { return mSampleRate; }
+                size_t          size() const { return mSize; }
+                status_t        wait();
+
+                sp<IMemoryHeap> getHeap() const { return mHeap; }
+
+        static  void            notify(void* cookie, int msg, int ext1, int ext2);
+        virtual status_t        dump(int fd, const Vector<String16>& args) const;
+
+    private:
+                                AudioCache();
+
+        Mutex               mLock;
+        Condition           mSignal;
+        sp<MemoryHeapBase>  mHeap;
+        float               mMsecsPerFrame;
+        ssize_t             mChannelCount;
+        ssize_t             mFrameCount;
+        uint32_t            mSampleRate;
+        uint32_t            mSize;
+        int                 mError;
+        bool                mCommandComplete;
+    };
+
+public:
+    static  void                instantiate();
+
+    // IMediaPlayerService interface
+    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 status_t            dump(int fd, const Vector<String16>& args);
+
+            void                removeClient(wp<Client> client);
+
+private:
+
+    class Client : public BnMediaPlayer {
+
+        // IMediaPlayer interface
+        virtual void            disconnect();
+        virtual status_t        setVideoSurface(const sp<ISurface>& surface);
+        virtual status_t        prepareAsync();
+        virtual status_t        start();
+        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);
+        virtual status_t        reset();
+        virtual status_t        setAudioStreamType(int type);
+        virtual status_t        setLooping(int loop);
+        virtual status_t        setVolume(float leftVolume, float rightVolume);
+
+        sp<MediaPlayerBase>     createPlayer(player_type playerType);
+                status_t        setDataSource(const char *url);
+                status_t        setDataSource(int fd, int64_t offset, int64_t length);
+        static  void            notify(void* cookie, int msg, int ext1, int ext2);
+
+                pid_t           pid() const { return mPid; }
+        virtual status_t        dump(int fd, const Vector<String16>& args) const;
+
+    private:
+        friend class MediaPlayerService;
+                                Client( const sp<MediaPlayerService>& service,
+                                        pid_t pid,
+                                        int32_t connId,
+                                        const sp<IMediaPlayerClient>& client);
+                                Client();
+        virtual                 ~Client();
+
+                void            deletePlayer();
+
+        sp<MediaPlayerBase>     getPlayer() const { Mutex::Autolock lock(mLock); return mPlayer; }
+
+        mutable     Mutex                       mLock;
+                    sp<MediaPlayerBase>         mPlayer;
+                    sp<MediaPlayerService>      mService;
+                    sp<IMediaPlayerClient>      mClient;
+                    sp<AudioOutput>             mAudioOutput;
+                    pid_t                       mPid;
+                    status_t                    mStatus;
+                    bool                        mLoop;
+                    int32_t                     mConnId;
+#if CALLBACK_ANTAGONIZER
+                    Antagonizer*                mAntagonizer;
+#endif
+    };
+
+// ----------------------------------------------------------------------------
+
+                            MediaPlayerService();
+    virtual                 ~MediaPlayerService();
+
+    mutable     Mutex                       mLock;
+                SortedVector< wp<Client> >  mClients;
+                int32_t                     mNextConnId;
+};
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_MEDIAPLAYERSERVICE_H
+
diff --git a/media/libmediaplayerservice/MidiFile.cpp b/media/libmediaplayerservice/MidiFile.cpp
new file mode 100644
index 0000000..538f7d4
--- /dev/null
+++ b/media/libmediaplayerservice/MidiFile.cpp
@@ -0,0 +1,572 @@
+/* MidiFile.cpp
+**
+** Copyright 2007, 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 "MidiFile"
+#include "utils/Log.h"
+
+#include <stdio.h>
+#include <assert.h>
+#include <limits.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sched.h>
+#include <utils/threads.h>
+#include <libsonivox/eas_reverb.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "MidiFile.h"
+
+#ifdef HAVE_GETTID
+static pid_t myTid() { return gettid(); }
+#else
+static pid_t myTid() { return getpid(); }
+#endif
+
+// ----------------------------------------------------------------------------
+
+extern pthread_key_t EAS_sigbuskey;
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+// The midi engine buffers are a bit small (128 frames), so we batch them up
+static const int NUM_BUFFERS = 4;
+
+// TODO: Determine appropriate return codes
+static status_t ERROR_NOT_OPEN = -1;
+static status_t ERROR_OPEN_FAILED = -2;
+static status_t ERROR_EAS_FAILURE = -3;
+static status_t ERROR_ALLOCATE_FAILED = -4;
+
+static const S_EAS_LIB_CONFIG* pLibConfig = NULL;
+
+MidiFile::MidiFile() :
+    mEasData(NULL), mEasHandle(NULL), mAudioBuffer(NULL),
+    mPlayTime(-1), mDuration(-1), mState(EAS_STATE_ERROR),
+    mStreamType(AudioTrack::MUSIC), mLoop(false), mExit(false),
+    mPaused(false), mRender(false), mTid(-1)
+{
+    LOGV("constructor");
+
+    mFileLocator.path = NULL;
+    mFileLocator.fd = -1;
+    mFileLocator.offset = 0;
+    mFileLocator.length = 0;
+
+    // get the library configuration and do sanity check
+    if (pLibConfig == NULL)
+        pLibConfig = EAS_Config();
+    if ((pLibConfig == NULL) || (LIB_VERSION != pLibConfig->libVersion)) {
+        LOGE("EAS library/header mismatch");
+        goto Failed;
+    }
+
+    // initialize EAS library
+    if (EAS_Init(&mEasData) != EAS_SUCCESS) {
+        LOGE("EAS_Init failed");
+        goto Failed;
+    }
+
+    // select reverb preset and enable
+    EAS_SetParameter(mEasData, EAS_MODULE_REVERB, EAS_PARAM_REVERB_PRESET, EAS_PARAM_REVERB_CHAMBER);
+    EAS_SetParameter(mEasData, EAS_MODULE_REVERB, EAS_PARAM_REVERB_BYPASS, EAS_FALSE);
+
+    // create playback thread
+    {
+        Mutex::Autolock l(mMutex);
+        createThreadEtc(renderThread, this, "midithread");
+        mCondition.wait(mMutex);
+        LOGV("thread started");
+    }
+
+    // indicate success
+    if (mTid > 0) {
+        LOGV(" render thread(%d) started", mTid);
+        mState = EAS_STATE_READY;
+    }
+
+Failed:
+    return;
+}
+
+status_t MidiFile::initCheck()
+{
+    if (mState == EAS_STATE_ERROR) return ERROR_EAS_FAILURE;
+    return NO_ERROR;
+}
+
+MidiFile::~MidiFile() {
+    LOGV("MidiFile destructor");
+    release();
+}
+
+status_t MidiFile::setDataSource(const char* path)
+{
+    LOGV("MidiFile::setDataSource url=%s", path);
+    Mutex::Autolock lock(mMutex);
+
+    // file still open?
+    if (mEasHandle) {
+        reset_nosync();
+    }
+
+    // open file and set paused state
+    mFileLocator.path = strdup(path);
+    mFileLocator.fd = -1;
+    mFileLocator.offset = 0;
+    mFileLocator.length = 0;
+    EAS_RESULT result = EAS_OpenFile(mEasData, &mFileLocator, &mEasHandle, &mMemFailedVar);
+    if (result == EAS_SUCCESS) {
+        updateState();
+    }
+
+    if (result != EAS_SUCCESS) {
+        LOGE("EAS_OpenFile failed: [%d]", (int)result);
+        mState = EAS_STATE_ERROR;
+        return ERROR_OPEN_FAILED;
+    }
+
+    mState = EAS_STATE_OPEN;
+    mPlayTime = 0;
+    return NO_ERROR;
+}
+
+status_t MidiFile::setSigBusHandlerStructTLSKey(pthread_key_t key)
+{
+    EAS_sigbuskey = key;
+    return 0;
+}
+
+status_t MidiFile::setDataSource(int fd, int64_t offset, int64_t length)
+{
+    LOGV("MidiFile::setDataSource fd=%d", fd);
+    Mutex::Autolock lock(mMutex);
+
+    // file still open?
+    if (mEasHandle) {
+        reset_nosync();
+    }
+
+    // open file and set paused state
+    mFileLocator.fd = dup(fd);
+    mFileLocator.offset = offset;
+    mFileLocator.length = length;
+    EAS_RESULT result = EAS_OpenFile(mEasData, &mFileLocator, &mEasHandle, &mMemFailedVar);
+    updateState();
+
+    if (result != EAS_SUCCESS) {
+        LOGE("EAS_OpenFile failed: [%d]", (int)result);
+        mState = EAS_STATE_ERROR;
+        return ERROR_OPEN_FAILED;
+    }
+
+    mState = EAS_STATE_OPEN;
+    mPlayTime = 0;
+    return NO_ERROR;
+}
+
+status_t MidiFile::prepare()
+{
+    LOGV("MidiFile::prepare");
+    Mutex::Autolock lock(mMutex);
+    if (!mEasHandle) {
+        return ERROR_NOT_OPEN;
+    }
+    EAS_RESULT result;
+    if ((result = EAS_Prepare(mEasData, mEasHandle)) != EAS_SUCCESS) {
+        LOGE("EAS_Prepare failed: [%ld]", result);
+        return ERROR_EAS_FAILURE;
+    }
+    updateState();
+    return NO_ERROR;
+}
+
+status_t MidiFile::prepareAsync()
+{
+    LOGV("MidiFile::prepareAsync");
+    status_t ret = prepare();
+
+    // don't hold lock during callback
+    if (ret == NO_ERROR) {
+        sendEvent(MEDIA_PREPARED);
+    } else {
+        sendEvent(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ret);
+    }
+    return ret;
+}
+
+status_t MidiFile::start()
+{
+    LOGV("MidiFile::start");
+    Mutex::Autolock lock(mMutex);
+    if (!mEasHandle) {
+        return ERROR_NOT_OPEN;
+    }
+
+    // resuming after pause?
+    if (mPaused) {
+        if (EAS_Resume(mEasData, mEasHandle) != EAS_SUCCESS) {
+            return ERROR_EAS_FAILURE;
+        }
+        mPaused = false;
+        updateState();
+    }
+
+    mRender = true;
+
+    // wake up render thread
+    LOGV("  wakeup render thread");
+    mCondition.signal();
+    return NO_ERROR;
+}
+
+status_t MidiFile::stop()
+{
+    LOGV("MidiFile::stop");
+    Mutex::Autolock lock(mMutex);
+    if (!mEasHandle) {
+        return ERROR_NOT_OPEN;
+    }
+    if (!mPaused && (mState != EAS_STATE_STOPPED)) {
+        EAS_RESULT result = EAS_Pause(mEasData, mEasHandle);
+        if (result != EAS_SUCCESS) {
+            LOGE("EAS_Pause returned error %ld", result);
+            return ERROR_EAS_FAILURE;
+        }
+    }
+    mPaused = false;
+    return NO_ERROR;
+}
+
+status_t MidiFile::seekTo(int position)
+{
+    LOGV("MidiFile::seekTo %d", position);
+    // hold lock during EAS calls
+    {
+        Mutex::Autolock lock(mMutex);
+        if (!mEasHandle) {
+            return ERROR_NOT_OPEN;
+        }
+        EAS_RESULT result;
+        if ((result = EAS_Locate(mEasData, mEasHandle, position, false))
+                != EAS_SUCCESS)
+        {
+            LOGE("EAS_Locate returned %ld", result);
+            return ERROR_EAS_FAILURE;
+        }
+        EAS_GetLocation(mEasData, mEasHandle, &mPlayTime);
+    }
+    sendEvent(MEDIA_SEEK_COMPLETE);
+    return NO_ERROR;
+}
+
+status_t MidiFile::pause()
+{
+    LOGV("MidiFile::pause");
+    Mutex::Autolock lock(mMutex);
+    if (!mEasHandle) {
+        return ERROR_NOT_OPEN;
+    }
+    if ((mState == EAS_STATE_PAUSING) || (mState == EAS_STATE_PAUSED)) return NO_ERROR;
+    if (EAS_Pause(mEasData, mEasHandle) != EAS_SUCCESS) {
+        return ERROR_EAS_FAILURE;
+    }
+    mPaused = true;
+    return NO_ERROR;
+}
+
+bool MidiFile::isPlaying()
+{
+    LOGV("MidiFile::isPlaying, mState=%d", int(mState));
+    if (!mEasHandle || mPaused) return false;
+    return (mState == EAS_STATE_PLAY);
+}
+
+status_t MidiFile::getCurrentPosition(int* position)
+{
+    LOGV("MidiFile::getCurrentPosition");
+    if (!mEasHandle) {
+        LOGE("getCurrentPosition(): file not open");
+        return ERROR_NOT_OPEN;
+    }
+    if (mPlayTime < 0) {
+        LOGE("getCurrentPosition(): mPlayTime = %ld", mPlayTime);
+        return ERROR_EAS_FAILURE;
+    }
+    *position = mPlayTime;
+    return NO_ERROR;
+}
+
+status_t MidiFile::getDuration(int* duration)
+{
+
+    LOGV("MidiFile::getDuration");
+    {
+        Mutex::Autolock lock(mMutex);
+        if (!mEasHandle) return ERROR_NOT_OPEN;
+        *duration = mDuration;
+    }
+
+    // if no duration cached, get the duration
+    // don't need a lock here because we spin up a new engine
+    if (*duration < 0) {
+        EAS_I32 temp;
+        EAS_DATA_HANDLE easData = NULL;
+        EAS_HANDLE easHandle = NULL;
+        EAS_RESULT result = EAS_Init(&easData);
+        if (result == EAS_SUCCESS) {
+            result = EAS_OpenFile(easData, &mFileLocator, &easHandle, NULL);
+        }
+        if (result == EAS_SUCCESS) {
+            result = EAS_Prepare(easData, easHandle);
+        }
+        if (result == EAS_SUCCESS) {
+            result = EAS_ParseMetaData(easData, easHandle, &temp);
+        }
+        if (easHandle) {
+            EAS_CloseFile(easData, easHandle);
+        }
+        if (easData) {
+            EAS_Shutdown(easData);
+        }
+
+        if (result != EAS_SUCCESS) {
+            return ERROR_EAS_FAILURE;
+        }
+
+        // cache successful result
+        mDuration = *duration = int(temp);
+    }
+
+    return NO_ERROR;
+}
+
+status_t MidiFile::release()
+{
+    LOGV("MidiFile::release");
+    Mutex::Autolock l(mMutex);
+    reset_nosync();
+
+    // wait for render thread to exit
+    mExit = true;
+    mCondition.signal();
+
+    // wait for thread to exit
+    if (mAudioBuffer) {
+        mCondition.wait(mMutex);
+    }
+
+    // release resources
+    if (mEasData) {
+        EAS_Shutdown(mEasData);
+        mEasData = NULL;
+    }
+    return NO_ERROR;
+}
+
+status_t MidiFile::reset()
+{
+    LOGV("MidiFile::reset");
+    Mutex::Autolock lock(mMutex);
+    return reset_nosync();
+}
+
+// call only with mutex held
+status_t MidiFile::reset_nosync()
+{
+    LOGV("MidiFile::reset_nosync");
+    // close file
+    if (mEasHandle) {
+        EAS_CloseFile(mEasData, mEasHandle);
+        mEasHandle = NULL;
+    }
+    if (mFileLocator.path) {
+        free((void*)mFileLocator.path);
+        mFileLocator.path = NULL;
+    }
+    if (mFileLocator.fd >= 0) {
+        close(mFileLocator.fd);
+    }
+    mFileLocator.fd = -1;
+    mFileLocator.offset = 0;
+    mFileLocator.length = 0;
+
+    mPlayTime = -1;
+    mDuration = -1;
+    mLoop = false;
+    mPaused = false;
+    mRender = false;
+    return NO_ERROR;
+}
+
+status_t MidiFile::setLooping(int loop)
+{
+    LOGV("MidiFile::setLooping");
+    Mutex::Autolock lock(mMutex);
+    if (!mEasHandle) {
+        return ERROR_NOT_OPEN;
+    }
+    loop = loop ? -1 : 0;
+    if (EAS_SetRepeat(mEasData, mEasHandle, loop) != EAS_SUCCESS) {
+        return ERROR_EAS_FAILURE;
+    }
+    return NO_ERROR;
+}
+
+status_t MidiFile::createOutputTrack() {
+    if (mAudioSink->open(pLibConfig->sampleRate,pLibConfig->numChannels, 2) != NO_ERROR) {
+        LOGE("mAudioSink open failed");
+        return ERROR_OPEN_FAILED;
+    }
+    return NO_ERROR;
+}
+
+int MidiFile::renderThread(void* p) {
+
+    return ((MidiFile*)p)->render();
+}
+
+int MidiFile::render() {
+    EAS_RESULT result = EAS_FAILURE;
+    EAS_I32 count;
+    int temp;
+    bool audioStarted = false;
+
+    LOGV("MidiFile::render");
+
+    struct mediasigbushandler sigbushandler;
+
+    // allocate render buffer
+    mAudioBuffer = new EAS_PCM[pLibConfig->mixBufferSize * pLibConfig->numChannels * NUM_BUFFERS];
+    if (!mAudioBuffer) {
+        LOGE("mAudioBuffer allocate failed");
+        goto threadExit;
+    }
+
+    // signal main thread that we started
+    {
+        Mutex::Autolock l(mMutex);
+        mTid = myTid();
+        LOGV("render thread(%d) signal", mTid);
+        mCondition.signal();
+    }
+
+    sigbushandler.handlesigbus = NULL;
+    sigbushandler.sigbusvar = mMemFailedVar;
+    pthread_setspecific(EAS_sigbuskey, &sigbushandler);
+
+    while (1) {
+        mMutex.lock();
+
+        // nothing to render, wait for client thread to wake us up
+        while (!mRender && !mExit)
+        {
+            LOGV("MidiFile::render - signal wait");
+            mCondition.wait(mMutex);
+            LOGV("MidiFile::render - signal rx'd");
+        }
+        if (mExit) {
+            mMutex.unlock();
+            break;
+        }
+
+        // render midi data into the input buffer
+        //LOGV("MidiFile::render - rendering audio");
+        int num_output = 0;
+        EAS_PCM* p = mAudioBuffer;
+        for (int i = 0; i < NUM_BUFFERS; i++) {
+            result = EAS_Render(mEasData, p, pLibConfig->mixBufferSize, &count);
+            if (result != EAS_SUCCESS) {
+                LOGE("EAS_Render returned %ld", result);
+            }
+            p += count * pLibConfig->numChannels;
+            num_output += count * pLibConfig->numChannels * sizeof(EAS_PCM);
+        }
+
+        // update playback state and position
+        // LOGV("MidiFile::render - updating state");
+        EAS_GetLocation(mEasData, mEasHandle, &mPlayTime);
+        EAS_State(mEasData, mEasHandle, &mState);
+        mMutex.unlock();
+
+        // create audio output track if necessary
+        if (!mAudioSink->ready()) {
+            LOGV("MidiFile::render - create output track");
+            if (createOutputTrack() != NO_ERROR)
+                goto threadExit;
+        }
+
+        // Write data to the audio hardware
+        // LOGV("MidiFile::render - writing to audio output");
+        if ((temp = mAudioSink->write(mAudioBuffer, num_output)) < 0) {
+            LOGE("Error in writing:%d",temp);
+            return temp;
+        }
+
+        // start audio output if necessary
+        if (!audioStarted) {
+            //LOGV("MidiFile::render - starting audio");
+            mAudioSink->start();
+            audioStarted = true;
+        }
+
+        // still playing?
+        if ((mState == EAS_STATE_STOPPED) || (mState == EAS_STATE_ERROR) ||
+                (mState == EAS_STATE_PAUSED))
+        {
+            switch(mState) {
+            case EAS_STATE_STOPPED:
+            {
+                LOGV("MidiFile::render - stopped");
+                sendEvent(MEDIA_PLAYBACK_COMPLETE);
+                break;
+            }
+            case EAS_STATE_ERROR:
+            {
+                LOGE("MidiFile::render - error");
+                sendEvent(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN);
+                break;
+            }
+            case EAS_STATE_PAUSED:
+                LOGV("MidiFile::render - paused");
+                break;
+            default:
+                break;
+            }
+            mAudioSink->stop();
+            audioStarted = false;
+            mRender = false;
+        }
+    }
+
+threadExit:
+    mAudioSink.clear();
+    if (mAudioBuffer) {
+        delete [] mAudioBuffer;
+        mAudioBuffer = NULL;
+    }
+    mMutex.lock();
+    mTid = -1;
+    mCondition.signal();
+    mMutex.unlock();
+    return result;
+}
+
+} // end namespace android
diff --git a/media/libmediaplayerservice/MidiFile.h b/media/libmediaplayerservice/MidiFile.h
new file mode 100644
index 0000000..9d2dfdd
--- /dev/null
+++ b/media/libmediaplayerservice/MidiFile.h
@@ -0,0 +1,79 @@
+/*
+**
+** Copyright 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_MIDIFILE_H
+#define ANDROID_MIDIFILE_H
+
+#include <media/MediaPlayerInterface.h>
+#include <media/AudioTrack.h>
+#include <libsonivox/eas.h>
+
+namespace android {
+
+class MidiFile : public MediaPlayerInterface {
+public:
+                        MidiFile();
+                        ~MidiFile();
+
+    virtual status_t    initCheck();
+    virtual status_t    setSigBusHandlerStructTLSKey(pthread_key_t key);
+    virtual status_t    setDataSource(const char* path);
+    virtual status_t    setDataSource(int fd, int64_t offset, int64_t length);
+    virtual status_t    setVideoSurface(const sp<ISurface>& surface) { return UNKNOWN_ERROR; }
+    virtual status_t    prepare();
+    virtual status_t    prepareAsync();
+    virtual status_t    start();
+    virtual status_t    stop();
+    virtual status_t    seekTo(int msec);
+    virtual status_t    pause();
+    virtual bool        isPlaying();
+    virtual status_t    getCurrentPosition(int* msec);
+    virtual status_t    getDuration(int* msec);
+    virtual status_t    release();
+    virtual status_t    reset();
+    virtual status_t    setLooping(int loop);
+    virtual player_type playerType() { return SONIVOX_PLAYER; }
+
+private:
+            status_t    createOutputTrack();
+            status_t    reset_nosync();
+    static  int         renderThread(void*);
+            int         render();
+            void        updateState(){ EAS_State(mEasData, mEasHandle, &mState); }
+
+    Mutex               mMutex;
+    Condition           mCondition;
+    int*                mMemFailedVar;
+    EAS_DATA_HANDLE     mEasData;
+    EAS_HANDLE          mEasHandle;
+    EAS_PCM*            mAudioBuffer;
+    EAS_I32             mPlayTime;
+    EAS_I32             mDuration;
+    EAS_STATE           mState;
+    EAS_FILE            mFileLocator;
+    int                 mStreamType;
+    bool                mLoop;
+    volatile bool       mExit;
+    bool                mPaused;
+    volatile bool       mRender;
+    pid_t               mTid;
+};
+
+}; // namespace android
+
+#endif // ANDROID_MIDIFILE_H
+
diff --git a/media/libmediaplayerservice/VorbisPlayer.cpp b/media/libmediaplayerservice/VorbisPlayer.cpp
new file mode 100644
index 0000000..a0e0f39
--- /dev/null
+++ b/media/libmediaplayerservice/VorbisPlayer.cpp
@@ -0,0 +1,527 @@
+/*
+** Copyright 2007, 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 "VorbisPlayer"
+#include "utils/Log.h"
+
+#include <stdio.h>
+#include <assert.h>
+#include <limits.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sched.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+
+#include "VorbisPlayer.h"
+
+#ifdef HAVE_GETTID
+static pid_t myTid() { return gettid(); }
+#else
+static pid_t myTid() { return getpid(); }
+#endif
+
+// ----------------------------------------------------------------------------
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+// TODO: Determine appropriate return codes
+static status_t ERROR_NOT_OPEN = -1;
+static status_t ERROR_OPEN_FAILED = -2;
+static status_t ERROR_ALLOCATE_FAILED = -4;
+static status_t ERROR_NOT_SUPPORTED = -8;
+static status_t ERROR_NOT_READY = -16;
+static status_t STATE_INIT = 0;
+static status_t STATE_ERROR = 1;
+static status_t STATE_OPEN = 2;
+
+
+VorbisPlayer::VorbisPlayer() :
+    mAudioBuffer(NULL), mPlayTime(-1), mDuration(-1), mState(STATE_ERROR),
+    mStreamType(AudioTrack::MUSIC), mLoop(false), mAndroidLoop(false),
+    mExit(false), mPaused(false), mRender(false), mRenderTid(-1)
+{
+    LOGV("constructor\n");
+    memset(&mVorbisFile, 0, sizeof mVorbisFile);
+}
+
+void VorbisPlayer::onFirstRef()
+{
+    LOGV("onFirstRef");
+    // create playback thread
+    Mutex::Autolock l(mMutex);
+    createThreadEtc(renderThread, this, "vorbis decoder");
+    mCondition.wait(mMutex);
+    if (mRenderTid > 0) {
+        LOGV("render thread(%d) started", mRenderTid);
+        mState = STATE_INIT;
+    }
+}
+
+status_t VorbisPlayer::initCheck()
+{
+    if (mState != STATE_ERROR) return NO_ERROR;
+    return ERROR_NOT_READY;
+}
+
+VorbisPlayer::~VorbisPlayer() {
+    LOGV("VorbisPlayer destructor\n");
+    release();
+}
+
+status_t VorbisPlayer::setDataSource(const char* path)
+{
+    return setdatasource(path, -1, 0, 0x7ffffffffffffffLL); // intentionally less than LONG_MAX
+}
+
+status_t VorbisPlayer::setDataSource(int fd, int64_t offset, int64_t length)
+{
+    return setdatasource(NULL, fd, offset, length);
+}
+
+size_t VorbisPlayer::vp_fread(void *buf, size_t size, size_t nmemb, void *me) {
+    VorbisPlayer *self = (VorbisPlayer*) me;
+
+    long curpos = vp_ftell(me);
+    while (nmemb != 0 && (curpos + size * nmemb) > self->mLength) {
+        nmemb--;
+    }
+    return fread(buf, size, nmemb, self->mFile);
+}
+
+int VorbisPlayer::vp_fseek(void *me, ogg_int64_t off, int whence) {
+    VorbisPlayer *self = (VorbisPlayer*) me;
+    if (whence == SEEK_SET)
+        return fseek(self->mFile, off + self->mOffset, whence);
+    else if (whence == SEEK_CUR)
+        return fseek(self->mFile, off, whence);
+    else if (whence == SEEK_END)
+        return fseek(self->mFile, self->mOffset + self->mLength + off, SEEK_SET);
+    return -1;
+}
+
+int VorbisPlayer::vp_fclose(void *me) {
+    LOGV("vp_fclose");
+    VorbisPlayer *self = (VorbisPlayer*) me;
+    int ret = fclose (self->mFile);
+    self->mFile = NULL;
+    return ret;
+}
+
+long VorbisPlayer::vp_ftell(void *me) {
+    VorbisPlayer *self = (VorbisPlayer*) me;
+    return ftell(self->mFile) - self->mOffset;
+}
+
+status_t VorbisPlayer::setdatasource(const char *path, int fd, int64_t offset, int64_t length)
+{
+    LOGV("setDataSource url=%s, fd=%d\n", path, fd);
+
+    // file still open?
+    Mutex::Autolock l(mMutex);
+    if (mState == STATE_OPEN) {
+        reset_nosync();
+    }
+
+    // open file and set paused state
+    if (path) {
+        mFile = fopen(path, "r");
+    } else {
+        mFile = fdopen(dup(fd), "r");
+    }
+    if (mFile == NULL) {
+        return ERROR_OPEN_FAILED;
+    }
+
+    struct stat sb;
+    int ret;
+    if (path) {
+        ret = stat(path, &sb);
+    } else {
+        ret = fstat(fd, &sb);
+    }
+    if (ret != 0) {
+        mState = STATE_ERROR;
+        fclose(mFile);
+        return ERROR_OPEN_FAILED;
+    }
+    if (sb.st_size > (length + offset)) {
+        mLength = length;
+    } else {
+        mLength = sb.st_size - offset;
+    }
+
+    ov_callbacks callbacks = {
+        (size_t (*)(void *, size_t, size_t, void *))  vp_fread,
+        (int (*)(void *, ogg_int64_t, int))           vp_fseek,
+        (int (*)(void *))                             vp_fclose,
+        (long (*)(void *))                            vp_ftell
+    };
+
+    mOffset = offset;
+    fseek(mFile, offset, SEEK_SET);
+
+    int result = ov_open_callbacks(this, &mVorbisFile, NULL, 0, callbacks);
+    if (result < 0) {
+        LOGE("ov_open() failed: [%d]\n", (int)result);
+        mState = STATE_ERROR;
+        fclose(mFile);
+        return ERROR_OPEN_FAILED;
+    }
+
+    // look for the android loop tag  (for ringtones)
+    char **ptr = ov_comment(&mVorbisFile,-1)->user_comments;
+    while(*ptr) {
+        // does the comment start with ANDROID_LOOP_TAG
+        if(strncmp(*ptr, ANDROID_LOOP_TAG, strlen(ANDROID_LOOP_TAG)) == 0) {
+            // read the value of the tag
+            char *val = *ptr + strlen(ANDROID_LOOP_TAG) + 1;
+            mAndroidLoop = (strncmp(val, "true", 4) == 0);
+        }
+        // we keep parsing even after finding one occurence of ANDROID_LOOP_TAG,
+        // as we could find another one  (the tag might have been appended more than once).
+        ++ptr;
+    }
+    LOGV_IF(mAndroidLoop, "looped sound");
+
+    mState = STATE_OPEN;
+    return NO_ERROR;
+}
+
+status_t VorbisPlayer::prepare()
+{
+    LOGV("prepare\n");
+    if (mState != STATE_OPEN ) {
+        return ERROR_NOT_OPEN;
+    }
+    return NO_ERROR;
+}
+
+status_t VorbisPlayer::prepareAsync() {
+    LOGV("prepareAsync\n");
+    // can't hold the lock here because of the callback
+    // it's safe because we don't change state
+    if (mState != STATE_OPEN ) {
+        sendEvent(MEDIA_ERROR);
+        return NO_ERROR;
+    }
+    sendEvent(MEDIA_PREPARED);
+    return NO_ERROR;
+}
+
+status_t VorbisPlayer::start()
+{
+    LOGV("start\n");
+    Mutex::Autolock l(mMutex);
+    if (mState != STATE_OPEN) {
+        return ERROR_NOT_OPEN;
+    }
+
+    mPaused = false;
+    mRender = true;
+
+    // wake up render thread
+    LOGV("  wakeup render thread\n");
+    mCondition.signal();
+    return NO_ERROR;
+}
+
+status_t VorbisPlayer::stop()
+{
+    LOGV("stop\n");
+    Mutex::Autolock l(mMutex);
+    if (mState != STATE_OPEN) {
+        return ERROR_NOT_OPEN;
+    }
+    mPaused = true;
+    mRender = false;
+    return NO_ERROR;
+}
+
+status_t VorbisPlayer::seekTo(int position)
+{
+    LOGV("seekTo %d\n", position);
+    Mutex::Autolock l(mMutex);
+    if (mState != STATE_OPEN) {
+        return ERROR_NOT_OPEN;
+    }
+
+    int result = ov_time_seek(&mVorbisFile, position);
+    if (result != 0) {
+        LOGE("ov_time_seek() returned %d\n", result);
+        return result;
+    }
+    sendEvent(MEDIA_SEEK_COMPLETE);
+    return NO_ERROR;
+}
+
+status_t VorbisPlayer::pause()
+{
+    LOGV("pause\n");
+    Mutex::Autolock l(mMutex);
+    if (mState != STATE_OPEN) {
+        return ERROR_NOT_OPEN;
+    }
+    mPaused = true;
+    return NO_ERROR;
+}
+
+bool VorbisPlayer::isPlaying()
+{
+    LOGV("isPlaying\n");
+    if (mState == STATE_OPEN) {
+        return mRender;
+    }
+    return false;
+}
+
+status_t VorbisPlayer::getCurrentPosition(int* position)
+{
+    LOGV("getCurrentPosition\n");
+    Mutex::Autolock l(mMutex);
+    if (mState != STATE_OPEN) {
+        LOGE("getCurrentPosition(): file not open");
+        return ERROR_NOT_OPEN;
+    }
+    *position = ov_time_tell(&mVorbisFile);
+    if (*position < 0) {
+        LOGE("getCurrentPosition(): ov_time_tell returned %d", *position);
+        return *position;
+    }
+    return NO_ERROR;
+}
+
+status_t VorbisPlayer::getDuration(int* duration)
+{
+    LOGV("getDuration\n");
+    Mutex::Autolock l(mMutex);
+    if (mState != STATE_OPEN) {
+        return ERROR_NOT_OPEN;
+    }
+
+    int ret = ov_time_total(&mVorbisFile, -1);
+    if (ret == OV_EINVAL) {
+        return -1;
+    }
+
+    *duration = ret;
+    return NO_ERROR;
+}
+
+status_t VorbisPlayer::release()
+{
+    LOGV("release\n");
+    Mutex::Autolock l(mMutex);
+    reset_nosync();
+
+    // TODO: timeout when thread won't exit
+    // wait for render thread to exit
+    if (mRenderTid > 0) {
+        mExit = true;
+        mCondition.signal();
+        mCondition.wait(mMutex);
+    }
+    return NO_ERROR;
+}
+
+status_t VorbisPlayer::reset()
+{
+    LOGV("reset\n");
+    Mutex::Autolock l(mMutex);
+    if (mState != STATE_OPEN) {
+        return NO_ERROR;
+    }
+    return reset_nosync();
+}
+
+// always call with lock held
+status_t VorbisPlayer::reset_nosync()
+{
+    // close file
+    ov_clear(&mVorbisFile); // this also closes the FILE
+    if (mFile != NULL) {
+        LOGV("OOPS! Vorbis didn't close the file");
+        fclose(mFile);
+    }
+    mState = STATE_ERROR;
+
+    mPlayTime = -1;
+    mDuration = -1;
+    mLoop = false;
+    mAndroidLoop = false;
+    mPaused = false;
+    mRender = false;
+    return NO_ERROR;
+}
+
+status_t VorbisPlayer::setLooping(int loop)
+{
+    LOGV("setLooping\n");
+    Mutex::Autolock l(mMutex);
+    mLoop = (loop != 0);
+    return NO_ERROR;
+}
+
+status_t VorbisPlayer::createOutputTrack() {
+    // open audio track
+    vorbis_info *vi = ov_info(&mVorbisFile, -1);
+
+    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) {
+        LOGE("mAudioSink open failed");
+        return ERROR_OPEN_FAILED;
+    }
+    return NO_ERROR;
+}
+
+int VorbisPlayer::renderThread(void* p) {
+    return ((VorbisPlayer*)p)->render();
+}
+
+#define AUDIOBUFFER_SIZE 4096
+
+int VorbisPlayer::render() {
+    int result = -1;
+    int temp;
+    int current_section = 0;
+    bool audioStarted = false;
+
+    LOGV("render\n");
+
+    // allocate render buffer
+    mAudioBuffer = new char[AUDIOBUFFER_SIZE];
+    if (!mAudioBuffer) {
+        LOGE("mAudioBuffer allocate failed\n");
+        goto threadExit;
+    }
+
+    // let main thread know we're ready
+    {
+        Mutex::Autolock l(mMutex);
+        mRenderTid = myTid();
+        mCondition.signal();
+    }
+
+    while (1) {
+        long numread = 0;
+        {
+            Mutex::Autolock l(mMutex);
+
+            // pausing?
+            if (mPaused) {
+                if (mAudioSink->ready()) mAudioSink->pause();
+                mRender = false;
+                audioStarted = false;
+            }
+
+            // nothing to render, wait for client thread to wake us up
+            if (!mExit && !mRender) {
+                LOGV("render - signal wait\n");
+                mCondition.wait(mMutex);
+                LOGV("render - signal rx'd\n");
+            }
+            if (mExit) break;
+
+            // We could end up here if start() is called, and before we get a
+            // chance to run, the app calls stop() or reset(). Re-check render
+            // flag so we don't try to render in stop or reset state.
+            if (!mRender) continue;
+
+            // render vorbis data into the input buffer
+            numread = ov_read(&mVorbisFile, mAudioBuffer, AUDIOBUFFER_SIZE, &current_section);
+            if (numread == 0) {
+                // end of file, do we need to loop?
+                // ...
+                if (mLoop || mAndroidLoop) {
+                    ov_time_seek(&mVorbisFile, 0);
+                    current_section = 0;
+                    numread = ov_read(&mVorbisFile, mAudioBuffer, AUDIOBUFFER_SIZE, &current_section);
+                } else {
+                    sendEvent(MEDIA_PLAYBACK_COMPLETE);
+                    mAudioSink->stop();
+                    audioStarted = false;
+                    mRender = false;
+                    mPaused = true;
+                    int endpos = ov_time_tell(&mVorbisFile);
+
+                    // wait until we're started again
+                    LOGV("playback complete - wait for signal");
+                    mCondition.wait(mMutex);
+                    LOGV("playback complete - signal rx'd");
+                    if (mExit) break;
+
+                    // if we're still at the end, restart from the beginning
+                    if (mState == STATE_OPEN) {
+                        int curpos = ov_time_tell(&mVorbisFile);
+                        if (curpos == endpos) {
+                            ov_time_seek(&mVorbisFile, 0);
+                        }
+                        current_section = 0;
+                        numread = ov_read(&mVorbisFile, mAudioBuffer, AUDIOBUFFER_SIZE, &current_section);
+                    }
+                }
+            }
+        }
+
+        // codec returns negative number on error
+        if (numread < 0) {
+            LOGE("Error in Vorbis decoder");
+            sendEvent(MEDIA_ERROR);
+            break;
+        }
+
+        // create audio output track if necessary
+        if (!mAudioSink->ready()) {
+            LOGV("render - create output track\n");
+            if (createOutputTrack() != NO_ERROR)
+                break;
+        }
+
+        // Write data to the audio hardware
+        if ((temp = mAudioSink->write(mAudioBuffer, numread)) < 0) {
+            LOGE("Error in writing:%d",temp);
+            result = temp;
+            break;
+        }
+
+        // start audio output if necessary
+        if (!audioStarted && !mPaused && !mExit) {
+            LOGV("render - starting audio\n");
+            mAudioSink->start();
+            audioStarted = true;
+        }
+    }
+
+threadExit:
+    mAudioSink.clear();
+    if (mAudioBuffer) {
+        delete [] mAudioBuffer;
+        mAudioBuffer = NULL;
+    }
+
+    // tell main thread goodbye
+    Mutex::Autolock l(mMutex);
+    mRenderTid = -1;
+    mCondition.signal();
+    return result;
+}
+
+} // end namespace android
diff --git a/media/libmediaplayerservice/VorbisPlayer.h b/media/libmediaplayerservice/VorbisPlayer.h
new file mode 100644
index 0000000..c30dc1b
--- /dev/null
+++ b/media/libmediaplayerservice/VorbisPlayer.h
@@ -0,0 +1,91 @@
+/*
+**
+** Copyright 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_VORBISPLAYER_H
+#define ANDROID_VORBISPLAYER_H
+
+#include <utils/threads.h>
+
+#include <media/MediaPlayerInterface.h>
+#include <media/AudioTrack.h>
+
+#include "ivorbiscodec.h"
+#include "ivorbisfile.h"
+
+#define ANDROID_LOOP_TAG "ANDROID_LOOP"
+
+namespace android {
+
+class VorbisPlayer : public MediaPlayerInterface {
+public:
+                        VorbisPlayer();
+                        ~VorbisPlayer();
+
+    virtual void        onFirstRef();
+    virtual status_t    initCheck();
+    virtual status_t    setDataSource(const char* path);
+    virtual status_t    setDataSource(int fd, int64_t offset, int64_t length);
+    virtual status_t    setVideoSurface(const sp<ISurface>& surface) { return UNKNOWN_ERROR; }
+    virtual status_t    prepare();
+    virtual status_t    prepareAsync();
+    virtual status_t    start();
+    virtual status_t    stop();
+    virtual status_t    seekTo(int msec);
+    virtual status_t    pause();
+    virtual bool        isPlaying();
+    virtual status_t    getCurrentPosition(int* msec);
+    virtual status_t    getDuration(int* msec);
+    virtual status_t    release();
+    virtual status_t    reset();
+    virtual status_t    setLooping(int loop);
+    virtual player_type playerType() { return VORBIS_PLAYER; }
+
+private:
+            status_t    setdatasource(const char *path, int fd, int64_t offset, int64_t length);
+            status_t    reset_nosync();
+            status_t    createOutputTrack();
+    static  int         renderThread(void*);
+            int         render();
+
+    static  size_t      vp_fread(void *, size_t, size_t, void *);
+    static  int         vp_fseek(void *, ogg_int64_t, int);
+    static  int         vp_fclose(void *);
+    static  long        vp_ftell(void *);
+
+    Mutex               mMutex;
+    Condition           mCondition;
+    FILE*               mFile;
+    int64_t             mOffset;
+    int64_t             mLength;
+    OggVorbis_File      mVorbisFile;
+    char*               mAudioBuffer;
+    int                 mPlayTime;
+    int                 mDuration;
+    status_t            mState;
+    int                 mStreamType;
+    bool                mLoop;
+    bool                mAndroidLoop;
+    volatile bool       mExit;
+    bool                mPaused;
+    volatile bool       mRender;
+    pid_t               mRenderTid;
+};
+
+}; // namespace android
+
+#endif // ANDROID_VORBISPLAYER_H
+
diff --git a/media/mediaserver/Android.mk b/media/mediaserver/Android.mk
new file mode 100644
index 0000000..c681698
--- /dev/null
+++ b/media/mediaserver/Android.mk
@@ -0,0 +1,22 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+	main_mediaserver.cpp 
+
+LOCAL_SHARED_LIBRARIES := \
+	libaudioflinger \
+	libcameraservice \
+	libmediaplayerservice \
+	libutils
+
+base := $(LOCAL_PATH)/../..
+
+LOCAL_C_INCLUDES := \
+    $(base)/libs/audioflinger \
+    $(base)/camera/libcameraservice \
+    $(base)/media/libmediaplayerservice
+
+LOCAL_MODULE:= mediaserver
+
+include $(BUILD_EXECUTABLE)
diff --git a/media/mediaserver/main_mediaserver.cpp b/media/mediaserver/main_mediaserver.cpp
new file mode 100644
index 0000000..6954b63
--- /dev/null
+++ b/media/mediaserver/main_mediaserver.cpp
@@ -0,0 +1,45 @@
+/*
+**
+** Copyright 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.
+*/
+
+// System headers required for setgroups, etc.
+#include <sys/types.h>
+#include <unistd.h>
+#include <grp.h>
+
+#include <utils/IPCThreadState.h>
+#include <utils/ProcessState.h>
+#include <utils/IServiceManager.h>
+#include <utils/Log.h>
+
+#include <AudioFlinger.h>
+#include <CameraService.h>
+#include <MediaPlayerService.h>
+#include <private/android_filesystem_config.h>
+
+using namespace android;
+
+int main(int argc, char** argv)
+{
+    sp<ProcessState> proc(ProcessState::self());
+    sp<IServiceManager> sm = defaultServiceManager();
+    LOGI("ServiceManager: %p", sm.get());
+    AudioFlinger::instantiate();
+    MediaPlayerService::instantiate();
+    CameraService::instantiate();
+    ProcessState::self()->startThreadPool();
+    IPCThreadState::self()->joinThreadPool();
+}