auto import from //depot/cupcake/@135843
diff --git a/media/java/android/drm/mobile1/DrmConstraintInfo.java b/media/java/android/drm/mobile1/DrmConstraintInfo.java
new file mode 100644
index 0000000..50ae8bd
--- /dev/null
+++ b/media/java/android/drm/mobile1/DrmConstraintInfo.java
@@ -0,0 +1,96 @@
+/*
+ * 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.
+ */
+
+package android.drm.mobile1;
+
+import java.util.Date;
+
+/**
+ * This class provides interfaces to access the DRM constraint.
+ */
+public class DrmConstraintInfo {
+    /**
+     * The constraint of count.
+     */
+    private int count;
+
+    /**
+     * The constraint of start date.
+     */
+    private long startDate;
+
+    /**
+     * The constraint of end date.
+     */
+    private long endDate;
+
+    /**
+     * The constraint of interval.
+     */
+    private long interval;
+
+    /**
+     * Construct the DrmConstraint.
+     */
+    DrmConstraintInfo() {
+        count = -1;
+        startDate = -1;
+        endDate = -1;
+        interval = -1;
+    }
+
+    /**
+     * Get the count constraint.
+     *
+     * @return the count or -1 if no limit.
+     */
+    public int getCount() {
+        return count;
+    }
+
+    /**
+     * Get the start date constraint.
+     *
+     * @return the start date or null if no limit.
+     */
+    public Date getStartDate() {
+        if (startDate == -1)
+            return null;
+
+        return new Date(startDate);
+    }
+
+    /**
+     * Get the end date constraint.
+     *
+     * @return the end date or null if no limit.
+     */
+    public Date getEndDate() {
+        if (endDate == -1)
+            return null;
+
+        return new Date(endDate);
+    }
+
+    /**
+     * Get the Interval constraint.
+     *
+     * @return the interval or -1 if no limit.
+     */
+    public long getInterval() {
+        return interval;
+    }
+}
diff --git a/media/java/android/drm/mobile1/DrmException.java b/media/java/android/drm/mobile1/DrmException.java
new file mode 100644
index 0000000..7b06c92
--- /dev/null
+++ b/media/java/android/drm/mobile1/DrmException.java
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+package android.drm.mobile1;
+
+import java.io.IOException;
+
+/**
+ * A DrmException is thrown to report errors specific to handle DRM content and rights.
+ */
+public class DrmException extends Exception
+{
+    // TODO: add more specific DRM error codes.
+    
+    private DrmException() {
+    }
+    
+    public DrmException(String message) {
+        super(message);
+    }
+}
diff --git a/media/java/android/drm/mobile1/DrmRawContent.java b/media/java/android/drm/mobile1/DrmRawContent.java
new file mode 100644
index 0000000..046b84a
--- /dev/null
+++ b/media/java/android/drm/mobile1/DrmRawContent.java
@@ -0,0 +1,464 @@
+/*
+ * 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.
+ */
+
+package android.drm.mobile1;
+
+import java.io.*;
+
+/**
+ * This class provides interfaces to access the DRM raw content.
+ */
+public class DrmRawContent {
+    /**
+     * The "application/vnd.oma.drm.message" mime type.
+     */
+    public static final String DRM_MIMETYPE_MESSAGE_STRING = "application/vnd.oma.drm.message";
+
+    /**
+     * The "application/vnd.oma.drm.content" mime type.
+     */
+    public static final String DRM_MIMETYPE_CONTENT_STRING = "application/vnd.oma.drm.content";
+
+    /**
+     * The DRM delivery type: Forward-Lock
+     */
+    public static final int DRM_FORWARD_LOCK = 1;
+
+    /**
+     * The DRM delivery type: Combined Delivery
+     */
+    public static final int DRM_COMBINED_DELIVERY = 2;
+
+    /**
+     * The DRM delivery type: Separate Delivery
+     */
+    public static final int DRM_SEPARATE_DELIVERY = 3;
+
+    /**
+     * The DRM delivery type: Separate Delivery in DRM message
+     */
+    public static final int DRM_SEPARATE_DELIVERY_DM = 4;
+
+    /**
+     * The DRM media content length is unknown currently
+     */
+    public static final int DRM_UNKNOWN_DATA_LEN = -1;
+
+
+    /**
+     * The id of "application/vnd.oma.drm.message" mime type.
+     */
+    private static final int DRM_MIMETYPE_MESSAGE = 1;
+
+    /**
+     * The id of "application/vnd.oma.drm.content" mime type.
+     */
+    private static final int DRM_MIMETYPE_CONTENT = 2;
+
+    /**
+     * Successful operation.
+     */
+    private static final int JNI_DRM_SUCCESS = 0;
+
+    /**
+     * General failure.
+     */
+    private static final int JNI_DRM_FAILURE = -1;
+
+    /**
+     * Indicates the end of the DRM content is reached.
+     */
+    private static final int JNI_DRM_EOF = -2;
+
+    /**
+     * The media content length is unknown from native method
+     */
+    private static final int JNI_DRM_UNKNOWN_DATA_LEN = -3;
+
+    /**
+     * The member to save the original InputStream data.
+     */
+    private BufferedInputStream inData;
+
+    /**
+     * The member to save the original InputStream data length.
+     */
+    private int inDataLen;
+
+    /**
+     * The unique id to this DRM content. It will be initialized
+     * in constructor by native method. And it will not be changed
+     * after initialization.
+     */
+    private int id;
+
+    /**
+     * The rights issuer address of this DRM object.
+     */
+    private String rightsIssuer;
+
+    /**
+     * The media content type of this DRM object.
+     */
+    private String mediaType;
+
+    /**
+     * The delivery method type of this DRM object.
+     */
+    private int rawType;
+
+
+    /**
+     * Construct a DrmRawContent object.
+     *
+     * @param inRawdata     object of DRM raw data stream.
+     * @param len           the length of raw data can be read.
+     * @param mimeTypeStr   the mime type of the DRM content.
+     */
+    public DrmRawContent(InputStream inRawdata, int len, String mimeTypeStr) throws DrmException, IOException {
+        int mimeType;
+
+        id = -1;
+        inData = new BufferedInputStream(inRawdata, 1024);
+        inDataLen = len;
+
+        if (DRM_MIMETYPE_MESSAGE_STRING.equals(mimeTypeStr))
+            mimeType = DRM_MIMETYPE_MESSAGE;
+        else if (DRM_MIMETYPE_CONTENT_STRING.equals(mimeTypeStr))
+            mimeType = DRM_MIMETYPE_CONTENT;
+        else
+            throw new IllegalArgumentException("mimeType must be DRM_MIMETYPE_MESSAGE or DRM_MIMETYPE_CONTENT");
+
+        if (len <= 0)
+            throw new IllegalArgumentException("len must be > 0");
+
+        /* call native method to initialize this DRM content */
+        id = nativeConstructDrmContent(inData, inDataLen, mimeType);
+
+        if (JNI_DRM_FAILURE == id)
+            throw new DrmException("nativeConstructDrmContent() returned JNI_DRM_FAILURE");
+
+        /* init the rights issuer field. */
+        rightsIssuer = nativeGetRightsAddress();
+
+        /* init the raw content type. */
+        rawType = nativeGetDeliveryMethod();
+        if (JNI_DRM_FAILURE == rawType)
+            throw new DrmException("nativeGetDeliveryMethod() returned JNI_DRM_FAILURE");
+
+        /* init the media content type. */
+        mediaType = nativeGetContentType();
+        if (null == mediaType)
+            throw new DrmException("nativeGetContentType() returned null");
+    }
+
+    /**
+     * Get rights address from raw Seperate Delivery content.
+     *
+     * @return the string of the rights issuer address,
+     *         or null if no rights issuer.
+     */
+    public String getRightsAddress() {
+        return rightsIssuer;
+    }
+
+    /**
+     * Get the type of the raw DRM content.
+     *
+     * @return one of the following delivery type of this DRM content:
+     *              #DRM_FORWARD_LOCK
+     *              #DRM_COMBINED_DELIVERY
+     *              #DRM_SEPARATE_DELIVERY
+     *              #DRM_SEPARATE_DELIVERY_DM
+     */
+    public int getRawType() {
+        return rawType;
+    }
+
+    /**
+     * Get one InputStream object to read decrypted content.
+     *
+     * @param rights        the rights object contain decrypted key.
+     *
+     * @return the InputStream object of decrypted media content.
+     */
+    public InputStream getContentInputStream(DrmRights rights) {
+        if (null == rights)
+            throw new NullPointerException();
+
+        return new DrmInputStream(rights);
+    }
+
+    /**
+     * Get the type of the decrypted media content.
+     *
+     * @return the decrypted media content type of this DRM content.
+     */
+    public String getContentType() {
+        return mediaType;
+    }
+
+    /**
+     * Get the length of the decrypted media content.
+     *
+     * @param rights        the rights object contain decrypted key.
+     *
+     * @return the length of the decrypted media content.
+     *         #DRM_UNKNOWN_DATA_LEN if the length is unknown currently.
+     */
+    public int getContentLength(DrmRights rights) throws DrmException {
+        /**
+         * Because currently the media object associate with rights object
+         * has been handled in native logic, so here it is not need to deal
+         * the rights. But for the apps, it is mandatory for user to get
+         * the rights object before get the media content length.
+         */
+        if (null == rights)
+            throw new NullPointerException();
+
+        int mediaLen = nativeGetContentLength();
+
+        if (JNI_DRM_FAILURE == mediaLen)
+            throw new DrmException("nativeGetContentLength() returned JNI_DRM_FAILURE");
+
+        if (JNI_DRM_UNKNOWN_DATA_LEN == mediaLen)
+            return DRM_UNKNOWN_DATA_LEN;
+
+        return mediaLen;
+    }
+
+    /**
+     * This class provide a InputStream to the DRM media content.
+     */
+    class DrmInputStream extends InputStream
+    {
+        /**
+         * The flag to indicate whether this stream is closed or not.
+         */
+        private boolean isClosed;
+
+        /**
+         * The offset of this DRM content to be reset.
+         */
+        private int offset;
+
+        /**
+         * A byte of data to be readed.
+         */
+        private byte[] b;
+
+        /**
+         * Construct a DrmInputStream instance.
+         */
+        public DrmInputStream(DrmRights rights) {
+            /**
+             * Because currently the media object associate with rights object
+             * has been handled in native logic, so here it is not need to deal
+             * the rights. But for the apps, it is mandatory for user to get
+             * the rights object before get the media content data.
+             */
+
+            isClosed = false;
+            offset = 0;
+            b = new byte[1];
+        }
+
+        /* Non-javadoc
+         * @see java.io.InputStream#available()
+         */
+        public int available() throws IOException {
+            /* call native method to get this DRM decrypted media content length */
+            int len = nativeGetContentLength();
+
+            if (JNI_DRM_FAILURE == len)
+                throw new IOException();
+
+            /* if the length is unknown, just return 0 for available value */
+            if (JNI_DRM_UNKNOWN_DATA_LEN == len)
+                return 0;
+
+            int availableLen = len - offset;
+            if (availableLen < 0)
+                throw new IOException();
+
+            return availableLen;
+        }
+
+        /* Non-javadoc
+         * @see java.io.InputStream#read()
+         */
+        public int read() throws IOException {
+            int res;
+
+            res = read(b, 0, 1);
+
+            if (-1 == res)
+                return -1;
+
+            return b[0] & 0xff;
+        }
+
+        /* Non-javadoc
+         * @see java.io.InputStream#read(byte)
+         */
+        public int read(byte[] b) throws IOException {
+            return read(b, 0, b.length);
+        }
+
+        /* Non-javadoc
+         * @see java.io.InputStream#read(byte, int, int)
+         */
+        public int read(byte[] b, int off, int len) throws IOException {
+            if (null == b)
+                throw new NullPointerException();
+            if (off < 0 || len < 0 || off + len > b.length)
+                throw new IndexOutOfBoundsException();
+            if (true == isClosed)
+                throw new IOException();
+
+            if (0 == len)
+                return 0;
+
+            len = nativeReadContent(b, off, len, offset);
+
+            if (JNI_DRM_FAILURE == len)
+                throw new IOException();
+            else if (JNI_DRM_EOF == len)
+                return -1;
+
+            offset += len;
+
+            return len;
+        }
+
+        /* Non-javadoc
+         * @see java.io.InputStream#markSupported()
+         */
+        public boolean markSupported() {
+            return false;
+        }
+
+        /* Non-javadoc
+         * @see java.io.InputStream#mark(int)
+         */
+        public void mark(int readlimit) {
+        }
+
+        /* Non-javadoc
+         * @see java.io.InputStream#reset()
+         */
+        public void reset() throws IOException {
+            throw new IOException();
+        }
+
+        /* Non-javadoc
+         * @see java.io.InputStream#skip()
+         */
+        public long skip(long n) throws IOException {
+            return 0;
+        }
+
+        /* Non-javadoc
+         * @see java.io.InputStream#close()
+         */
+        public void close() {
+            isClosed = true;
+        }
+    }
+
+    /**
+     * native method: construct a DRM content according the mime type.
+     *
+     * @param data      input DRM content data to be parsed.
+     * @param len       the length of the data.
+     * @param mimeType  the mime type of this DRM content. the value of this field includes:
+     *                      #DRM_MIMETYPE_MESSAGE
+     *                      #DRM_MIMETYPE_CONTENT
+     *
+     * @return #the id of the DRM content if succeed.
+     *         #JNI_DRM_FAILURE if fail.
+     */
+    private native int nativeConstructDrmContent(InputStream data, int len, int mimeType);
+
+    /**
+     * native method: get this DRM content rights issuer.
+     *
+     * @return the address of rights issuer if in case of separate delivery.
+     *         null if not separete delivery, or otherwise.
+     */
+    private native String nativeGetRightsAddress();
+
+    /**
+     * native method: get this DRM content delivery type.
+     *
+     * @return the delivery method, the value may be one of the following:
+     *              #DRM_FORWARD_LOCK
+     *              #DRM_COMBINED_DELIVERY
+     *              #DRM_SEPARATE_DELIVERY
+     *              #DRM_SEPARATE_DELIVERY_DM
+     *         #JNI_DRM_FAILURE if fail.
+     */
+    private native int nativeGetDeliveryMethod();
+
+    /**
+     * native method: get a piece of media content data.
+     *
+     * @param buf       the buffer to save DRM media content data.
+     * @param bufOff    the offset of the buffer to start to save data.
+     * @param len       the number of byte to read.
+     * @param mediaOff  the offset of the media content data to start to read.
+     *
+     * @return the length of the media content data has been read.
+     *         #JNI_DRM_EOF if reach to end of the media content.
+     *         #JNI_DRM_FAILURE if fail.
+     */
+    private native int nativeReadContent(byte[] buf, int bufOff, int len, int mediaOff);
+
+    /**
+     * native method: get this DRM content type.
+     *
+     * @return the decrypted media content type.
+     *         null if fail.
+     */
+    private native String nativeGetContentType();
+
+    /**
+     * native method: get this DRM decrypted media content length.
+     *
+     * @return the length of decrypted media content.
+     *         #JNI_DRM_FAILURE if fail.
+     *         #JNI_DRM_UNKNOWN_DATA_LEN if the length is unknown currently.
+     */
+    private native int nativeGetContentLength();
+
+    /**
+     * The finalizer of the DRMRawContent. Do some cleanup.
+     */
+    protected native void finalize();
+
+
+    /**
+     * Load the shared library to link the native methods.
+     */
+    static {
+        try {
+            System.loadLibrary("drm1_jni");
+        }
+        catch (UnsatisfiedLinkError ule) {
+            System.err.println("WARNING: Could not load libdrm1_jni.so");
+        }
+    }
+}
diff --git a/media/java/android/drm/mobile1/DrmRights.java b/media/java/android/drm/mobile1/DrmRights.java
new file mode 100644
index 0000000..bcccb6a
--- /dev/null
+++ b/media/java/android/drm/mobile1/DrmRights.java
@@ -0,0 +1,136 @@
+/*
+ * 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.
+ */
+
+package android.drm.mobile1;
+
+/**
+ * This class provides interfaces to access the DRM rights.
+ */
+public class DrmRights {
+    /**
+     * The DRM permission of play.
+     */
+    public static final int DRM_PERMISSION_PLAY = 1;
+
+    /**
+     * The DRM permission of display.
+     */
+    public static final int DRM_PERMISSION_DISPLAY = 2;
+
+    /**
+     * The DRM permission of execute.
+     */
+    public static final int DRM_PERMISSION_EXECUTE = 3;
+
+    /**
+     * The DRM permission of print.
+     */
+    public static final int DRM_PERMISSION_PRINT = 4;
+
+    /**
+     * Successful operation.
+     */
+    private static final int JNI_DRM_SUCCESS = 0;
+
+    /**
+     * General failure.
+     */
+    private static final int JNI_DRM_FAILURE = -1;
+
+    /**
+     * The uid of this rights object.
+     */
+    private String roId = "";
+
+
+    /**
+     * Construct the DrmRights.
+     */
+    public DrmRights() {
+    }
+
+    /**
+     * Get the constraint of the given permission on this rights object.
+     *
+     * @param permission    the given permission.
+     *
+     * @return a DrmConstraint instance.
+     */
+    public DrmConstraintInfo getConstraint(int permission) {
+        DrmConstraintInfo c = new DrmConstraintInfo();
+
+        /* call native method to get latest constraint information */
+        int res = nativeGetConstraintInfo(permission, c);
+
+        if (JNI_DRM_FAILURE == res)
+            return null;
+
+        return c;
+    }
+
+    /**
+     * Consume the rights of the given permission.
+     *
+     * @param permission    the given permission.
+     *
+     * @return true if consume success.
+     *         false if consume failure.
+     */
+    public boolean consumeRights(int permission) {
+        /* call native method to consume and update rights */
+        int res = nativeConsumeRights(permission);
+
+        if (JNI_DRM_FAILURE == res)
+            return false;
+
+        return true;
+    }
+
+
+    /**
+     * native method: get the constraint information of the given permission.
+     *
+     * @param permission    the given permission.
+     * @param constraint    the instance of constraint.
+     *
+     * @return #JNI_DRM_SUCCESS if succeed.
+     *         #JNI_DRM_FAILURE if fail.
+     */
+    private native int nativeGetConstraintInfo(int permission, DrmConstraintInfo constraint);
+
+    /**
+     * native method: consume the rights of the given permission.
+     *
+     * @param permission    the given permission.
+     *
+     * @return #JNI_DRM_SUCCESS if succeed.
+     *         #JNI_DRM_FAILURE if fail.
+     */
+    private native int nativeConsumeRights(int permission);
+
+
+    /**
+     * Load the shared library to link the native methods.
+     */
+    static {
+        try {
+            System.loadLibrary("drm1_jni");
+        }
+        catch (UnsatisfiedLinkError ule) {
+            System.err.println("WARNING: Could not load libdrm1_jni.so");
+        }
+    }
+}
diff --git a/media/java/android/drm/mobile1/DrmRightsManager.java b/media/java/android/drm/mobile1/DrmRightsManager.java
new file mode 100644
index 0000000..1bc36ec
--- /dev/null
+++ b/media/java/android/drm/mobile1/DrmRightsManager.java
@@ -0,0 +1,255 @@
+/*
+ * 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.
+ */
+
+package android.drm.mobile1;
+
+import java.io.*;
+import java.util.*;
+
+/**
+ * This class provides interfaces to access the DRM right manager.
+ */
+public class DrmRightsManager {
+    /**
+     * The "application/vnd.oma.drm.rights+xml" mime type.
+     */
+    public static final String DRM_MIMETYPE_RIGHTS_XML_STRING = "application/vnd.oma.drm.rights+xml";
+
+    /**
+     * The "application/vnd.oma.drm.rights+wbxml" mime type.
+     */
+    public static final String DRM_MIMETYPE_RIGHTS_WBXML_STRING = "application/vnd.oma.drm.rights+wbxml";
+
+    /**
+     * The id of "application/vnd.oma.drm.rights+xml" mime type.
+     */
+    private static final int DRM_MIMETYPE_RIGHTS_XML = 3;
+
+    /**
+     * The id of "application/vnd.oma.drm.rights+wbxml" mime type.
+     */
+    private static final int DRM_MIMETYPE_RIGHTS_WBXML = 4;
+
+    /**
+     * The id of "application/vnd.oma.drm.message" mime type.
+     */
+    private static final int DRM_MIMETYPE_MESSAGE = 1;
+
+    /**
+     * Successful operation.
+     */
+    private static final int JNI_DRM_SUCCESS = 0;
+
+    /**
+     * General failure.
+     */
+    private static final int JNI_DRM_FAILURE = -1;
+
+    /**
+     * The instance of the rights manager.
+     */
+    private static DrmRightsManager singleton = null;
+
+
+    /**
+     * Construct a DrmRightsManager
+     */
+    protected DrmRightsManager() {
+    }
+
+    /**
+     * Get the DrmRightsManager instance.
+     *
+     * @return the instance of DrmRightsManager.
+     */
+    public static synchronized DrmRightsManager getInstance() {
+        if (singleton == null) {
+            singleton = new DrmRightsManager();
+        }
+
+        return singleton;
+    }
+
+    /**
+     * Install one DRM rights and return one instance of DrmRights.
+     *
+     * @param rightsData    raw rights data.
+     * @param mimeTypeStr   the mime type of the rights object.
+     *
+     * @return the instance of the installed DrmRights.
+     */
+    public synchronized DrmRights installRights(InputStream rightsData, int len, String mimeTypeStr) throws DrmException, IOException {
+        int mimeType = 0;
+
+        if (DRM_MIMETYPE_RIGHTS_XML_STRING.equals(mimeTypeStr))
+            mimeType = DRM_MIMETYPE_RIGHTS_XML;
+        else if (DRM_MIMETYPE_RIGHTS_WBXML_STRING.equals(mimeTypeStr))
+            mimeType = DRM_MIMETYPE_RIGHTS_WBXML;
+        else if (DrmRawContent.DRM_MIMETYPE_MESSAGE_STRING.equals(mimeTypeStr))
+            mimeType = DRM_MIMETYPE_MESSAGE;
+        else
+            throw new IllegalArgumentException("mimeType must be DRM_MIMETYPE_RIGHTS_XML or DRM_MIMETYPE_RIGHTS_WBXML or DRM_MIMETYPE_MESSAGE");
+
+        if (len <= 0)
+            return null;
+
+        DrmRights rights = new DrmRights();
+
+        /* call native method to install this rights object. */
+        int res = nativeInstallDrmRights(rightsData, len, mimeType, rights);
+
+        if (JNI_DRM_FAILURE == res)
+            throw new DrmException("nativeInstallDrmRights() returned JNI_DRM_FAILURE");
+
+        return rights;
+    }
+
+    /**
+     * Query DRM rights of specified DRM raw content.
+     *
+     * @param content       raw content object.
+     *
+     * @return the instance of DrmRights, or null if there is no rights.
+     */
+    public synchronized DrmRights queryRights(DrmRawContent content) {
+        DrmRights rights = new DrmRights();
+
+        /* call native method to query the rights */
+        int res = nativeQueryRights(content, rights);
+
+        if (JNI_DRM_FAILURE == res)
+            return null;
+
+        return rights;
+    }
+
+    /**
+     * Get the list of all DRM rights saved in local client.
+     *
+     * @return the list of all the rights object.
+     */
+    public synchronized List getRightsList() {
+        List rightsList = new ArrayList();
+
+        /* call native method to get how many rights object in current agent */
+        int num = nativeGetNumOfRights();
+
+        if (JNI_DRM_FAILURE == num)
+            return null;
+
+        if (num > 0) {
+            DrmRights[] rightsArray = new DrmRights[num];
+            int i;
+
+            for (i = 0; i < num; i++)
+                rightsArray[i] = new DrmRights();
+
+            /* call native method to get all the rights information */
+            num = nativeGetRightsList(rightsArray, num);
+
+            if (JNI_DRM_FAILURE == num)
+                return null;
+
+            /* add all rights informations to ArrayList */
+            for (i = 0; i < num; i++)
+                rightsList.add(rightsArray[i]);
+        }
+
+        return rightsList;
+    }
+
+    /**
+     * Delete the specified DRM rights object.
+     *
+     * @param rights    the specified rights object to be deleted.
+     */
+    public synchronized void deleteRights(DrmRights rights) {
+        /* call native method to delete the specified rights object */
+        int res = nativeDeleteRights(rights);
+
+        if (JNI_DRM_FAILURE == res)
+            return;
+    }
+
+
+    /**
+     * native method: install rights object to local client.
+     *
+     * @param data      input DRM rights object data to be installed.
+     * @param len       the length of the data.
+     * @param mimeType  the mime type of this DRM rights object. the value of this field includes:
+     *                      #DRM_MIMETYPE_RIGHTS_XML
+     *                      #DRM_MIMETYPE_RIGHTS_WBXML
+     * @parma rights    the instance of DRMRights to be filled.
+     *
+     * @return #JNI_DRM_SUCCESS if succeed.
+     *         #JNI_DRM_FAILURE if fail.
+     */
+    private native int nativeInstallDrmRights(InputStream data, int len, int mimeType, DrmRights rights);
+
+    /**
+     * native method: query the given DRM content's rights object.
+     *
+     * @param content   the given DRM content.
+     * @param rights    the instance of rights to set if have.
+     *
+     * @return #JNI_DRM_SUCCESS if succeed.
+     *         #JNI_DRM_FAILURE if fail.
+     */
+    private native int nativeQueryRights(DrmRawContent content, DrmRights rights);
+
+    /**
+     * native method: get how many rights object in current DRM agent.
+     *
+     * @return the number of the rights object.
+     *         #JNI_DRM_FAILURE if fail.
+     */
+    private native int nativeGetNumOfRights();
+
+    /**
+     * native method: get all the rights object in current local agent.
+     *
+     * @param rights    the array instance of rights object.
+     * @param numRights how many rights can be saved.
+     *
+     * @return the number of the rights object has been gotten.
+     *         #JNI_DRM_FAILURE if fail.
+     */
+    private native int nativeGetRightsList(DrmRights[] rights, int numRights);
+
+    /**
+     * native method: delete a specified rights object.
+     *
+     * @param rights    the specified rights object to be deleted.
+     *
+     * @return #JNI_DRM_SUCCESS if succeed.
+     *         #JNI_DRM_FAILURE if fail.
+     */
+    private native int nativeDeleteRights(DrmRights rights);
+
+
+    /**
+     * Load the shared library to link the native methods.
+     */
+    static {
+        try {
+            System.loadLibrary("drm1_jni");
+        }
+        catch (UnsatisfiedLinkError ule) {
+            System.err.println("WARNING: Could not load libdrm1_jni.so");
+        }
+    }
+}
diff --git a/media/java/android/drm/mobile1/package.html b/media/java/android/drm/mobile1/package.html
new file mode 100644
index 0000000..1c9bf9d
--- /dev/null
+++ b/media/java/android/drm/mobile1/package.html
@@ -0,0 +1,5 @@
+<html>
+<body>
+    {@hide}
+</body>
+</html>
diff --git a/media/java/android/media/AmrInputStream.java b/media/java/android/media/AmrInputStream.java
new file mode 100644
index 0000000..d40ca5aa
--- /dev/null
+++ b/media/java/android/media/AmrInputStream.java
@@ -0,0 +1,141 @@
+/*
+ * 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.
+ */
+
+package android.media;
+
+import android.util.Config;
+import android.util.Log;
+
+import java.io.InputStream;
+import java.io.IOException;
+
+
+/**
+ * AmrInputStream
+ * @hide
+ */
+public final class AmrInputStream extends InputStream
+{    
+    static {
+        System.loadLibrary("media_jni");
+    }
+    
+    private final static String TAG = "AmrInputStream";
+    
+    // frame is 20 msec at 8.000 khz
+    private final static int SAMPLES_PER_FRAME = 8000 * 20 / 1000;
+    
+    // pcm input stream
+    private InputStream mInputStream;
+    
+    // native handle
+    private int mGae;
+    
+    // result amr stream
+    private byte[] mBuf = new byte[SAMPLES_PER_FRAME * 2];
+    private int mBufIn = 0;
+    private int mBufOut = 0;
+    
+    // helper for bytewise read()
+    private byte[] mOneByte = new byte[1];
+    
+    /**
+     * Create a new AmrInputStream, which converts 16 bit PCM to AMR
+     * @param inputStream InputStream containing 16 bit PCM.
+     */
+    public AmrInputStream(InputStream inputStream) {
+        mInputStream = inputStream;
+        mGae = GsmAmrEncoderNew();
+        GsmAmrEncoderInitialize(mGae);
+    }
+
+    @Override
+    public int read() throws IOException {
+        int rtn = read(mOneByte, 0, 1);
+        return rtn == 1 ? (0xff & mOneByte[0]) : -1;
+    }
+    
+    @Override
+    public int read(byte[] b) throws IOException {
+        return read(b, 0, b.length);
+    }
+
+    @Override
+    public int read(byte[] b, int offset, int length) throws IOException {
+        if (mGae == 0) throw new IllegalStateException("not open");
+        
+        // local buffer of amr encoded audio empty
+        if (mBufOut >= mBufIn) {
+            // reset the buffer
+            mBufOut = 0;
+            mBufIn = 0;
+            
+            // fetch a 20 msec frame of pcm
+            for (int i = 0; i < SAMPLES_PER_FRAME * 2; ) {
+                int n = mInputStream.read(mBuf, i, SAMPLES_PER_FRAME * 2 - i);
+                if (n == -1) return -1;
+                i += n;
+            }
+            
+            // encode it
+            mBufIn = GsmAmrEncoderEncode(mGae, mBuf, 0, mBuf, 0);
+        }
+        
+        // return encoded audio to user
+        if (length > mBufIn - mBufOut) length = mBufIn - mBufOut;
+        System.arraycopy(mBuf, mBufOut, b, offset, length);
+        mBufOut += length;
+        
+        return length;
+    }
+
+    @Override
+    public void close() throws IOException {
+        try {
+            if (mInputStream != null) mInputStream.close();
+        } finally {
+            mInputStream = null;
+            try {
+                if (mGae != 0) GsmAmrEncoderCleanup(mGae);
+            } finally {
+                try {
+                    if (mGae != 0) GsmAmrEncoderDelete(mGae);
+                } finally {
+                    mGae = 0;
+                }
+            }
+        }
+    }
+
+    @Override
+    protected void finalize() throws Throwable {
+        if (mGae != 0) {
+            close();
+            throw new IllegalStateException("someone forgot to close AmrInputStream");
+        }
+    }
+    
+    //
+    // AudioRecord JNI interface
+    //
+    private static native int GsmAmrEncoderNew();
+    private static native void GsmAmrEncoderInitialize(int gae);
+    private static native int GsmAmrEncoderEncode(int gae,
+            byte[] pcm, int pcmOffset, byte[] amr, int amrOffset) throws IOException;
+    private static native void GsmAmrEncoderCleanup(int gae);
+    private static native void GsmAmrEncoderDelete(int gae);
+
+}
diff --git a/media/java/android/media/AsyncPlayer.java b/media/java/android/media/AsyncPlayer.java
new file mode 100644
index 0000000..35f0409
--- /dev/null
+++ b/media/java/android/media/AsyncPlayer.java
@@ -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.
+ */
+
+package android.media;
+
+import android.content.Context;
+import android.net.Uri;
+import android.os.PowerManager;
+import android.util.Log;
+
+import java.io.IOException;
+import java.lang.IllegalStateException;
+
+/**
+ * Plays a series of audio URIs, but does all the hard work on another thread
+ * so that any slowness with preparing or loading doesn't block the calling thread.
+ */
+public class AsyncPlayer {
+    private static final int PLAY = 1;
+    private static final int STOP = 2;
+
+    private static final class Command {
+        Command next;
+        int code;
+        Context context;
+        Uri uri;
+        boolean looping;
+        int stream;
+
+        public String toString() {
+            return "{ code=" + code + " looping=" + looping + " stream=" + stream
+                    + " uri=" + uri + " }";
+        }
+    }
+
+    private final class Thread extends java.lang.Thread {
+        Thread() {
+            super("AsyncPlayer-" + mTag);
+        }
+
+        public void run() {
+            while (true) {
+                Command cmd = null;
+
+                synchronized (mLock) {
+                    if (mHead != null) {
+                        cmd = mHead;
+                        mHead = cmd.next;
+                        if (mTail == cmd) {
+                            mTail = null;
+                        }
+                    }
+                }
+
+                switch (cmd.code) {
+                case PLAY:
+                    try {
+                        // Preparing can be slow, so if there is something else
+                        // is playing, let it continue until we're done, so there
+                        // is less of a glitch.
+                        MediaPlayer player = new MediaPlayer();
+                        player.setAudioStreamType(cmd.stream);
+                        player.setDataSource(cmd.context, cmd.uri);
+                        player.setLooping(cmd.looping);
+                        player.prepare();
+                        player.start();
+                        if (mPlayer != null) {
+                            mPlayer.release();
+                        }
+                        mPlayer = player;
+                    }
+                    catch (IOException e) {
+                        Log.w(mTag, "error loading sound for " + cmd.uri, e);
+                    } catch (IllegalStateException e) {
+                        Log.w(mTag, "IllegalStateException (content provider died?) " + cmd.uri, e);
+                    }
+                    break;
+                case STOP:
+                    if (mPlayer != null) {
+                        mPlayer.stop();
+                        mPlayer.release();
+                        mPlayer = null;
+                    } else {
+                        Log.w(mTag, "STOP command without a player");
+                    }
+                    break;
+                }
+
+                synchronized (mLock) {
+                    if (mHead == null) {
+                        // nothing left to do, quit
+                        // doing this check after we're done prevents the case where they
+                        // added it during the operation from spawning two threads and
+                        // trying to do them in parallel.
+                        mThread = null;
+                        releaseWakeLock();
+                        return;
+                    }
+                }
+            }
+        }
+    }
+
+    private String mTag;
+    private Command mHead;
+    private Command mTail;
+    private Thread mThread;
+    private MediaPlayer mPlayer;
+    private Object mLock = new Object();
+    private PowerManager.WakeLock mWakeLock;
+
+    // The current state according to the caller.  Reality lags behind
+    // because of the asynchronous nature of this class.
+    private int mState = STOP;
+
+    /**
+     * Construct an AsyncPlayer object.
+     *
+     * @param tag a string to use for debugging
+     */
+    public AsyncPlayer(String tag) {
+        if (tag != null) {
+            mTag = tag;
+        } else {
+            mTag = "AsyncPlayer";
+        }
+    }
+
+    /**
+     * Start playing the sound.  It will actually start playing at some
+     * point in the future.  There are no guarantees about latency here.
+     * Calling this before another audio file is done playing will stop
+     * that one and start the new one.
+     *
+     * @param context Your application's context.
+     * @param uri The URI to play.  (see {@link MediaPlayer#setDataSource(Context, Uri)})
+     * @param looping Whether the audio should loop forever.  
+     *          (see {@link MediaPlayer#setLooping(boolean)})
+     * @param stream the AudioStream to use.
+     *          (see {@link MediaPlayer#setAudioStreamType(int)})
+     */
+    public void play(Context context, Uri uri, boolean looping, int stream) {
+        Command cmd = new Command();
+        cmd.code = PLAY;
+        cmd.context = context;
+        cmd.uri = uri;
+        cmd.looping = looping;
+        cmd.stream = stream;
+        synchronized (mLock) {
+            enqueueLocked(cmd);
+            mState = PLAY;
+        }
+    }
+    
+    /**
+     * Stop a previously played sound.  It can't be played again or unpaused
+     * at this point.  Calling this multiple times has no ill effects.
+     */
+    public void stop() {
+        synchronized (mLock) {
+            // This check allows stop to be called multiple times without starting
+            // a thread that ends up doing nothing.
+            if (mState != STOP) {
+                Command cmd = new Command();
+                cmd.code = STOP;
+                enqueueLocked(cmd);
+                mState = STOP;
+            }
+        }
+    }
+
+    private void enqueueLocked(Command cmd) {
+        if (mTail == null) {
+            mHead = cmd;
+        } else {
+            mTail.next = cmd;
+        }
+        mTail = cmd;
+        if (mThread == null) {
+            acquireWakeLock();
+            mThread = new Thread();
+            mThread.start();
+        }
+    }
+
+    /**
+     * We want to hold a wake lock while we do the prepare and play.  The stop probably is
+     * optional, but it won't hurt to have it too.  The problem is that if you start a sound
+     * while you're holding a wake lock (e.g. an alarm starting a notification), you want the
+     * sound to play, but if the CPU turns off before mThread gets to work, it won't.  The
+     * simplest way to deal with this is to make it so there is a wake lock held while the
+     * thread is starting or running.  You're going to need the WAKE_LOCK permission if you're
+     * going to call this.
+     *
+     * This must be called before the first time play is called.
+     *
+     * @hide
+     */
+    public void setUsesWakeLock(Context context) {
+        if (mWakeLock != null || mThread != null) {
+            // if either of these has happened, we've already played something.
+            // and our releases will be out of sync.
+            throw new RuntimeException("assertion failed mWakeLock=" + mWakeLock
+                    + " mThread=" + mThread);
+        }
+        PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
+        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, mTag);
+    }
+
+    private void acquireWakeLock() {
+        if (mWakeLock != null) {
+            mWakeLock.acquire();
+        }
+    }
+
+    private void releaseWakeLock() {
+        if (mWakeLock != null) {
+            mWakeLock.release();
+        }
+    }
+}
+
diff --git a/media/java/android/media/AudioFormat.java b/media/java/android/media/AudioFormat.java
new file mode 100644
index 0000000..0732b61
--- /dev/null
+++ b/media/java/android/media/AudioFormat.java
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+
+package android.media;
+
+/**
+ * The AudioFormat class is used to access a number of audio format and
+ * channel configuration constants. They are for instance used
+ * in __link AudioTrack} and __link AudioRecord}.
+ * 
+ */
+public class AudioFormat {
+    
+    //---------------------------------------------------------
+    // Constants
+    //--------------------
+    /** Invalid audio data format */
+    public static final int ENCODING_INVALID = 0;
+    /** Default audio data format */
+    public static final int ENCODING_DEFAULT = 1;
+    /** Audio data format: PCM 16 bit per sample */
+    public static final int ENCODING_PCM_16BIT = 2; // accessed by native code
+    /** Audio data format: PCM 8 bit per sample */
+    public static final int ENCODING_PCM_8BIT = 3;  // accessed by native code
+
+    /** Invalid audio channel configuration */
+    public static final int CHANNEL_CONFIGURATION_INVALID   = 0;
+    /** Default audio channel configuration */
+    public static final int CHANNEL_CONFIGURATION_DEFAULT   = 1;
+    /** Mono audio configuration */
+    public static final int CHANNEL_CONFIGURATION_MONO      = 2;
+    /** Stereo (2 channel) audio configuration */
+    public static final int CHANNEL_CONFIGURATION_STEREO    = 3;
+
+}
+
+
+
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
new file mode 100644
index 0000000..077d016
--- /dev/null
+++ b/media/java/android/media/AudioManager.java
@@ -0,0 +1,1086 @@
+/*
+ * 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.
+ */
+
+package android.media;
+
+import android.annotation.SdkConstant;
+import android.annotation.SdkConstant.SdkConstantType;
+import android.content.Context;
+import android.database.ContentObserver;
+import android.os.Binder;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.provider.Settings;
+import android.util.Log;
+
+/**
+ * AudioManager provides access to volume and ringer mode control.
+ * <p>
+ * Use <code>Context.getSystemService(Context.AUDIO_SERVICE)</code> to get
+ * an instance of this class.
+ */
+public class AudioManager {
+
+    private final Context mContext;
+    private final Handler mHandler;
+
+    // used to listen for updates to the sound effects settings so we don't
+    // poll it for every UI sound
+    private ContentObserver mContentObserver;
+
+
+    private static String TAG = "AudioManager";
+    private static boolean DEBUG = false;
+    private static boolean localLOGV = DEBUG || android.util.Config.LOGV;
+
+    /**
+     * Broadcast intent, a hint for applications that audio is about to become
+     * 'noisy' due to a change in audio outputs. For example, this intent may
+     * be sent when a wired headset is unplugged, or when an A2DP audio
+     * sink is disconnected, and the audio system is about to automatically
+     * switch audio route to the speaker. Applications that are controlling
+     * audio streams may consider pausing, reducing volume or some other action
+     * on receipt of this intent so as not to surprise the user with audio
+     * from the speaker.
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_AUDIO_BECOMING_NOISY = "android.media.AUDIO_BECOMING_NOISY";
+
+    /**
+     * Sticky broadcast intent action indicating that the ringer mode has
+     * changed. Includes the new ringer mode.
+     *
+     * @see #EXTRA_RINGER_MODE
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String RINGER_MODE_CHANGED_ACTION = "android.media.RINGER_MODE_CHANGED";
+
+    /**
+     * The new ringer mode.
+     *
+     * @see #RINGER_MODE_CHANGED_ACTION
+     * @see #RINGER_MODE_NORMAL
+     * @see #RINGER_MODE_SILENT
+     * @see #RINGER_MODE_VIBRATE
+     */
+    public static final String EXTRA_RINGER_MODE = "android.media.EXTRA_RINGER_MODE";
+
+    /**
+     * Broadcast intent action indicating that the vibrate setting has
+     * changed. Includes the vibrate type and its new setting.
+     *
+     * @see #EXTRA_VIBRATE_TYPE
+     * @see #EXTRA_VIBRATE_SETTING
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String VIBRATE_SETTING_CHANGED_ACTION = "android.media.VIBRATE_SETTING_CHANGED";
+
+    /**
+     * @hide Broadcast intent when the volume for a particular stream type changes.
+     * Includes the stream and the new volume
+     *
+     * @see #EXTRA_VOLUME_STREAM_TYPE
+     * @see #EXTRA_VOLUME_STREAM_VALUE
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String VOLUME_CHANGED_ACTION = "android.media.VOLUME_CHANGED_ACTION";
+
+    /**
+     * The new vibrate setting for a particular type.
+     *
+     * @see #VIBRATE_SETTING_CHANGED_ACTION
+     * @see #EXTRA_VIBRATE_TYPE
+     * @see #VIBRATE_SETTING_ON
+     * @see #VIBRATE_SETTING_OFF
+     * @see #VIBRATE_SETTING_ONLY_SILENT
+     */
+    public static final String EXTRA_VIBRATE_SETTING = "android.media.EXTRA_VIBRATE_SETTING";
+
+    /**
+     * The vibrate type whose setting has changed.
+     *
+     * @see #VIBRATE_SETTING_CHANGED_ACTION
+     * @see #VIBRATE_TYPE_NOTIFICATION
+     * @see #VIBRATE_TYPE_RINGER
+     */
+    public static final String EXTRA_VIBRATE_TYPE = "android.media.EXTRA_VIBRATE_TYPE";
+
+    /**
+     * @hide The stream type for the volume changed intent.
+     */
+    public static final String EXTRA_VOLUME_STREAM_TYPE = "android.media.EXTRA_VOLUME_STREAM_TYPE";
+
+    /**
+     * @hide The volume associated with the stream for the volume changed intent.
+     */
+    public static final String EXTRA_VOLUME_STREAM_VALUE =
+        "android.media.EXTRA_VOLUME_STREAM_VALUE";
+
+    /** The audio stream for phone calls */
+    public static final int STREAM_VOICE_CALL = AudioSystem.STREAM_VOICE_CALL;
+    /** The audio stream for system sounds */
+    public static final int STREAM_SYSTEM = AudioSystem.STREAM_SYSTEM;
+    /** The audio stream for the phone ring */
+    public static final int STREAM_RING = AudioSystem.STREAM_RING;
+    /** The audio stream for music playback */
+    public static final int STREAM_MUSIC = AudioSystem.STREAM_MUSIC;
+    /** The audio stream for alarms */
+    public static final int STREAM_ALARM = AudioSystem.STREAM_ALARM;
+    /** The audio stream for notifications */
+    public static final int STREAM_NOTIFICATION = AudioSystem.STREAM_NOTIFICATION;
+    /** @hide The audio stream for phone calls when connected to bluetooth */
+    public static final int STREAM_BLUETOOTH_SCO = AudioSystem.STREAM_BLUETOOTH_SCO;
+    /** Number of audio streams */
+    /**
+     * @deprecated Use AudioSystem.getNumStreamTypes() instead
+     */
+    public static final int NUM_STREAMS = AudioSystem.NUM_STREAMS;
+
+
+    /** @hide Maximum volume index values for audio streams */
+    public static final int[] MAX_STREAM_VOLUME = new int[] {
+        6,  // STREAM_VOICE_CALL
+        8,  // STREAM_SYSTEM
+        8,  // STREAM_RING
+        16, // STREAM_MUSIC
+        8,  // STREAM_ALARM
+        8,  // STREAM_NOTIFICATION
+        15, // STREAM_BLUETOOTH_SCO
+    };
+
+    /**  @hide Default volume index values for audio streams */
+    public static final int[] DEFAULT_STREAM_VOLUME = new int[] {
+        4,  // STREAM_VOICE_CALL
+        5,  // STREAM_SYSTEM
+        5,  // STREAM_RING
+        11, // STREAM_MUSIC
+        6,  // STREAM_ALARM
+        5,  // STREAM_NOTIFICATION
+        7   // STREAM_BLUETOOTH_SCO
+    };
+
+    /**
+     * Increase the ringer volume.
+     *
+     * @see #adjustVolume(int, int)
+     * @see #adjustStreamVolume(int, int, int)
+     */
+    public static final int ADJUST_RAISE = 1;
+
+    /**
+     * Decrease the ringer volume.
+     *
+     * @see #adjustVolume(int, int)
+     * @see #adjustStreamVolume(int, int, int)
+     */
+    public static final int ADJUST_LOWER = -1;
+
+    /**
+     * Maintain the previous ringer volume. This may be useful when needing to
+     * show the volume toast without actually modifying the volume.
+     *
+     * @see #adjustVolume(int, int)
+     * @see #adjustStreamVolume(int, int, int)
+     */
+    public static final int ADJUST_SAME = 0;
+
+    // Flags should be powers of 2!
+
+    /**
+     * Show a toast containing the current volume.
+     *
+     * @see #adjustStreamVolume(int, int, int)
+     * @see #adjustVolume(int, int)
+     * @see #setStreamVolume(int, int, int)
+     * @see #setRingerMode(int)
+     */
+    public static final int FLAG_SHOW_UI = 1 << 0;
+
+    /**
+     * Whether to include ringer modes as possible options when changing volume.
+     * For example, if true and volume level is 0 and the volume is adjusted
+     * with {@link #ADJUST_LOWER}, then the ringer mode may switch the silent or
+     * vibrate mode.
+     * <p>
+     * By default this is on for the ring stream. If this flag is included,
+     * this behavior will be present regardless of the stream type being
+     * affected by the ringer mode.
+     * 
+     * @see #adjustVolume(int, int)
+     * @see #adjustStreamVolume(int, int, int)
+     */
+    public static final int FLAG_ALLOW_RINGER_MODES = 1 << 1;
+
+    /**
+     * Whether to play a sound when changing the volume.
+     * <p>
+     * If this is given to {@link #adjustVolume(int, int)} or
+     * {@link #adjustSuggestedStreamVolume(int, int, int)}, it may be ignored
+     * in some cases (for example, the decided stream type is not
+     * {@link AudioManager#STREAM_RING}, or the volume is being adjusted
+     * downward).
+     *
+     * @see #adjustStreamVolume(int, int, int)
+     * @see #adjustVolume(int, int)
+     * @see #setStreamVolume(int, int, int)
+     */
+    public static final int FLAG_PLAY_SOUND = 1 << 2;
+
+    /**
+     * Removes any sounds/vibrate that may be in the queue, or are playing (related to
+     * changing volume).
+     */
+    public static final int FLAG_REMOVE_SOUND_AND_VIBRATE = 1 << 3;
+
+    /**
+     * Whether to vibrate if going into the vibrate ringer mode.
+     */
+    public static final int FLAG_VIBRATE = 1 << 4;
+
+    /**
+     * Ringer mode that will be silent and will not vibrate. (This overrides the
+     * vibrate setting.)
+     *
+     * @see #setRingerMode(int)
+     * @see #getRingerMode()
+     */
+    public static final int RINGER_MODE_SILENT = 0;
+
+    /**
+     * Ringer mode that will be silent and will vibrate. (This will cause the
+     * phone ringer to always vibrate, but the notification vibrate to only
+     * vibrate if set.)
+     *
+     * @see #setRingerMode(int)
+     * @see #getRingerMode()
+     */
+    public static final int RINGER_MODE_VIBRATE = 1;
+
+    /**
+     * Ringer mode that may be audible and may vibrate. It will be audible if
+     * the volume before changing out of this mode was audible. It will vibrate
+     * if the vibrate setting is on.
+     *
+     * @see #setRingerMode(int)
+     * @see #getRingerMode()
+     */
+    public static final int RINGER_MODE_NORMAL = 2;
+
+    /**
+     * Vibrate type that corresponds to the ringer.
+     *
+     * @see #setVibrateSetting(int, int)
+     * @see #getVibrateSetting(int)
+     * @see #shouldVibrate(int)
+     */
+    public static final int VIBRATE_TYPE_RINGER = 0;
+
+    /**
+     * Vibrate type that corresponds to notifications.
+     *
+     * @see #setVibrateSetting(int, int)
+     * @see #getVibrateSetting(int)
+     * @see #shouldVibrate(int)
+     */
+    public static final int VIBRATE_TYPE_NOTIFICATION = 1;
+
+    /**
+     * Vibrate setting that suggests to never vibrate.
+     *
+     * @see #setVibrateSetting(int, int)
+     * @see #getVibrateSetting(int)
+     */
+    public static final int VIBRATE_SETTING_OFF = 0;
+
+    /**
+     * Vibrate setting that suggests to vibrate when possible.
+     *
+     * @see #setVibrateSetting(int, int)
+     * @see #getVibrateSetting(int)
+     */
+    public static final int VIBRATE_SETTING_ON = 1;
+
+    /**
+     * Vibrate setting that suggests to only vibrate when in the vibrate ringer
+     * mode.
+     *
+     * @see #setVibrateSetting(int, int)
+     * @see #getVibrateSetting(int)
+     */
+    public static final int VIBRATE_SETTING_ONLY_SILENT = 2;
+
+    /**
+     * Suggests using the default stream type. This may not be used in all
+     * places a stream type is needed.
+     */
+    public static final int USE_DEFAULT_STREAM_TYPE = Integer.MIN_VALUE;
+
+    private static IAudioService sService;
+
+    /**
+     * @hide
+     */
+    public AudioManager(Context context) {
+        mContext = context;
+        mHandler = new Handler(context.getMainLooper());
+    }
+
+    private static IAudioService getService()
+    {
+        if (sService != null) {
+            return sService;
+        }
+        IBinder b = ServiceManager.getService(Context.AUDIO_SERVICE);
+        sService = IAudioService.Stub.asInterface(b);
+        return sService;
+    }
+
+    /**
+     * Adjusts the volume of a particular stream by one step in a direction.
+     *
+     * @param streamType The stream type to adjust. One of {@link #STREAM_VOICE_CALL},
+     * {@link #STREAM_SYSTEM}, {@link #STREAM_RING}, {@link #STREAM_MUSIC} or
+     * {@link #STREAM_ALARM}
+     * @param direction The direction to adjust the volume. One of
+     *            {@link #ADJUST_LOWER}, {@link #ADJUST_RAISE}, or
+     *            {@link #ADJUST_SAME}.
+     * @param flags One or more flags.
+     * @see #adjustVolume(int, int)
+     * @see #setStreamVolume(int, int, int)
+     */
+    public void adjustStreamVolume(int streamType, int direction, int flags) {
+        IAudioService service = getService();
+        try {
+            service.adjustStreamVolume(streamType, direction, flags);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Dead object in adjustStreamVolume", e);
+        }
+    }
+
+    /**
+     * Adjusts the volume of the most relevant stream. For example, if a call is
+     * active, it will have the highest priority regardless of if the in-call
+     * screen is showing. Another example, if music is playing in the background
+     * and a call is not active, the music stream will be adjusted.
+     *
+     * @param direction The direction to adjust the volume. One of
+     *            {@link #ADJUST_LOWER}, {@link #ADJUST_RAISE}, or
+     *            {@link #ADJUST_SAME}.
+     * @param flags One or more flags.
+     * @see #adjustSuggestedStreamVolume(int, int, int)
+     * @see #adjustStreamVolume(int, int, int)
+     * @see #setStreamVolume(int, int, int)
+     */
+    public void adjustVolume(int direction, int flags) {
+        IAudioService service = getService();
+        try {
+            service.adjustVolume(direction, flags);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Dead object in adjustVolume", e);
+        }
+    }
+
+    /**
+     * Adjusts the volume of the most relevant stream, or the given fallback
+     * stream.
+     *
+     * @param direction The direction to adjust the volume. One of
+     *            {@link #ADJUST_LOWER}, {@link #ADJUST_RAISE}, or
+     *            {@link #ADJUST_SAME}.
+     * @param suggestedStreamType The stream type that will be used if there
+     *            isn't a relevant stream. {@link #USE_DEFAULT_STREAM_TYPE} is valid here.
+     * @param flags One or more flags.
+     * @see #adjustVolume(int, int)
+     * @see #adjustStreamVolume(int, int, int)
+     * @see #setStreamVolume(int, int, int)
+     */
+    public void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags) {
+        IAudioService service = getService();
+        try {
+            service.adjustSuggestedStreamVolume(direction, suggestedStreamType, flags);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Dead object in adjustVolume", e);
+        }
+    }
+
+    /**
+     * Returns the current ringtone mode.
+     *
+     * @return The current ringtone mode, one of {@link #RINGER_MODE_NORMAL},
+     *         {@link #RINGER_MODE_SILENT}, or {@link #RINGER_MODE_VIBRATE}.
+     * @see #setRingerMode(int)
+     */
+    public int getRingerMode() {
+        IAudioService service = getService();
+        try {
+            return service.getRingerMode();
+        } catch (RemoteException e) {
+            Log.e(TAG, "Dead object in getRingerMode", e);
+            return RINGER_MODE_NORMAL;
+        }
+    }
+
+    /**
+     * Returns the maximum volume index for a particular stream.
+     *
+     * @param streamType The stream type whose maximum volume index is returned.
+     * @return The maximum valid volume index for the stream.
+     * @see #getStreamVolume(int)
+     */
+    public int getStreamMaxVolume(int streamType) {
+        IAudioService service = getService();
+        try {
+            return service.getStreamMaxVolume(streamType);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Dead object in getStreamMaxVolume", e);
+            return 0;
+        }
+    }
+
+    /**
+     * Returns the current volume index for a particular stream.
+     *
+     * @param streamType The stream type whose volume index is returned.
+     * @return The current volume index for the stream.
+     * @see #getStreamMaxVolume(int)
+     * @see #setStreamVolume(int, int, int)
+     */
+    public int getStreamVolume(int streamType) {
+        IAudioService service = getService();
+        try {
+            return service.getStreamVolume(streamType);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Dead object in getStreamVolume", e);
+            return 0;
+        }
+    }
+
+    /**
+     * Sets the ringer mode.
+     * <p>
+     * Silent mode will mute the volume and will not vibrate. Vibrate mode will
+     * mute the volume and vibrate. Normal mode will be audible and may vibrate
+     * according to user settings.
+     *
+     * @param ringerMode The ringer mode, one of {@link #RINGER_MODE_NORMAL},
+     *            {@link #RINGER_MODE_SILENT}, or {@link #RINGER_MODE_VIBRATE}.
+     * @see #getRingerMode()
+     */
+    public void setRingerMode(int ringerMode) {
+        IAudioService service = getService();
+        try {
+            service.setRingerMode(ringerMode);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Dead object in setRingerMode", e);
+        }
+    }
+
+    /**
+     * Sets the volume index for a particular stream.
+     *
+     * @param streamType The stream whose volume index should be set.
+     * @param index The volume index to set. See
+     *            {@link #getStreamMaxVolume(int)} for the largest valid value.
+     * @param flags One or more flags.
+     * @see #getStreamMaxVolume(int)
+     * @see #getStreamVolume(int)
+     */
+    public void setStreamVolume(int streamType, int index, int flags) {
+        IAudioService service = getService();
+        try {
+            service.setStreamVolume(streamType, index, flags);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Dead object in setStreamVolume", e);
+        }
+    }
+
+    /**
+     * Solo or unsolo a particular stream. All other streams are muted.
+     * <p>
+     * The solo command is protected against client process death: if a process
+     * with an active solo request on a stream dies, all streams that were muted
+     * because of this request will be unmuted automatically.
+     * <p>
+     * The solo requests for a given stream are cumulative: the AudioManager
+     * can receive several solo requests from one or more clients and the stream
+     * will be unsoloed only when the same number of unsolo requests are received.
+     * <p>
+     * For a better user experience, applications MUST unsolo a soloed stream
+     * in onPause() and solo is again in onResume() if appropriate.
+     *
+     * @param streamType The stream to be soloed/unsoloed.
+     * @param state The required solo state: true for solo ON, false for solo OFF
+     */
+    public void setStreamSolo(int streamType, boolean state) {
+        IAudioService service = getService();
+        try {
+            service.setStreamSolo(streamType, state, mICallBack);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Dead object in setStreamSolo", e);
+        }
+    }
+
+    /**
+     * Mute or unmute an audio stream.
+     * <p>
+     * The mute command is protected against client process death: if a process
+     * with an active mute request on a stream dies, this stream will be unmuted
+     * automatically.
+     * <p>
+     * The mute requests for a given stream are cumulative: the AudioManager
+     * can receive several mute requests from one or more clients and the stream
+     * will be unmuted only when the same number of unmute requests are received.
+     * <p>
+     * For a better user experience, applications MUST unmute a muted stream
+     * in onPause() and mute is again in onResume() if appropriate.
+     *
+     * @param streamType The stream to be muted/unmuted.
+     * @param state The required mute state: true for mute ON, false for mute OFF
+     */
+    public void setStreamMute(int streamType, boolean state) {
+        IAudioService service = getService();
+        try {
+            service.setStreamMute(streamType, state, mICallBack);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Dead object in setStreamMute", e);
+        }
+    }
+
+    /**
+     * Returns whether a particular type should vibrate according to user
+     * settings and the current ringer mode.
+     * <p>
+     * This shouldn't be needed by most clients that use notifications to
+     * vibrate. The notification manager will not vibrate if the policy doesn't
+     * allow it, so the client should always set a vibrate pattern and let the
+     * notification manager control whether or not to actually vibrate.
+     *
+     * @param vibrateType The type of vibrate. One of
+     *            {@link #VIBRATE_TYPE_NOTIFICATION} or
+     *            {@link #VIBRATE_TYPE_RINGER}.
+     * @return Whether the type should vibrate at the instant this method is
+     *         called.
+     * @see #setVibrateSetting(int, int)
+     * @see #getVibrateSetting(int)
+     */
+    public boolean shouldVibrate(int vibrateType) {
+        IAudioService service = getService();
+        try {
+            return service.shouldVibrate(vibrateType);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Dead object in shouldVibrate", e);
+            return false;
+        }
+    }
+
+    /**
+     * Returns whether the user's vibrate setting for a vibrate type.
+     * <p>
+     * This shouldn't be needed by most clients that want to vibrate, instead
+     * see {@link #shouldVibrate(int)}.
+     *
+     * @param vibrateType The type of vibrate. One of
+     *            {@link #VIBRATE_TYPE_NOTIFICATION} or
+     *            {@link #VIBRATE_TYPE_RINGER}.
+     * @return The vibrate setting, one of {@link #VIBRATE_SETTING_ON},
+     *         {@link #VIBRATE_SETTING_OFF}, or
+     *         {@link #VIBRATE_SETTING_ONLY_SILENT}.
+     * @see #setVibrateSetting(int, int)
+     * @see #shouldVibrate(int)
+     */
+    public int getVibrateSetting(int vibrateType) {
+        IAudioService service = getService();
+        try {
+            return service.getVibrateSetting(vibrateType);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Dead object in getVibrateSetting", e);
+            return VIBRATE_SETTING_OFF;
+        }
+    }
+
+    /**
+     * Sets the setting for when the vibrate type should vibrate.
+     *
+     * @param vibrateType The type of vibrate. One of
+     *            {@link #VIBRATE_TYPE_NOTIFICATION} or
+     *            {@link #VIBRATE_TYPE_RINGER}.
+     * @param vibrateSetting The vibrate setting, one of
+     *            {@link #VIBRATE_SETTING_ON},
+     *            {@link #VIBRATE_SETTING_OFF}, or
+     *            {@link #VIBRATE_SETTING_ONLY_SILENT}.
+     * @see #getVibrateSetting(int)
+     * @see #shouldVibrate(int)
+     */
+    public void setVibrateSetting(int vibrateType, int vibrateSetting) {
+        IAudioService service = getService();
+        try {
+            service.setVibrateSetting(vibrateType, vibrateSetting);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Dead object in setVibrateSetting", e);
+        }
+    }
+
+    /**
+     * Sets the speakerphone on or off.
+     *
+     * @param on set <var>true</var> to turn on speakerphone;
+     *           <var>false</var> to turn it off
+     */
+    public void setSpeakerphoneOn(boolean on){
+        setRouting(MODE_IN_CALL, on ? ROUTE_SPEAKER : ROUTE_EARPIECE, ROUTE_ALL);
+    }
+
+    /**
+     * Checks whether the speakerphone is on or off.
+     *
+     * @return true if speakerphone is on, false if it's off
+     */
+    public boolean isSpeakerphoneOn() {
+        return (getRouting(MODE_IN_CALL) & ROUTE_SPEAKER) == 0 ? false : true;
+     }
+
+    /**
+     * Sets audio routing to the Bluetooth headset on or off.
+     *
+     * @param on set <var>true</var> to route SCO (voice) audio to/from Bluetooth
+     *           headset; <var>false</var> to route audio to/from phone earpiece
+     */
+    public void setBluetoothScoOn(boolean on){
+        // Don't disable A2DP when turning off SCO.
+        // A2DP does not affect in-call routing.
+        setRouting(MODE_RINGTONE,
+               on ? ROUTE_BLUETOOTH_SCO: ROUTE_SPEAKER, ROUTE_ALL & ~ROUTE_BLUETOOTH_A2DP);
+        setRouting(MODE_NORMAL,
+                on ? ROUTE_BLUETOOTH_SCO: ROUTE_SPEAKER, ROUTE_ALL & ~ROUTE_BLUETOOTH_A2DP);
+        setRouting(MODE_IN_CALL,
+                on ? ROUTE_BLUETOOTH_SCO: ROUTE_EARPIECE, ROUTE_ALL);
+    }
+
+    /**
+     * Checks whether audio routing to the Bluetooth headset is on or off.
+     *
+     * @return true if SCO audio is being routed to/from Bluetooth headset;
+     *         false if otherwise
+     */
+    public boolean isBluetoothScoOn() {
+        return (getRouting(MODE_IN_CALL) & ROUTE_BLUETOOTH_SCO) == 0 ? false : true;
+    }
+
+    /**
+     * Sets A2DP audio routing to the Bluetooth headset on or off.
+     *
+     * @param on set <var>true</var> to route A2DP audio to/from Bluetooth
+     *           headset; <var>false</var> disable A2DP audio
+     */
+    public void setBluetoothA2dpOn(boolean on){
+        // the audio flinger chooses A2DP as a higher priority,
+        // so there is no need to disable other routes.
+        setRouting(MODE_RINGTONE,
+               on ? ROUTE_BLUETOOTH_A2DP: 0, ROUTE_BLUETOOTH_A2DP);
+        setRouting(MODE_NORMAL,
+                on ? ROUTE_BLUETOOTH_A2DP: 0, ROUTE_BLUETOOTH_A2DP);
+    }
+
+    /**
+     * Checks whether A2DP audio routing to the Bluetooth headset is on or off.
+     *
+     * @return true if A2DP audio is being routed to/from Bluetooth headset;
+     *         false if otherwise
+     */
+    public boolean isBluetoothA2dpOn() {
+        return (getRouting(MODE_NORMAL) & ROUTE_BLUETOOTH_A2DP) == 0 ? false : true;
+    }
+
+    /**
+     * Sets audio routing to the wired headset on or off.
+     *
+     * @param on set <var>true</var> to route audio to/from wired
+     *           headset; <var>false</var> disable wired headset audio
+     * @hide
+     */
+    public void setWiredHeadsetOn(boolean on){
+        // A2DP has higher priority than wired headset, so headset connect/disconnect events
+        // should not affect A2DP routing
+        setRouting(MODE_NORMAL,
+                on ? ROUTE_HEADSET : ROUTE_SPEAKER, ROUTE_ALL & ~ROUTE_BLUETOOTH_A2DP);
+        setRouting(MODE_RINGTONE,
+                on ? ROUTE_HEADSET | ROUTE_SPEAKER : ROUTE_SPEAKER, ROUTE_ALL & ~ROUTE_BLUETOOTH_A2DP);
+        setRouting(MODE_IN_CALL,
+                on ? ROUTE_HEADSET : ROUTE_EARPIECE, ROUTE_ALL);
+    }
+
+    /**
+     * Checks whether audio routing to the wired headset is on or off.
+     *
+     * @return true if audio is being routed to/from wired headset;
+     *         false if otherwise
+     * @hide
+     */
+    public boolean isWiredHeadsetOn() {
+        return (getRouting(MODE_NORMAL) & ROUTE_HEADSET) == 0 ? false : true;
+    }
+
+    /**
+     * Sets the microphone mute on or off.
+     *
+     * @param on set <var>true</var> to mute the microphone;
+     *           <var>false</var> to turn mute off
+     */
+    public void setMicrophoneMute(boolean on){
+        IAudioService service = getService();
+        try {
+            service.setMicrophoneMute(on);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Dead object in setMicrophoneMute", e);
+        }
+    }
+
+    /**
+     * Checks whether the microphone mute is on or off.
+     *
+     * @return true if microphone is muted, false if it's not
+     */
+    public boolean isMicrophoneMute() {
+        IAudioService service = getService();
+        try {
+            return service.isMicrophoneMute();
+        } catch (RemoteException e) {
+            Log.e(TAG, "Dead object in isMicrophoneMute", e);
+            return false;
+        }
+    }
+
+    /**
+     * Sets the audio mode.
+     *
+     * @param mode  the requested audio mode (NORMAL, RINGTONE, or IN_CALL).
+     *              Informs the HAL about the current audio state so that
+     *              it can route the audio appropriately.
+     */
+    public void setMode(int mode) {
+        IAudioService service = getService();
+        try {
+            service.setMode(mode);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Dead object in setMode", e);
+        }
+    }
+
+    /**
+     * Returns the current audio mode.
+     *
+     * @return      the current audio mode (NORMAL, RINGTONE, or IN_CALL).
+     *              Returns the current current audio state from the HAL.
+     */
+    public int getMode() {
+        IAudioService service = getService();
+        try {
+            return service.getMode();
+        } catch (RemoteException e) {
+            Log.e(TAG, "Dead object in getMode", e);
+            return MODE_INVALID;
+        }
+    }
+
+    /* modes for setMode/getMode/setRoute/getRoute */
+    /**
+     * Audio harware modes.
+     */
+    /**
+     * Invalid audio mode.
+     */
+    public static final int MODE_INVALID            = AudioSystem.MODE_INVALID;
+    /**
+     * Current audio mode. Used to apply audio routing to current mode.
+     */
+    public static final int MODE_CURRENT            = AudioSystem.MODE_CURRENT;
+    /**
+     * Normal audio mode: not ringing and no call established.
+     */
+    public static final int MODE_NORMAL             = AudioSystem.MODE_NORMAL;
+    /**
+     * Ringing audio mode. An incoming is being signaled.
+     */
+    public static final int MODE_RINGTONE           = AudioSystem.MODE_RINGTONE;
+    /**
+     * In call audio mode. A call is established.
+     */
+    public static final int MODE_IN_CALL            = AudioSystem.MODE_IN_CALL;
+
+    /* Routing bits for setRouting/getRouting API */
+    /**
+     * Routing audio output to earpiece
+     */
+    public static final int ROUTE_EARPIECE          = AudioSystem.ROUTE_EARPIECE;
+    /**
+     * Routing audio output to spaker
+     */
+    public static final int ROUTE_SPEAKER           = AudioSystem.ROUTE_SPEAKER;
+    /**
+     * @deprecated use {@link #ROUTE_BLUETOOTH_SCO}
+     */
+    @Deprecated public static final int ROUTE_BLUETOOTH = AudioSystem.ROUTE_BLUETOOTH_SCO;
+    /**
+     * Routing audio output to bluetooth SCO
+     */
+    public static final int ROUTE_BLUETOOTH_SCO     = AudioSystem.ROUTE_BLUETOOTH_SCO;
+    /**
+     * Routing audio output to headset
+     */
+    public static final int ROUTE_HEADSET           = AudioSystem.ROUTE_HEADSET;
+    /**
+     * Routing audio output to bluetooth A2DP
+     */
+    public static final int ROUTE_BLUETOOTH_A2DP    = AudioSystem.ROUTE_BLUETOOTH_A2DP;
+    /**
+     * Used for mask parameter of {@link #setRouting(int,int,int)}.
+     */
+    public static final int ROUTE_ALL               = AudioSystem.ROUTE_ALL;
+
+    /**
+     * Sets the audio routing for a specified mode
+     *
+     * @param mode   audio mode to change route. E.g., MODE_RINGTONE.
+     * @param routes bit vector of routes requested, created from one or
+     *               more of ROUTE_xxx types. Set bits indicate that route should be on
+     * @param mask   bit vector of routes to change, created from one or more of
+     * ROUTE_xxx types. Unset bits indicate the route should be left unchanged
+     */
+    public void setRouting(int mode, int routes, int mask) {
+        IAudioService service = getService();
+        try {
+            service.setRouting(mode, routes, mask);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Dead object in setRouting", e);
+        }
+    }
+
+    /**
+     * Returns the current audio routing bit vector for a specified mode.
+     *
+     * @param mode audio mode to get route (e.g., MODE_RINGTONE)
+     * @return an audio route bit vector that can be compared with ROUTE_xxx
+     * bits
+     */
+    public int getRouting(int mode) {
+        IAudioService service = getService();
+        try {
+            return service.getRouting(mode);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Dead object in getRouting", e);
+            return -1;
+        }
+    }
+
+    /**
+     * Checks whether any music is active.
+     *
+     * @return true if any music tracks are active.
+     */
+    public boolean isMusicActive() {
+        IAudioService service = getService();
+        try {
+            return service.isMusicActive();
+        } catch (RemoteException e) {
+            Log.e(TAG, "Dead object in isMusicActive", e);
+            return false;
+        }
+    }
+
+    /*
+     * Sets a generic audio configuration parameter. The use of these parameters
+     * are platform dependant, see libaudio
+     *
+     * ** Temporary interface - DO NOT USE
+     *
+     * TODO: Replace with a more generic key:value get/set mechanism
+     *
+     * param key   name of parameter to set. Must not be null.
+     * param value value of parameter. Must not be null.
+     */
+    /**
+     * @hide
+     */
+    public void setParameter(String key, String value) {
+        IAudioService service = getService();
+        try {
+            service.setParameter(key, value);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Dead object in setParameter", e);
+        }
+    }
+
+    /* Sound effect identifiers */
+    /**
+     * Keyboard and direction pad click sound
+     * @see #playSoundEffect(int)
+     */
+    public static final int FX_KEY_CLICK = 0;
+    /**
+     * Focus has moved up
+     * @see #playSoundEffect(int)
+     */
+    public static final int FX_FOCUS_NAVIGATION_UP = 1;
+    /**
+     * Focus has moved down
+     * @see #playSoundEffect(int)
+     */
+    public static final int FX_FOCUS_NAVIGATION_DOWN = 2;
+    /**
+     * Focus has moved left
+     * @see #playSoundEffect(int)
+     */
+    public static final int FX_FOCUS_NAVIGATION_LEFT = 3;
+    /**
+     * Focus has moved right
+     * @see #playSoundEffect(int)
+     */
+    public static final int FX_FOCUS_NAVIGATION_RIGHT = 4;
+    /**
+     * IME standard keypress sound
+     * @see #playSoundEffect(int)
+     * @hide FIXME: Unhide before release
+     */
+    public static final int FX_KEYPRESS_STANDARD = 5;
+    /**
+     * IME spacebar keypress sound
+     * @see #playSoundEffect(int)
+     * @hide FIXME: Unhide before release
+     */
+    public static final int FX_KEYPRESS_SPACEBAR = 6;
+    /**
+     * IME delete keypress sound
+     * @see #playSoundEffect(int)
+     * @hide FIXME: Unhide before release
+     */
+    public static final int FX_KEYPRESS_DELETE = 7;
+    /**
+     * IME return_keypress sound
+     * @see #playSoundEffect(int)
+     * @hide FIXME: Unhide before release
+     */
+    public static final int FX_KEYPRESS_RETURN = 8;
+    /**
+     * @hide Number of sound effects
+     */
+    public static final int NUM_SOUND_EFFECTS = 9;
+
+    /**
+     * Plays a sound effect (Key clicks, lid open/close...)
+     * @param effectType The type of sound effect. One of
+     *            {@link #FX_KEY_CLICK},
+     *            {@link #FX_FOCUS_NAVIGATION_UP},
+     *            {@link #FX_FOCUS_NAVIGATION_DOWN},
+     *            {@link #FX_FOCUS_NAVIGATION_LEFT},
+     *            {@link #FX_FOCUS_NAVIGATION_RIGHT},
+     *            FIXME: include links before release
+     *            {link #FX_KEYPRESS_STANDARD},
+     *            {link #FX_KEYPRESS_SPACEBAR},
+     *            {link #FX_KEYPRESS_DELETE},
+     *            {link #FX_KEYPRESS_RETURN},
+     * NOTE: This version uses the UI settings to determine
+     * whether sounds are heard or not.
+     */
+    public void  playSoundEffect(int effectType) {
+        if (effectType < 0 || effectType >= NUM_SOUND_EFFECTS) {
+            return;
+        }
+
+        if (!querySoundEffectsEnabled()) {
+            return;
+        }
+
+        IAudioService service = getService();
+        try {
+            service.playSoundEffect(effectType);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Dead object in playSoundEffect"+e);
+        }
+    }
+
+    /**
+     * Plays a sound effect (Key clicks, lid open/close...)
+     * @param effectType The type of sound effect. One of
+     *            {@link #FX_KEY_CLICK},
+     *            {@link #FX_FOCUS_NAVIGATION_UP},
+     *            {@link #FX_FOCUS_NAVIGATION_DOWN},
+     *            {@link #FX_FOCUS_NAVIGATION_LEFT},
+     *            {@link #FX_FOCUS_NAVIGATION_RIGHT},
+     *            FIXME: include links before release
+     *            {link #FX_KEYPRESS_STANDARD},
+     *            {link #FX_KEYPRESS_SPACEBAR},
+     *            {link #FX_KEYPRESS_DELETE},
+     *            {link #FX_KEYPRESS_RETURN},
+     * @param volume Sound effect volume
+     * NOTE: This version is for applications that have their own
+     * settings panel for enabling and controlling volume.
+     *  @hide FIXME: Unhide before release
+     */
+    public void  playSoundEffect(int effectType, float volume) {
+        if (effectType < 0 || effectType >= NUM_SOUND_EFFECTS) {
+            return;
+        }
+
+        IAudioService service = getService();
+        try {
+            service.playSoundEffectVolume(effectType, volume);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Dead object in playSoundEffect"+e);
+        }
+    }
+
+    /**
+     * Settings has an in memory cache, so this is fast.
+     */
+    private boolean querySoundEffectsEnabled() {
+        return Settings.System.getInt(mContext.getContentResolver(), Settings.System.SOUND_EFFECTS_ENABLED, 0) != 0;
+    }
+
+
+    /**
+     *  Load Sound effects.
+     *  This method must be called when sound effects are enabled.
+     */
+    public void loadSoundEffects() {
+        IAudioService service = getService();
+        try {
+            service.loadSoundEffects();
+        } catch (RemoteException e) {
+            Log.e(TAG, "Dead object in loadSoundEffects"+e);
+        }
+    }
+
+    /**
+     *  Unload Sound effects.
+     *  This method can be called to free some memory when
+     *  sound effects are disabled.
+     */
+    public void unloadSoundEffects() {
+        IAudioService service = getService();
+        try {
+            service.unloadSoundEffects();
+        } catch (RemoteException e) {
+            Log.e(TAG, "Dead object in unloadSoundEffects"+e);
+        }
+    }
+
+     /**
+      * {@hide}
+      */
+     private IBinder mICallBack = new Binder();
+}
diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java
new file mode 100644
index 0000000..0ef7760
--- /dev/null
+++ b/media/java/android/media/AudioRecord.java
@@ -0,0 +1,798 @@
+/*
+ * 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.
+ */
+
+package android.media;
+
+import java.lang.ref.WeakReference;
+import java.io.OutputStream;
+import java.io.IOException;
+import java.lang.IllegalArgumentException;
+import java.lang.IllegalStateException;
+import java.lang.Thread;
+import java.nio.ByteBuffer;
+
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.util.Log;
+
+/**
+ * The AudioRecord class manages the audio resources for Java applications
+ * to record audio from the audio input hardware of the platform. This is
+ * achieved by "pulling" (reading) the data from the AudioRecord object. The
+ * application is responsible for polling the AudioRecord object in time using one of 
+ * the following three methods:  {@link #read(byte[],int, int)}, {@link #read(short[], int, int)}
+ * or {@link #read(ByteBuffer, int)}. The choice of which method to use will be based 
+ * on the audio data storage format that is the most convenient for the user of AudioRecord.
+ * <p>Upon creation, an AudioRecord object initializes its associated audio buffer that it will
+ * fill with the new audio data. The size of this buffer, specified during the construction, 
+ * determines how long an AudioRecord can record before "over-running" data that has not
+ * been read yet. Data should be from the audio hardware in chunks of sizes inferior to
+ * the total recording buffer size.
+ */
+public class AudioRecord
+{
+    //---------------------------------------------------------
+    // Constants
+    //--------------------
+    /**
+     *  State of an AudioRecord that was not successfully initialized upon creation 
+     */
+    public static final int STATE_UNINITIALIZED = 0;
+    /**
+     *  State of an AudioRecord that is ready to be used 
+     */
+    public static final int STATE_INITIALIZED   = 1;
+
+    /**
+     * State of an AudioRecord this is not recording 
+     */
+    public static final int RECORDSTATE_STOPPED = 1;  // matches SL_RECORDSTATE_STOPPED
+    /**
+     * State of an AudioRecord this is recording 
+     */
+    public static final int RECORDSTATE_RECORDING = 3;// matches SL_RECORDSTATE_RECORDING
+
+    // Error codes:
+    // to keep in sync with frameworks/base/core/jni/android_media_AudioRecord.cpp
+    /**
+     * Denotes a successful operation.
+     */
+    public static final int SUCCESS                 = 0;
+    /**
+     * Denotes a generic operation failure.
+     */
+    public static final int ERROR                   = -1;
+    /**
+     * Denotes a failure due to the use of an invalid value.
+     */
+    public static final int ERROR_BAD_VALUE         = -2;
+    /**
+     * Denotes a failure due to the improper use of a method.
+     */
+    public static final int ERROR_INVALID_OPERATION = -3;
+    
+    private static final int AUDIORECORD_ERROR_SETUP_ZEROFRAMECOUNT      = -16;
+    private static final int AUDIORECORD_ERROR_SETUP_INVALIDCHANNELCOUNT = -17;
+    private static final int AUDIORECORD_ERROR_SETUP_INVALIDFORMAT       = -18;
+    private static final int AUDIORECORD_ERROR_SETUP_INVALIDSTREAMTYPE   = -19;
+    private static final int AUDIORECORD_ERROR_SETUP_NATIVEINITFAILED    = -20;
+    
+    // Events:
+    // to keep in sync with frameworks/base/include/media/AudioRecord.h 
+    /**
+     * Event id for when the recording head has reached a previously set marker.
+     */
+    private static final int NATIVE_EVENT_MARKER  = 2;
+    /**
+     * Event id for when the previously set update period has passed during recording.
+     */
+    private static final int NATIVE_EVENT_NEW_POS = 3;
+    
+    private final static String TAG = "AudioRecord-Java";
+
+
+    //---------------------------------------------------------
+    // Used exclusively by native code
+    //--------------------
+    /** 
+     * Accessed by native methods: provides access to C++ AudioRecord object 
+     */
+    @SuppressWarnings("unused")
+    private int mNativeRecorderInJavaObj;
+    /** 
+     * Accessed by native methods: provides access to record source constants 
+     */
+    @SuppressWarnings("unused")
+    private final static int SOURCE_DEFAULT = MediaRecorder.AudioSource.DEFAULT;
+    @SuppressWarnings("unused")
+    private final static int SOURCE_MIC = MediaRecorder.AudioSource.MIC;
+    /** 
+     * Accessed by native methods: provides access to the callback data.
+     */
+    @SuppressWarnings("unused")
+    private int mNativeCallbackCookie;
+    
+
+    //---------------------------------------------------------
+    // Member variables
+    //--------------------    
+    /**
+     * The audio data sampling rate in Hz.
+     */
+    private int mSampleRate = 22050;
+    /**
+     * The number of input audio channels (1 is mono, 2 is stereo)
+     */
+    private int mChannelCount = 1;
+    /**
+     * The current audio channel configuration
+     */
+    private int mChannelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_MONO;
+    /**
+     * The encoding of the audio samples.
+     * @see AudioFormat#ENCODING_PCM_8BIT
+     * @see AudioFormat#ENCODING_PCM_16BIT
+     */
+    private int mAudioFormat = AudioFormat.ENCODING_PCM_16BIT;
+    /**
+     * Where the audio data is recorded from.
+     */
+    private int mRecordSource = MediaRecorder.AudioSource.DEFAULT;
+    /**
+     * Indicates the state of the AudioRecord instance.
+     */
+    private int mState = STATE_UNINITIALIZED;
+    /**
+     * Indicates the recording state of the AudioRecord instance.
+     */
+    private int mRecordingState = RECORDSTATE_STOPPED;
+    /**
+     * Lock to make sure mRecordingState updates are reflecting the actual state of the object.
+     */
+    private Object mRecordingStateLock = new Object();
+    /**
+     * The listener the AudioRecord notifies when a previously set marker is reached.
+     *  @see #setMarkerReachedListener(OnMarkerReachedListener)
+     */
+    private OnMarkerReachedListener mMarkerListener = null;
+    /**
+     * Lock to protect marker listener updates against event notifications
+     */
+    private final Object mMarkerListenerLock = new Object();
+    /**
+     * The listener the AudioRecord notifies periodically during recording.
+     *  @see #setPeriodicNotificationListener(OnPeriodicNotificationListener)
+     */
+    private OnPeriodicNotificationListener mPeriodicListener = null;
+    /**
+     * Lock to protect periodic listener updates against event notifications
+     */
+    private final Object mPeriodicListenerLock = new Object();
+    /**
+     * Handler for events coming from the native code
+     */
+    private NativeEventHandler mNativeEventHandler = null;
+    /**
+     * Size of the native audio buffer.
+     */
+    private int mNativeBufferSizeInBytes = 0;
+
+    
+    //---------------------------------------------------------
+    // Constructor, Finalize
+    //--------------------
+    /**
+     * Class constructor.
+     * @param audioSource the recording source. See {@link MediaRecorder.AudioSource} for
+     *    recording source definitions.
+     * @param sampleRateInHz the sample rate expressed in Hertz. Examples of rates are (but
+     *   not limited to) 44100, 22050 and 11025.
+     * @param channelConfig describes the configuration of the audio channels. 
+     *   See {@link AudioFormat#CHANNEL_CONFIGURATION_MONO} and
+     *   {@link AudioFormat#CHANNEL_CONFIGURATION_STEREO}
+     * @param audioFormat the format in which the audio data is represented. 
+     *   See {@link AudioFormat#ENCODING_PCM_16BIT} and 
+     *   {@link AudioFormat#ENCODING_PCM_8BIT}
+     * @param bufferSizeInBytes the total size (in bytes) of the buffer where audio data is written
+     *   to during the recording. New audio data can be read from this buffer in smaller chunks 
+     *   than this size.
+     * @throws java.lang.IllegalArgumentException
+     */
+    public AudioRecord(int audioSource, int sampleRateInHz, int channelConfig, int audioFormat, 
+            int bufferSizeInBytes)
+    throws IllegalArgumentException {   
+        mState = STATE_UNINITIALIZED;
+        mRecordingState = RECORDSTATE_STOPPED;
+
+        audioParamCheck(audioSource, sampleRateInHz, channelConfig, audioFormat);
+
+        audioBuffSizeCheck(bufferSizeInBytes);
+
+        // native initialization
+        //TODO: update native initialization when information about hardware init failure
+        //      due to capture device already open is available.
+        int initResult = native_setup( new WeakReference<AudioRecord>(this), 
+                mRecordSource, mSampleRate, mChannelCount, mAudioFormat, mNativeBufferSizeInBytes);
+        if (initResult != SUCCESS) {
+            loge("Error code "+initResult+" when initializing native AudioRecord object.");
+            return; // with mState == STATE_UNINITIALIZED
+        }
+
+        mState = STATE_INITIALIZED;
+    }
+
+
+    // Convenience method for the constructor's parameter checks.
+    // This is where constructor IllegalArgumentException-s are thrown
+    // postconditions:
+    //    mRecordSource is valid
+    //    mChannelCount is valid
+    //    mAudioFormat is valid
+    //    mSampleRate is valid
+    private void audioParamCheck(int audioSource, int sampleRateInHz, 
+                                 int channelConfig, int audioFormat) {
+
+        //--------------
+        // audio source
+        if ( (audioSource != MediaRecorder.AudioSource.DEFAULT)
+                && (audioSource != MediaRecorder.AudioSource.MIC) ) {
+            throw (new IllegalArgumentException("Invalid audio source."));
+        } else {
+            mRecordSource = audioSource;
+        }
+        
+        //--------------
+        // sample rate
+        if ( (sampleRateInHz < 4000) || (sampleRateInHz > 48000) ) {
+            throw (new IllegalArgumentException(sampleRateInHz
+                    + "Hz is not a supported sample rate."));
+        } else { 
+            mSampleRate = sampleRateInHz;
+        }
+
+        //--------------
+        // channel config
+        switch (channelConfig) {
+        case AudioFormat.CHANNEL_CONFIGURATION_DEFAULT:
+        case AudioFormat.CHANNEL_CONFIGURATION_MONO:
+            mChannelCount = 1;
+            mChannelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_MONO;
+            break;
+        case AudioFormat.CHANNEL_CONFIGURATION_STEREO:
+            mChannelCount = 2;
+            mChannelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_STEREO;
+            break;
+        default:
+            mChannelCount = 0;
+        mChannelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_INVALID;
+        throw (new IllegalArgumentException("Unsupported channel configuration."));
+        }
+
+        //--------------
+        // audio format
+        switch (audioFormat) {
+        case AudioFormat.ENCODING_DEFAULT:
+            mAudioFormat = AudioFormat.ENCODING_PCM_16BIT;
+            break;
+        case AudioFormat.ENCODING_PCM_16BIT:
+        case AudioFormat.ENCODING_PCM_8BIT:
+            mAudioFormat = audioFormat;
+            break;
+        default:
+            mAudioFormat = AudioFormat.ENCODING_INVALID;
+        throw (new IllegalArgumentException("Unsupported sample encoding." 
+                + " Should be ENCODING_PCM_8BIT or ENCODING_PCM_16BIT."));
+        }
+    }
+
+
+    // Convenience method for the contructor's audio buffer size check.
+    // preconditions:
+    //    mChannelCount is valid
+    //    mAudioFormat is AudioFormat.ENCODING_PCM_8BIT OR AudioFormat.ENCODING_PCM_16BIT
+    // postcondition:
+    //    mNativeBufferSizeInBytes is valid (multiple of frame size, positive)
+    private void audioBuffSizeCheck(int audioBufferSize) {
+        // NB: this section is only valid with PCM data. 
+        // To update when supporting compressed formats
+        int frameSizeInBytes = mChannelCount 
+            * (mAudioFormat == AudioFormat.ENCODING_PCM_8BIT ? 1 : 2);
+        if ((audioBufferSize % frameSizeInBytes != 0) || (audioBufferSize < 1)) {
+            throw (new IllegalArgumentException("Invalid audio buffer size."));
+        }
+
+        mNativeBufferSizeInBytes = audioBufferSize;
+    }    
+    
+    
+    // Convenience method for the creation of the native event handler
+    // It is called only when a non-null event listener is set.
+    // precondition:
+    //    mNativeEventHandler is null
+    private void createNativeEventHandler() {
+        Looper looper;
+        if ((looper = Looper.myLooper()) != null) {
+            mNativeEventHandler = new NativeEventHandler(this, looper);
+        } else if ((looper = Looper.getMainLooper()) != null) {
+            mNativeEventHandler = new NativeEventHandler(this, looper);
+        } else {
+            mNativeEventHandler = null;
+        }
+    }
+    
+
+    /**
+     * Releases the native AudioRecord resources.
+     */
+    public void release() {
+        try {
+            stop();
+        } catch(IllegalStateException ise) { 
+            // don't raise an exception, we're releasing the resources.
+        }
+        native_release();
+        mState = STATE_UNINITIALIZED;
+    }
+    
+
+    @Override
+    protected void finalize() {
+        native_finalize();
+    } 
+
+
+    //--------------------------------------------------------------------------
+    // Getters
+    //--------------------
+    /**
+     * Returns the configured audio data sample rate in Hz
+     */
+    public int getSampleRate() {
+        return mSampleRate;
+    }
+    
+    /**
+     * Returns the audio recording source. 
+     * @see MediaRecorder.AudioSource
+     */
+    public int getAudioSource() {
+        return mRecordSource;
+    }
+
+    /**
+     * Returns the configured audio data format. See {@link AudioFormat#ENCODING_PCM_16BIT}
+     * and {@link AudioFormat#ENCODING_PCM_8BIT}.
+     */
+    public int getAudioFormat() {
+        return mAudioFormat;
+    }
+
+    /**
+     * Returns the configured channel configuration. 
+     * See {@link AudioFormat#CHANNEL_CONFIGURATION_MONO}
+     * and {@link AudioFormat#CHANNEL_CONFIGURATION_STEREO}.
+     */
+    public int getChannelConfiguration() {
+        return mChannelConfiguration;
+    }
+
+    /**
+     * Returns the configured number of channels.
+     */
+    public int getChannelCount() {
+        return mChannelCount;
+    }
+
+    /**
+     * Returns the state of the AudioRecord instance. This is useful after the
+     * AudioRecord instance has been created to check if it was initialized 
+     * properly. This ensures that the appropriate hardware resources have been
+     * acquired.
+     * @see AudioRecord#STATE_INITIALIZED
+     * @see AudioRecord#STATE_UNINITIALIZED
+     */
+    public int getState() {
+        return mState;
+    }
+
+    /**
+     * Returns the recording state of the AudioRecord instance.
+     * @see AudioRecord#RECORDSTATE_STOPPED
+     * @see AudioRecord#RECORDSTATE_RECORDING
+     */
+    public int getRecordingState() {
+        return mRecordingState;
+    }
+    
+    /**
+     * @return marker position in frames
+     */
+    public int getNotificationMarkerPosition() {
+        return native_get_marker_pos();
+    }
+
+    /**
+     * @return update period in frames
+     */
+    public int getPositionNotificationPeriod() {
+        return native_get_pos_update_period();
+    }
+    
+    /**
+     * {@hide}
+     * Returns the minimum buffer size required for the successful creation of an AudioRecord
+     * object.
+     * @param sampleRateInHz the sample rate expressed in Hertz.
+     * @param channelConfig describes the configuration of the audio channels. 
+     *   See {@link AudioFormat#CHANNEL_CONFIGURATION_MONO} and
+     *   {@link AudioFormat#CHANNEL_CONFIGURATION_STEREO}
+     * @param audioFormat the format in which the audio data is represented. 
+     *   See {@link AudioFormat#ENCODING_PCM_16BIT}.
+     * @return {@link #ERROR_BAD_VALUE} if the recording parameters are not supported by the 
+     *  hardware, or an invalid parameter was passed,
+     *  or {@link #ERROR} if the implementation was unable to query the hardware for its 
+     *  output properties, 
+     *   or the minimum buffer size expressed in of bytes.
+     */
+    static public int getMinBufferSize(int sampleRateInHz, int channelConfig, int audioFormat) {
+        int channelCount = 0;
+        switch(channelConfig) {
+        case AudioFormat.CHANNEL_CONFIGURATION_DEFAULT:
+        case AudioFormat.CHANNEL_CONFIGURATION_MONO:
+            channelCount = 1;
+            break;
+        case AudioFormat.CHANNEL_CONFIGURATION_STEREO:
+            channelCount = 2;
+            break;
+        case AudioFormat.CHANNEL_CONFIGURATION_INVALID:
+        default:
+            loge("getMinBufferSize(): Invalid channel configuration.");
+            return AudioRecord.ERROR_BAD_VALUE;
+        }
+        
+        // PCM_8BIT is not supported at the moment
+        if (audioFormat != AudioFormat.ENCODING_PCM_16BIT) {
+            loge("getMinBufferSize(): Invalid audio format.");
+            return AudioRecord.ERROR_BAD_VALUE;
+        }
+        
+        int size = native_get_min_buff_size(sampleRateInHz, channelCount, audioFormat);
+        if (size == 0) {
+            return AudioRecord.ERROR_BAD_VALUE;
+        } 
+        else if (size == -1) {
+            return AudioRecord.ERROR;
+        }
+        else {
+            return size;
+        }
+    }
+
+
+    //---------------------------------------------------------
+    // Transport control methods
+    //--------------------
+    /**
+     * Starts recording from the AudioRecord instance. 
+     * @throws IllegalStateException
+     */
+    public void startRecording()
+    throws IllegalStateException {
+        if (mState != STATE_INITIALIZED) {
+            throw(new IllegalStateException("startRecording() called on an "
+                    +"uninitialized AudioRecord."));
+        }
+
+        // start recording
+        synchronized(mRecordingStateLock) {
+            native_start();
+            mRecordingState = RECORDSTATE_RECORDING;
+        }
+    }
+
+
+
+    /**
+     * Stops recording.
+     * @throws IllegalStateException
+     */
+    public void stop()
+    throws IllegalStateException {
+        if (mState != STATE_INITIALIZED) {
+            throw(new IllegalStateException("stop() called on an uninitialized AudioRecord."));
+        }
+
+        // stop recording
+        synchronized(mRecordingStateLock) {
+            native_stop();
+            mRecordingState = RECORDSTATE_STOPPED;
+        }
+    }
+
+
+    //---------------------------------------------------------
+    // Audio data supply
+    //--------------------
+    /**
+     * Reads audio data from the audio hardware for recording into a buffer.
+     * @param audioData the array to which the recorded audio data is written.
+     * @param offsetInBytes index in audioData from which the data is written.
+     * @param sizeInBytes the number of requested bytes.
+     * @return the number of bytes that were read or or {@link #ERROR_INVALID_OPERATION}
+     *    if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if
+     *    the parameters don't resolve to valid data and indexes.
+     *    The number of bytes will not exceed sizeInBytes.
+     */    
+    public int read(byte[] audioData, int offsetInBytes, int sizeInBytes) {
+        if (mState != STATE_INITIALIZED) {
+            return ERROR_INVALID_OPERATION;
+        }
+        
+        if ( (audioData == null) || (offsetInBytes < 0 ) || (sizeInBytes < 0) 
+                || (offsetInBytes + sizeInBytes > audioData.length)) {
+            return ERROR_BAD_VALUE;
+        }
+
+        return native_read_in_byte_array(audioData, offsetInBytes, sizeInBytes);
+    }
+
+
+    /**
+     * Reads audio data from the audio hardware for recording into a buffer.
+     * @param audioData the array to which the recorded audio data is written.
+     * @param offsetInShorts index in audioData from which the data is written.
+     * @param sizeInShorts the number of requested shorts.
+     * @return the number of bytes that were read or or {@link #ERROR_INVALID_OPERATION}
+     *    if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if
+     *    the parameters don't resolve to valid data and indexes.
+     *    The number of shorts will not exceed sizeInShorts.
+     */    
+    public int read(short[] audioData, int offsetInShorts, int sizeInShorts) {
+        if (mState != STATE_INITIALIZED) {
+            return ERROR_INVALID_OPERATION;
+        }
+        
+        if ( (audioData == null) || (offsetInShorts < 0 ) || (sizeInShorts < 0) 
+                || (offsetInShorts + sizeInShorts > audioData.length)) {
+            return ERROR_BAD_VALUE;
+        }
+
+        return native_read_in_short_array(audioData, offsetInShorts, sizeInShorts);
+    }
+
+
+    /**
+     * Reads audio data from the audio hardware for recording into a direct buffer. If this buffer
+     * is not a direct buffer, this method will always return 0.
+     * @param audioBuffer the direct buffer to which the recorded audio data is written.
+     * @param sizeInBytes the number of requested bytes.
+     * @return the number of bytes that were read or or {@link #ERROR_INVALID_OPERATION}
+     *    if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if
+     *    the parameters don't resolve to valid data and indexes.
+     *    The number of bytes will not exceed sizeInBytes.
+     */    
+    public int read(ByteBuffer audioBuffer, int sizeInBytes) {
+        if (mState != STATE_INITIALIZED) {
+            return ERROR_INVALID_OPERATION;
+        }
+        
+        if ( (audioBuffer == null) || (sizeInBytes < 0) ) {
+            return ERROR_BAD_VALUE;
+        }
+
+        return native_read_in_direct_buffer(audioBuffer, sizeInBytes);
+    }
+
+
+    //--------------------------------------------------------------------------
+    // Initialization / configuration
+    //--------------------  
+    /**
+     * Sets the listener the AudioRecord notifies when a previously set marker is reached.
+     * @param listener
+     */
+    public void setMarkerReachedListener(OnMarkerReachedListener listener) {
+        synchronized (mMarkerListenerLock) {
+            mMarkerListener = listener;
+        }
+        if ((listener != null) && (mNativeEventHandler == null)) {
+            createNativeEventHandler();
+        }
+    }
+    
+    
+    /**
+     * Sets the listener the AudioRecord notifies periodically during recording.
+     * @param listener
+     */
+    public void setPeriodicNotificationListener(OnPeriodicNotificationListener listener) {
+        synchronized (mPeriodicListenerLock) {
+            mPeriodicListener = listener;
+        }
+        if ((listener != null) && (mNativeEventHandler == null)) {
+            createNativeEventHandler();
+        }
+    }
+    
+    
+    /**
+     * Sets the marker position at which the listener, if set with 
+     * {@link #setMarkerReachedListener(OnMarkerReachedListener)}, is called.
+     * @param markerInFrames marker position expressed in frames
+     * @return error code or success, see {@link #SUCCESS}, {@link #ERROR_BAD_VALUE},
+     *  {@link #ERROR_INVALID_OPERATION} 
+     */
+    public int setNotificationMarkerPosition(int markerInFrames) {
+        return native_set_marker_pos(markerInFrames);
+    }
+    
+    
+    /**
+     * Sets the period at which the listener, if set with
+     * {@link #setPositionNotificationPeriod(int)}, is called.
+     * @param periodInFrames update period expressed in frames
+     * @return error code or success, see {@link #SUCCESS}, {@link #ERROR_INVALID_OPERATION}
+     */
+    public int setPositionNotificationPeriod(int periodInFrames) {
+        return native_set_pos_update_period(periodInFrames);
+    }
+
+
+    //---------------------------------------------------------
+    // Interface definitions
+    //--------------------
+    /**
+     * Interface definition for a callback to be invoked when an AudioRecord has
+     * reached a notification marker set by setNotificationMarkerPosition().
+     */
+    public interface OnMarkerReachedListener  {
+        /**
+         * Called on the listener to notify it that the previously set marker has been reached
+         * by the recording head.
+         */
+        void onMarkerReached(AudioRecord recorder);
+    }
+
+
+    /**
+     * Interface definition for a callback to be invoked for each periodic AudioRecord 
+     * update during recording. The update interval is set by setPositionNotificationPeriod().
+     */
+    public interface OnPeriodicNotificationListener  {
+        /**
+         * Called on the listener to periodically notify it that the recording head has reached
+         * a multiple of the notification period.
+         */
+        void onPeriodicNotification(AudioRecord recorder);
+    }
+
+    
+    //---------------------------------------------------------
+    // Inner classes
+    //--------------------
+    /**
+     * Helper class to handle the forwarding of native events to the appropriate listeners
+     */
+    private class NativeEventHandler extends Handler
+    {
+        private AudioRecord mAudioRecord;
+
+        public NativeEventHandler(AudioRecord ar, Looper looper) {
+            super(looper);
+            mAudioRecord = ar;
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            if (mAudioRecord == null) {
+                return;
+            }
+            switch(msg.what) {
+            case NATIVE_EVENT_MARKER:
+                synchronized (mMarkerListenerLock) {
+                    if (mAudioRecord.mMarkerListener != null) {
+                        mAudioRecord.mMarkerListener.onMarkerReached(mAudioRecord);
+                    }
+                }
+                break;
+            case NATIVE_EVENT_NEW_POS:
+                synchronized (mPeriodicListenerLock) {
+                    if (mAudioRecord.mPeriodicListener != null) {
+                        mAudioRecord.mPeriodicListener.onPeriodicNotification(mAudioRecord);
+                    }
+                }
+                break;
+            default:
+                Log.e(TAG, "[ android.media.AudioRecord.NativeEventHandler ] " +
+                        "Unknown event type: " + msg.what);
+                break;
+            }
+        }
+    }
+    
+    
+    //---------------------------------------------------------
+    // Java methods called from the native side
+    //--------------------
+    @SuppressWarnings("unused")
+    private static void postEventFromNative(Object audiorecord_ref,
+            int what, int arg1, int arg2, Object obj) {
+        //logd("Event posted from the native side: event="+ what + " args="+ arg1+" "+arg2);
+        AudioRecord recorder = (AudioRecord)((WeakReference)audiorecord_ref).get();
+        if (recorder == null) {
+            return;
+        }
+        
+        if (recorder.mNativeEventHandler != null) {
+            Message m = recorder.mNativeEventHandler.obtainMessage(what, arg1, arg2, obj);
+            recorder.mNativeEventHandler.sendMessage(m);
+        }
+
+    }
+    
+
+    //---------------------------------------------------------
+    // Native methods called from the Java side
+    //--------------------
+
+    private native final int native_setup(Object audiorecord_this, 
+            int recordSource, int sampleRate, int nbChannels, int audioFormat, int buffSizeInBytes);
+
+    private native final void native_finalize();
+    
+    private native final void native_release();
+
+    private native final void native_start();  
+
+    private native final void native_stop();
+
+    private native final int native_read_in_byte_array(byte[] audioData, 
+            int offsetInBytes, int sizeInBytes);
+
+    private native final int native_read_in_short_array(short[] audioData, 
+            int offsetInShorts, int sizeInShorts);
+
+    private native final int native_read_in_direct_buffer(Object jBuffer, int sizeInBytes);
+    
+    private native final int native_set_marker_pos(int marker);
+    private native final int native_get_marker_pos();
+    
+    private native final int native_set_pos_update_period(int updatePeriod);
+    private native final int native_get_pos_update_period();
+    
+    static private native final int native_get_min_buff_size(
+            int sampleRateInHz, int channelCount, int audioFormat);
+
+    
+    //---------------------------------------------------------
+    // Utility methods
+    //------------------
+
+    private static void logd(String msg) {
+        Log.d(TAG, "[ android.media.AudioRecord ] " + msg);
+    }
+
+    private static void loge(String msg) {
+        Log.e(TAG, "[ android.media.AudioRecord ] " + msg);
+    }
+
+}
+
+
+
+
+
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
new file mode 100644
index 0000000..83ede0d
--- /dev/null
+++ b/media/java/android/media/AudioService.java
@@ -0,0 +1,1236 @@
+/*
+ * 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.
+ */
+
+package android.media;
+
+import android.app.ActivityManagerNative;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.media.MediaPlayer.OnCompletionListener;
+import android.media.MediaPlayer.OnErrorListener;
+import android.os.Binder;
+import android.os.Environment;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.provider.Settings;
+import android.provider.Settings.System;
+import android.util.Log;
+import android.view.VolumePanel;
+
+import com.android.internal.telephony.ITelephony;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
+
+/**
+ * The implementation of the volume manager service.
+ * <p>
+ * This implementation focuses on delivering a responsive UI. Most methods are
+ * asynchronous to external calls. For example, the task of setting a volume
+ * will update our internal state, but in a separate thread will set the system
+ * volume and later persist to the database. Similarly, setting the ringer mode
+ * will update the state and broadcast a change and in a separate thread later
+ * persist the ringer mode.
+ *
+ * @hide
+ */
+public class AudioService extends IAudioService.Stub {
+
+    private static final String TAG = "AudioService";
+
+    /** How long to delay before persisting a change in volume/ringer mode. */
+    private static final int PERSIST_DELAY = 3000;
+
+    private Context mContext;
+    private ContentResolver mContentResolver;
+
+    /** The UI */
+    private VolumePanel mVolumePanel;
+
+    // sendMsg() flags
+    /** Used when a message should be shared across all stream types. */
+    private static final int SHARED_MSG = -1;
+    /** If the msg is already queued, replace it with this one. */
+    private static final int SENDMSG_REPLACE = 0;
+    /** If the msg is already queued, ignore this one and leave the old. */
+    private static final int SENDMSG_NOOP = 1;
+    /** If the msg is already queued, queue this one and leave the old. */
+    private static final int SENDMSG_QUEUE = 2;
+
+    // AudioHandler message.whats
+    private static final int MSG_SET_SYSTEM_VOLUME = 0;
+    private static final int MSG_PERSIST_VOLUME = 1;
+    private static final int MSG_PERSIST_RINGER_MODE = 3;
+    private static final int MSG_PERSIST_VIBRATE_SETTING = 4;
+    private static final int MSG_MEDIA_SERVER_DIED = 5;
+    private static final int MSG_MEDIA_SERVER_STARTED = 6;
+    private static final int MSG_PLAY_SOUND_EFFECT = 7;
+
+    /** @see AudioSystemThread */
+    private AudioSystemThread mAudioSystemThread;
+    /** @see AudioHandler */
+    private AudioHandler mAudioHandler;
+    /** @see VolumeStreamState */
+    private VolumeStreamState[] mStreamStates;
+
+    private boolean mMicMute;
+    private int mMode;
+    private int[] mRoutes = new int[AudioSystem.NUM_MODES];
+    private Object mSettingsLock = new Object();
+    private boolean mMediaServerOk;
+
+    private SoundPool mSoundPool;
+    private Object mSoundEffectsLock = new Object();
+    private static final int NUM_SOUNDPOOL_CHANNELS = 4;
+    private static final int SOUND_EFFECT_VOLUME = 1000;
+
+    /* Sound effect file names  */
+    private static final String SOUND_EFFECTS_PATH = "/media/audio/ui/";
+    private static final String[] SOUND_EFFECT_FILES = new String[] {
+        "Effect_Tick.ogg",
+        "KeypressStandard.ogg",
+        "KeypressSpacebar.ogg",
+        "KeypressDelete.ogg",
+        "KeypressReturn.ogg"
+    };
+
+    /* Sound effect file name mapping sound effect id (AudioManager.FX_xxx) to
+     * file index in SOUND_EFFECT_FILES[] (first column) and indicating if effect
+     * uses soundpool (second column) */
+    private int[][] SOUND_EFFECT_FILES_MAP = new int[][] {
+        {0, -1},  // FX_KEY_CLICK
+        {0, -1},  // FX_FOCUS_NAVIGATION_UP
+        {0, -1},  // FX_FOCUS_NAVIGATION_DOWN
+        {0, -1},  // FX_FOCUS_NAVIGATION_LEFT
+        {0, -1},  // FX_FOCUS_NAVIGATION_RIGHT
+        {1, -1},  // FX_KEYPRESS_STANDARD
+        {2, -1},  // FX_KEYPRESS_SPACEBAR
+        {3, -1},  // FX_FOCUS_DELETE
+        {4, -1}   // FX_FOCUS_RETURN
+    };
+
+    private AudioSystem.ErrorCallback mAudioSystemCallback = new AudioSystem.ErrorCallback() {
+        public void onError(int error) {
+            switch (error) {
+            case AudioSystem.AUDIO_STATUS_SERVER_DIED:
+                if (mMediaServerOk) {
+                    sendMsg(mAudioHandler, MSG_MEDIA_SERVER_DIED, SHARED_MSG, SENDMSG_NOOP, 0, 0,
+                            null, 1500);
+                }
+                break;
+            case AudioSystem.AUDIO_STATUS_OK:
+                if (!mMediaServerOk) {
+                    sendMsg(mAudioHandler, MSG_MEDIA_SERVER_STARTED, SHARED_MSG, SENDMSG_NOOP, 0, 0,
+                            null, 0);
+                }
+                break;
+            default:
+                break;
+            }
+       }
+    };
+
+    /**
+     * Current ringer mode from one of {@link AudioManager#RINGER_MODE_NORMAL},
+     * {@link AudioManager#RINGER_MODE_SILENT}, or
+     * {@link AudioManager#RINGER_MODE_VIBRATE}.
+     */
+    private int mRingerMode;
+
+    /** @see System#MODE_RINGER_STREAMS_AFFECTED */
+    private int mRingerModeAffectedStreams;
+
+    /** @see System#MUTE_STREAMS_AFFECTED */
+    private int mMuteAffectedStreams;
+
+    /**
+     * Has multiple bits per vibrate type to indicate the type's vibrate
+     * setting. See {@link #setVibrateSetting(int, int)}.
+     * <p>
+     * NOTE: This is not the final decision of whether vibrate is on/off for the
+     * type since it depends on the ringer mode. See {@link #shouldVibrate(int)}.
+     */
+    private int mVibrateSetting;
+
+    ///////////////////////////////////////////////////////////////////////////
+    // Construction
+    ///////////////////////////////////////////////////////////////////////////
+
+    /** @hide */
+    public AudioService(Context context) {
+        mContext = context;
+        mContentResolver = context.getContentResolver();
+        mVolumePanel = new VolumePanel(context, this);
+
+        createAudioSystemThread();
+        createStreamStates();
+        readPersistedSettings();
+        readAudioSettings();
+        mMediaServerOk = true;
+        AudioSystem.setErrorCallback(mAudioSystemCallback);
+        loadSoundEffects();
+    }
+
+    private void createAudioSystemThread() {
+        mAudioSystemThread = new AudioSystemThread();
+        mAudioSystemThread.start();
+        waitForAudioHandlerCreation();
+    }
+
+    /** Waits for the volume handler to be created by the other thread. */
+    private void waitForAudioHandlerCreation() {
+        synchronized(this) {
+            while (mAudioHandler == null) {
+                try {
+                    // Wait for mAudioHandler to be set by the other thread
+                    wait();
+                } catch (InterruptedException e) {
+                    Log.e(TAG, "Interrupted while waiting on volume handler.");
+                }
+            }
+        }
+    }
+
+    private void createStreamStates() {
+        final int[] volumeLevelsPhone =
+            createVolumeLevels(0, AudioManager.MAX_STREAM_VOLUME[AudioManager.STREAM_VOICE_CALL]);
+        final int[] volumeLevelsCoarse =
+            createVolumeLevels(0, AudioManager.MAX_STREAM_VOLUME[AudioManager.STREAM_SYSTEM]);
+        final int[] volumeLevelsFine =
+            createVolumeLevels(0, AudioManager.MAX_STREAM_VOLUME[AudioManager.STREAM_MUSIC]);
+        final int[] volumeLevelsBtPhone =
+            createVolumeLevels(0,
+                    AudioManager.MAX_STREAM_VOLUME[AudioManager.STREAM_BLUETOOTH_SCO]);
+
+        int numStreamTypes = AudioSystem.getNumStreamTypes();
+        VolumeStreamState[] streams = mStreamStates = new VolumeStreamState[numStreamTypes];
+
+        for (int i = 0; i < numStreamTypes; i++) {
+            final int[] levels;
+
+            switch (i) {
+
+                case AudioSystem.STREAM_MUSIC:
+                    levels = volumeLevelsFine;
+                    break;
+
+                case AudioSystem.STREAM_VOICE_CALL:
+                    levels = volumeLevelsPhone;
+                    break;
+
+                case AudioSystem.STREAM_BLUETOOTH_SCO:
+                    levels = volumeLevelsBtPhone;
+                    break;
+
+                default:
+                    levels = volumeLevelsCoarse;
+                    break;
+            }
+
+            if (i == AudioSystem.STREAM_BLUETOOTH_SCO) {
+                streams[i] = new VolumeStreamState(AudioManager.DEFAULT_STREAM_VOLUME[i], i,levels);
+            } else {
+                streams[i] = new VolumeStreamState(System.VOLUME_SETTINGS[i], i, levels);
+            }
+        }
+    }
+
+    private static int[] createVolumeLevels(int offset, int numlevels) {
+        double curve = 1.0f; // 1.4f
+        int [] volumes = new int[numlevels + offset];
+        for (int i = 0; i < offset; i++) {
+            volumes[i] = 0;
+        }
+
+        double val = 0;
+        double max = Math.pow(numlevels - 1, curve);
+        for (int i = 0; i < numlevels; i++) {
+            val = Math.pow(i, curve) / max;
+            volumes[offset + i] = (int) (val * 100.0f);
+        }
+        return volumes;
+    }
+
+    private void readPersistedSettings() {
+        final ContentResolver cr = mContentResolver;
+
+        mRingerMode = System.getInt(cr, System.MODE_RINGER, AudioManager.RINGER_MODE_NORMAL);
+        mRingerModeAffectedStreams = System.getInt(mContentResolver,
+                System.MODE_RINGER_STREAMS_AFFECTED, 1 << AudioSystem.STREAM_RING);
+
+        mVibrateSetting = System.getInt(cr, System.VIBRATE_ON, 0);
+
+        mMuteAffectedStreams = System.getInt(cr,
+                System.MUTE_STREAMS_AFFECTED,
+                ((1 << AudioSystem.STREAM_MUSIC)|(1 << AudioSystem.STREAM_RING)|(1 << AudioSystem.STREAM_SYSTEM)));
+
+        // Each stream will read its own persisted settings
+
+        // Broadcast the sticky intent
+        broadcastRingerMode();
+
+        // Broadcast vibrate settings
+        broadcastVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER);
+        broadcastVibrateSetting(AudioManager.VIBRATE_TYPE_NOTIFICATION);
+    }
+
+    private void readAudioSettings() {
+        synchronized (mSettingsLock) {
+            mMicMute = AudioSystem.isMicrophoneMuted();
+            mMode = AudioSystem.getMode();
+            for (int mode = 0; mode < AudioSystem.NUM_MODES; mode++) {
+                mRoutes[mode] = AudioSystem.getRouting(mode);
+            }
+        }
+    }
+
+    private void applyAudioSettings() {
+        synchronized (mSettingsLock) {
+            AudioSystem.muteMicrophone(mMicMute);
+            AudioSystem.setMode(mMode);
+            for (int mode = 0; mode < AudioSystem.NUM_MODES; mode++) {
+                AudioSystem.setRouting(mode, mRoutes[mode], AudioSystem.ROUTE_ALL);
+            }
+        }
+   }
+
+    ///////////////////////////////////////////////////////////////////////////
+    // IPC methods
+    ///////////////////////////////////////////////////////////////////////////
+
+    /** @see AudioManager#adjustVolume(int, int) */
+    public void adjustVolume(int direction, int flags) {
+        adjustSuggestedStreamVolume(direction, AudioManager.USE_DEFAULT_STREAM_TYPE, flags);
+    }
+
+    /** @see AudioManager#adjustVolume(int, int, int) */
+    public void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags) {
+
+        int streamType = getActiveStreamType(suggestedStreamType);
+
+        // Don't play sound on other streams
+        if (streamType != AudioSystem.STREAM_RING && (flags & AudioManager.FLAG_PLAY_SOUND) != 0) {
+            flags &= ~AudioManager.FLAG_PLAY_SOUND;
+        }
+
+        adjustStreamVolume(streamType, direction, flags);
+    }
+
+    /** @see AudioManager#adjustStreamVolume(int, int, int) */
+    public void adjustStreamVolume(int streamType, int direction, int flags) {
+        ensureValidDirection(direction);
+        ensureValidStreamType(streamType);
+
+        boolean notificationsUseRingVolume = Settings.System.getInt(mContentResolver,
+                Settings.System.NOTIFICATIONS_USE_RING_VOLUME, 1) == 1;
+        if (notificationsUseRingVolume && streamType == AudioManager.STREAM_NOTIFICATION) {
+            // Redirect the volume change to the ring stream
+            streamType = AudioManager.STREAM_RING;
+        }
+
+        VolumeStreamState streamState = mStreamStates[streamType];
+        final int oldIndex = streamState.mIndex;
+        boolean adjustVolume = true;
+
+        // If either the client forces allowing ringer modes for this adjustment,
+        // or the stream type is one that is affected by ringer modes
+        if ((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0
+                || streamType == AudioManager.STREAM_RING) {
+            // Check if the ringer mode changes with this volume adjustment. If
+            // it does, it will handle adjusting the volume, so we won't below
+            adjustVolume = checkForRingerModeChange(oldIndex, direction);
+        }
+
+        if (adjustVolume && streamState.adjustIndex(direction)) {
+
+            boolean alsoUpdateNotificationVolume =  notificationsUseRingVolume &&
+                    streamType == AudioManager.STREAM_RING;
+            if (alsoUpdateNotificationVolume) {
+                mStreamStates[AudioManager.STREAM_NOTIFICATION].adjustIndex(direction);
+            }
+
+            // Post message to set system volume (it in turn will post a message
+            // to persist). Do not change volume if stream is muted.
+            if (streamState.muteCount() == 0) {
+                sendMsg(mAudioHandler, MSG_SET_SYSTEM_VOLUME, streamType, SENDMSG_NOOP, 0, 0,
+                        streamState, 0);
+
+                if (alsoUpdateNotificationVolume) {
+                    sendMsg(mAudioHandler, MSG_SET_SYSTEM_VOLUME, AudioManager.STREAM_NOTIFICATION,
+                            SENDMSG_NOOP, 0, 0, mStreamStates[AudioManager.STREAM_NOTIFICATION], 0);
+                }
+            }
+        }
+
+        // UI
+        mVolumePanel.postVolumeChanged(streamType, flags);
+        // Broadcast Intent
+        sendVolumeUpdate(streamType);
+    }
+
+    /** @see AudioManager#setStreamVolume(int, int, int) */
+    public void setStreamVolume(int streamType, int index, int flags) {
+        ensureValidStreamType(streamType);
+        syncRingerAndNotificationStreamVolume(streamType, index, false);
+
+        setStreamVolumeInt(streamType, index, false);
+
+        // UI, etc.
+        mVolumePanel.postVolumeChanged(streamType, flags);
+        // Broadcast Intent
+        sendVolumeUpdate(streamType);
+    }
+
+    private void sendVolumeUpdate(int streamType) {
+        Intent intent = new Intent(AudioManager.VOLUME_CHANGED_ACTION);
+        intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, streamType);
+        intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, getStreamVolume(streamType));
+
+        // Currently, sending the intent only when the stream is BLUETOOTH_SCO
+        if (streamType == AudioManager.STREAM_BLUETOOTH_SCO) {
+            mContext.sendBroadcast(intent);
+        }
+    }
+
+    /**
+     * Sync the STREAM_RING and STREAM_NOTIFICATION volumes if mandated by the
+     * value in Settings.
+     *
+     * @param streamType Type of the stream
+     * @param index Volume index for the stream
+     * @param force If true, set the volume even if the current and desired
+     * volume as same
+     */
+    private void syncRingerAndNotificationStreamVolume(int streamType, int index, boolean force) {
+        boolean notificationsUseRingVolume = Settings.System.getInt(mContentResolver,
+                Settings.System.NOTIFICATIONS_USE_RING_VOLUME, 1) == 1;
+        if (notificationsUseRingVolume) {
+            if (streamType == AudioManager.STREAM_NOTIFICATION) {
+                // Redirect the volume change to the ring stream
+                streamType = AudioManager.STREAM_RING;
+            }
+            if (streamType == AudioManager.STREAM_RING) {
+                // One-off to sync notification volume to ringer volume
+                setStreamVolumeInt(AudioManager.STREAM_NOTIFICATION, index, force);
+            }
+        }
+    }
+
+
+    /**
+     * Sets the stream state's index, and posts a message to set system volume.
+     * This will not call out to the UI. Assumes a valid stream type.
+     *
+     * @param streamType Type of the stream
+     * @param index Desired volume index of the stream
+     * @param force If true, set the volume even if the desired volume is same
+     * as the current volume.
+     */
+    private void setStreamVolumeInt(int streamType, int index, boolean force) {
+        VolumeStreamState streamState = mStreamStates[streamType];
+        if (streamState.setIndex(index) || force) {
+            // Post message to set system volume (it in turn will post a message
+            // to persist). Do not change volume if stream is muted.
+            if (streamState.muteCount() == 0) {
+                sendMsg(mAudioHandler, MSG_SET_SYSTEM_VOLUME, streamType, SENDMSG_NOOP, 0, 0,
+                        streamState, 0);
+            }
+        }
+    }
+
+    /** @see AudioManager#setStreamSolo(int, boolean) */
+    public void setStreamSolo(int streamType, boolean state, IBinder cb) {
+        for (int stream = 0; stream < mStreamStates.length; stream++) {
+            if (!isStreamAffectedByMute(stream) || stream == streamType) continue;
+            // Bring back last audible volume
+            mStreamStates[stream].mute(cb, state);
+         }
+    }
+
+    /** @see AudioManager#setStreamMute(int, boolean) */
+    public void setStreamMute(int streamType, boolean state, IBinder cb) {
+        if (isStreamAffectedByMute(streamType)) {
+            mStreamStates[streamType].mute(cb, state);
+        }
+    }
+
+    /** @see AudioManager#getStreamVolume(int) */
+    public int getStreamVolume(int streamType) {
+        ensureValidStreamType(streamType);
+        return mStreamStates[streamType].mIndex;
+    }
+
+    /** @see AudioManager#getStreamMaxVolume(int) */
+    public int getStreamMaxVolume(int streamType) {
+        ensureValidStreamType(streamType);
+        return mStreamStates[streamType].getMaxIndex();
+    }
+
+    /** @see AudioManager#getRingerMode() */
+    public int getRingerMode() {
+        return mRingerMode;
+    }
+
+    /** @see AudioManager#setRingerMode(int) */
+    public void setRingerMode(int ringerMode) {
+        if (ringerMode != mRingerMode) {
+            mRingerMode = ringerMode;
+
+            // Adjust volumes via posting message
+            int numStreamTypes = AudioSystem.getNumStreamTypes();
+            if (mRingerMode == AudioManager.RINGER_MODE_NORMAL) {
+                for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
+                    if (!isStreamAffectedByRingerMode(streamType)) continue;
+                    // Bring back last audible volume
+                    setStreamVolumeInt(streamType, mStreamStates[streamType].mLastAudibleIndex,
+                                       false);
+                }
+            } else {
+                for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
+                    if (!isStreamAffectedByRingerMode(streamType)) continue;
+                    // Either silent or vibrate, either way volume is 0
+                    setStreamVolumeInt(streamType, 0, false);
+                }
+            }
+
+            // Send sticky broadcast
+            broadcastRingerMode();
+
+            // Post a persist ringer mode msg
+            sendMsg(mAudioHandler, MSG_PERSIST_RINGER_MODE, SHARED_MSG,
+                    SENDMSG_REPLACE, 0, 0, null, PERSIST_DELAY);
+        }
+    }
+
+    /** @see AudioManager#shouldVibrate(int) */
+    public boolean shouldVibrate(int vibrateType) {
+
+        switch (getVibrateSetting(vibrateType)) {
+
+            case AudioManager.VIBRATE_SETTING_ON:
+                return mRingerMode != AudioManager.RINGER_MODE_SILENT;
+
+            case AudioManager.VIBRATE_SETTING_ONLY_SILENT:
+                return mRingerMode == AudioManager.RINGER_MODE_VIBRATE;
+
+            case AudioManager.VIBRATE_SETTING_OFF:
+                // Phone ringer should always vibrate in vibrate mode
+                if (vibrateType == AudioManager.VIBRATE_TYPE_RINGER) {
+                    return mRingerMode == AudioManager.RINGER_MODE_VIBRATE;
+                }
+
+            default:
+                return false;
+        }
+    }
+
+    /** @see AudioManager#getVibrateSetting(int) */
+    public int getVibrateSetting(int vibrateType) {
+        return (mVibrateSetting >> (vibrateType * 2)) & 3;
+    }
+
+    /** @see AudioManager#setVibrateSetting(int, int) */
+    public void setVibrateSetting(int vibrateType, int vibrateSetting) {
+
+        mVibrateSetting = getValueForVibrateSetting(mVibrateSetting, vibrateType, vibrateSetting);
+
+        // Broadcast change
+        broadcastVibrateSetting(vibrateType);
+
+        // Post message to set ringer mode (it in turn will post a message
+        // to persist)
+        sendMsg(mAudioHandler, MSG_PERSIST_VIBRATE_SETTING, SHARED_MSG, SENDMSG_NOOP, 0, 0,
+                null, 0);
+    }
+
+    /**
+     * @see #setVibrateSetting(int, int)
+     * @hide
+     */
+    public static int getValueForVibrateSetting(int existingValue, int vibrateType,
+            int vibrateSetting) {
+
+        // First clear the existing setting. Each vibrate type has two bits in
+        // the value. Note '3' is '11' in binary.
+        existingValue &= ~(3 << (vibrateType * 2));
+
+        // Set into the old value
+        existingValue |= (vibrateSetting & 3) << (vibrateType * 2);
+
+        return existingValue;
+    }
+
+    /** @see AudioManager#setMicrophoneMute(boolean) */
+    public void setMicrophoneMute(boolean on) {
+        if (!checkAudioSettingsPermission("setMicrophoneMute()")) {
+            return;
+        }
+        synchronized (mSettingsLock) {
+            if (on != mMicMute) {
+                AudioSystem.muteMicrophone(on);
+                mMicMute = on;
+            }
+        }
+    }
+
+    /** @see AudioManager#isMicrophoneMute() */
+    public boolean isMicrophoneMute() {
+        return mMicMute;
+    }
+
+    /** @see AudioManager#setMode(int) */
+    public void setMode(int mode) {
+        if (!checkAudioSettingsPermission("setMode()")) {
+            return;
+        }
+        synchronized (mSettingsLock) {
+            if (mode != mMode) {
+                AudioSystem.setMode(mode);
+                mMode = mode;
+            }
+            int streamType = getActiveStreamType(AudioManager.USE_DEFAULT_STREAM_TYPE);
+            int index = mStreamStates[streamType].mIndex;
+            syncRingerAndNotificationStreamVolume(streamType, index, true);
+            setStreamVolumeInt(streamType, index, true);
+        }
+    }
+
+    /** @see AudioManager#getMode() */
+    public int getMode() {
+        return mMode;
+    }
+
+    /** @see AudioManager#setRouting(int, int, int) */
+    public void setRouting(int mode, int routes, int mask) {
+        if (!checkAudioSettingsPermission("setRouting()")) {
+            return;
+        }
+        synchronized (mSettingsLock) {
+            if ((mRoutes[mode] & mask) != (routes & mask)) {
+                AudioSystem.setRouting(mode, routes, mask);
+                mRoutes[mode] = (mRoutes[mode] & ~mask) | (routes & mask);
+            }
+            int streamType = getActiveStreamType(AudioManager.USE_DEFAULT_STREAM_TYPE);
+            int index = mStreamStates[streamType].mIndex;
+            syncRingerAndNotificationStreamVolume(streamType, index, true);
+            setStreamVolumeInt(streamType, index, true);
+        }
+    }
+
+    /** @see AudioManager#getRouting(int) */
+    public int getRouting(int mode) {
+        return mRoutes[mode];
+    }
+
+    /** @see AudioManager#isMusicActive() */
+    public boolean isMusicActive() {
+        return AudioSystem.isMusicActive();
+    }
+
+    /** @see AudioManager#setParameter(String, String) */
+    public void setParameter(String key, String value) {
+        AudioSystem.setParameter(key, value);
+    }
+
+    /** @see AudioManager#playSoundEffect(int) */
+    public void playSoundEffect(int effectType) {
+        sendMsg(mAudioHandler, MSG_PLAY_SOUND_EFFECT, SHARED_MSG, SENDMSG_NOOP,
+                effectType, SOUND_EFFECT_VOLUME, null, 0);
+    }
+
+    /** @see AudioManager#playSoundEffect(int, float) */
+    /* @hide FIXME: unhide before release */
+    public void playSoundEffectVolume(int effectType, float volume) {
+        sendMsg(mAudioHandler, MSG_PLAY_SOUND_EFFECT, SHARED_MSG, SENDMSG_NOOP,
+                effectType, (int) (volume * 1000), null, 0);
+    }
+
+    /**
+     * Loads samples into the soundpool.
+     * This method must be called at when sound effects are enabled
+     */
+    public boolean loadSoundEffects() {
+        synchronized (mSoundEffectsLock) {
+            mSoundPool = new SoundPool(NUM_SOUNDPOOL_CHANNELS, AudioSystem.STREAM_SYSTEM, 0);
+            if (mSoundPool == null) {
+                return false;
+            }
+            /*
+             * poolId table: The value -1 in this table indicates that corresponding
+             * file (same index in SOUND_EFFECT_FILES[] has not been loaded.
+             * Once loaded, the value in poolId is the sample ID and the same
+             * sample can be reused for another effect using the same file.
+             */
+            int[] poolId = new int[SOUND_EFFECT_FILES.length];
+            for (int fileIdx = 0; fileIdx < SOUND_EFFECT_FILES.length; fileIdx++) {
+                poolId[fileIdx] = -1;
+            }
+            /*
+             * Effects whose value in SOUND_EFFECT_FILES_MAP[effect][1] is -1 must be loaded.
+             * If load succeeds, value in SOUND_EFFECT_FILES_MAP[effect][1] is > 0:
+             * this indicates we have a valid sample loaded for this effect.
+             */
+            for (int effect = 0; effect < AudioManager.NUM_SOUND_EFFECTS; effect++) {
+                // Do not load sample if this effect uses the MediaPlayer
+                if (SOUND_EFFECT_FILES_MAP[effect][1] == 0) {
+                    continue;
+                }
+                if (poolId[SOUND_EFFECT_FILES_MAP[effect][0]] == -1) {
+                    String filePath = Environment.getRootDirectory() + SOUND_EFFECTS_PATH + SOUND_EFFECT_FILES[SOUND_EFFECT_FILES_MAP[effect][0]];
+                    int sampleId = mSoundPool.load(filePath, 0);
+                    SOUND_EFFECT_FILES_MAP[effect][1] = sampleId;
+                    poolId[SOUND_EFFECT_FILES_MAP[effect][0]] = sampleId;
+                    if (sampleId <= 0) {
+                        Log.w(TAG, "Soundpool could not load file: "+filePath);
+                    }
+                } else {
+                    SOUND_EFFECT_FILES_MAP[effect][1] = poolId[SOUND_EFFECT_FILES_MAP[effect][0]];
+                }
+            }
+        }
+
+        return true;
+    }
+
+    /**
+     *  Unloads samples from the sound pool.
+     *  This method can be called to free some memory when
+     *  sound effects are disabled.
+     */
+    public void unloadSoundEffects() {
+        synchronized (mSoundEffectsLock) {
+            if (mSoundPool == null) {
+                return;
+            }
+            int[] poolId = new int[SOUND_EFFECT_FILES.length];
+            for (int fileIdx = 0; fileIdx < SOUND_EFFECT_FILES.length; fileIdx++) {
+                poolId[fileIdx] = 0;
+            }
+
+            for (int effect = 0; effect < AudioManager.NUM_SOUND_EFFECTS; effect++) {
+                if (SOUND_EFFECT_FILES_MAP[effect][1] <= 0) {
+                    continue;
+                }
+                if (poolId[SOUND_EFFECT_FILES_MAP[effect][0]] == 0) {
+                    mSoundPool.unload(SOUND_EFFECT_FILES_MAP[effect][1]);
+                    SOUND_EFFECT_FILES_MAP[effect][1] = -1;
+                    poolId[SOUND_EFFECT_FILES_MAP[effect][0]] = -1;
+                }
+            }
+            mSoundPool = null;
+        }
+    }
+
+    ///////////////////////////////////////////////////////////////////////////
+    // Internal methods
+    ///////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Checks if the adjustment should change ringer mode instead of just
+     * adjusting volume. If so, this will set the proper ringer mode and volume
+     * indices on the stream states.
+     */
+    private boolean checkForRingerModeChange(int oldIndex, int direction) {
+        boolean adjustVolumeIndex = true;
+        int newRingerMode = mRingerMode;
+
+        if (mRingerMode == AudioManager.RINGER_MODE_NORMAL && oldIndex == 1
+                && direction == AudioManager.ADJUST_LOWER) {
+            newRingerMode = AudioManager.RINGER_MODE_VIBRATE;
+        } else if (mRingerMode == AudioManager.RINGER_MODE_VIBRATE) {
+            if (direction == AudioManager.ADJUST_RAISE) {
+                newRingerMode = AudioManager.RINGER_MODE_NORMAL;
+            } else if (direction == AudioManager.ADJUST_LOWER) {
+                newRingerMode = AudioManager.RINGER_MODE_SILENT;
+            }
+        } else if (direction == AudioManager.ADJUST_RAISE
+                && mRingerMode == AudioManager.RINGER_MODE_SILENT) {
+            newRingerMode = AudioManager.RINGER_MODE_VIBRATE;
+        }
+
+        if (newRingerMode != mRingerMode) {
+            setRingerMode(newRingerMode);
+
+            /*
+             * If we are changing ringer modes, do not increment/decrement the
+             * volume index. Instead, the handler for the message above will
+             * take care of changing the index.
+             */
+            adjustVolumeIndex = false;
+        }
+
+        return adjustVolumeIndex;
+    }
+
+    public boolean isStreamAffectedByRingerMode(int streamType) {
+        return (mRingerModeAffectedStreams & (1 << streamType)) != 0;
+    }
+
+    public boolean isStreamAffectedByMute(int streamType) {
+        return (mMuteAffectedStreams & (1 << streamType)) != 0;
+    }
+
+    private void ensureValidDirection(int direction) {
+        if (direction < AudioManager.ADJUST_LOWER || direction > AudioManager.ADJUST_RAISE) {
+            throw new IllegalArgumentException("Bad direction " + direction);
+        }
+    }
+
+    private void ensureValidStreamType(int streamType) {
+        if (streamType < 0 || streamType >= mStreamStates.length) {
+            throw new IllegalArgumentException("Bad stream type " + streamType);
+        }
+    }
+
+    private int getActiveStreamType(int suggestedStreamType) {
+        boolean isOffhook = false;
+        try {
+            ITelephony phone = ITelephony.Stub.asInterface(ServiceManager.checkService("phone"));
+            if (phone != null) isOffhook = phone.isOffhook();
+        } catch (RemoteException e) {
+            Log.w(TAG, "Couldn't connect to phone service", e);
+        }
+
+        if ((getRouting(AudioSystem.MODE_IN_CALL) & AudioSystem.ROUTE_BLUETOOTH_SCO) != 0) {
+            // Log.v(TAG, "getActiveStreamType: Forcing STREAM_BLUETOOTH_SCO...");
+            return AudioSystem.STREAM_BLUETOOTH_SCO;
+        } else if (isOffhook) {
+            // Log.v(TAG, "getActiveStreamType: Forcing STREAM_VOICE_CALL...");
+            return AudioSystem.STREAM_VOICE_CALL;
+        } else if (AudioSystem.isMusicActive()) {
+            // Log.v(TAG, "getActiveStreamType: Forcing STREAM_MUSIC...");
+            return AudioSystem.STREAM_MUSIC;
+        } else if (suggestedStreamType == AudioManager.USE_DEFAULT_STREAM_TYPE) {
+            // Log.v(TAG, "getActiveStreamType: Forcing STREAM_RING...");
+            return AudioSystem.STREAM_RING;
+        } else {
+            // Log.v(TAG, "getActiveStreamType: Returning suggested type " + suggestedStreamType);
+            return suggestedStreamType;
+        }
+    }
+
+    private void broadcastRingerMode() {
+        // Send sticky broadcast
+        if (ActivityManagerNative.isSystemReady()) {
+            Intent broadcast = new Intent(AudioManager.RINGER_MODE_CHANGED_ACTION);
+            broadcast.putExtra(AudioManager.EXTRA_RINGER_MODE, mRingerMode);
+            long origCallerIdentityToken = Binder.clearCallingIdentity();
+            mContext.sendStickyBroadcast(broadcast);
+            Binder.restoreCallingIdentity(origCallerIdentityToken);
+        }
+    }
+
+    private void broadcastVibrateSetting(int vibrateType) {
+        // Send broadcast
+        if (ActivityManagerNative.isSystemReady()) {
+            Intent broadcast = new Intent(AudioManager.VIBRATE_SETTING_CHANGED_ACTION);
+            broadcast.putExtra(AudioManager.EXTRA_VIBRATE_TYPE, vibrateType);
+            broadcast.putExtra(AudioManager.EXTRA_VIBRATE_SETTING, getVibrateSetting(vibrateType));
+            mContext.sendBroadcast(broadcast);
+        }
+    }
+
+    // Message helper methods
+    private static int getMsg(int baseMsg, int streamType) {
+        return (baseMsg & 0xffff) | streamType << 16;
+    }
+
+    private static int getMsgBase(int msg) {
+        return msg & 0xffff;
+    }
+
+    private static void sendMsg(Handler handler, int baseMsg, int streamType,
+            int existingMsgPolicy, int arg1, int arg2, Object obj, int delay) {
+        int msg = (streamType == SHARED_MSG) ? baseMsg : getMsg(baseMsg, streamType);
+
+        if (existingMsgPolicy == SENDMSG_REPLACE) {
+            handler.removeMessages(msg);
+        } else if (existingMsgPolicy == SENDMSG_NOOP && handler.hasMessages(msg)) {
+            return;
+        }
+
+        handler
+                .sendMessageDelayed(handler.obtainMessage(msg, arg1, arg2, obj), delay);
+    }
+
+    boolean checkAudioSettingsPermission(String method) {
+        if (mContext.checkCallingOrSelfPermission("android.permission.MODIFY_AUDIO_SETTINGS")
+                == PackageManager.PERMISSION_GRANTED) {
+            return true;
+        }
+        String msg = "Audio Settings Permission Denial: " + method + " from pid="
+                + Binder.getCallingPid()
+                + ", uid=" + Binder.getCallingUid();
+        Log.w(TAG, msg);
+        return false;
+    }
+
+
+    ///////////////////////////////////////////////////////////////////////////
+    // Inner classes
+    ///////////////////////////////////////////////////////////////////////////
+
+    public class VolumeStreamState {
+        private final String mVolumeIndexSettingName;
+        private final String mLastAudibleVolumeIndexSettingName;
+        private final int mStreamType;
+
+        private final int[] mVolumes;
+        private int mIndex;
+        private int mLastAudibleIndex;
+        private ArrayList<VolumeDeathHandler> mDeathHandlers; //handles mute/solo requests client death
+
+        private VolumeStreamState(String settingName, int streamType, int[] volumes) {
+
+            mVolumeIndexSettingName = settingName;
+            mLastAudibleVolumeIndexSettingName = settingName + System.APPEND_FOR_LAST_AUDIBLE;
+
+            mStreamType = streamType;
+            mVolumes = volumes;
+
+            final ContentResolver cr = mContentResolver;
+            mIndex = getValidIndex(Settings.System.getInt(cr, mVolumeIndexSettingName, AudioManager.DEFAULT_STREAM_VOLUME[streamType]));
+            mLastAudibleIndex = getValidIndex(Settings.System.getInt(cr,
+                    mLastAudibleVolumeIndexSettingName, mIndex > 0 ? mIndex : AudioManager.DEFAULT_STREAM_VOLUME[streamType]));
+
+            AudioSystem.setVolume(streamType, volumes[mIndex]);
+            mDeathHandlers = new ArrayList<VolumeDeathHandler>();
+        }
+
+        /**
+         * Constructor to be used when there is no setting associated with the VolumeStreamState.
+         *
+         * @param defaultVolume Default volume of the stream to use.
+         * @param streamType Type of the stream.
+         * @param volumes Volumes levels associated with this stream.
+         */
+        private VolumeStreamState(int defaultVolume, int streamType, int[] volumes) {
+            mVolumeIndexSettingName = null;
+            mLastAudibleVolumeIndexSettingName = null;
+            mIndex = mLastAudibleIndex = defaultVolume;
+            mStreamType = streamType;
+            mVolumes = volumes;
+            AudioSystem.setVolume(mStreamType, defaultVolume);
+            mDeathHandlers = new ArrayList<VolumeDeathHandler>();
+        }
+
+        public boolean adjustIndex(int deltaIndex) {
+            return setIndex(mIndex + deltaIndex);
+        }
+
+        public boolean setIndex(int index) {
+            int oldIndex = mIndex;
+            mIndex = getValidIndex(index);
+
+            if (oldIndex != mIndex) {
+                if (mIndex > 0) {
+                    mLastAudibleIndex = mIndex;
+                }
+                return true;
+            } else {
+                return false;
+            }
+        }
+
+        public int getMaxIndex() {
+            return mVolumes.length - 1;
+        }
+
+        public void mute(IBinder cb, boolean state) {
+            VolumeDeathHandler handler = getDeathHandler(cb, state);
+            if (handler == null) {
+                Log.e(TAG, "Could not get client death handler for stream: "+mStreamType);
+                return;
+            }
+            handler.mute(state);
+        }
+
+        private int getValidIndex(int index) {
+            if (index < 0) {
+                return 0;
+            } else if (index >= mVolumes.length) {
+                return mVolumes.length - 1;
+            }
+
+            return index;
+        }
+
+        private class VolumeDeathHandler implements IBinder.DeathRecipient {
+            private IBinder mICallback; // To be notified of client's death
+            private int mMuteCount; // Number of active mutes for this client
+
+            VolumeDeathHandler(IBinder cb) {
+                mICallback = cb;
+            }
+
+            public void mute(boolean state) {
+                synchronized(mDeathHandlers) {
+                    if (state) {
+                        if (mMuteCount == 0) {
+                            // Register for client death notification
+                            try {
+                                mICallback.linkToDeath(this, 0);
+                                mDeathHandlers.add(this);
+                                // If the stream is not yet muted by any client, set lvel to 0
+                                if (muteCount() == 0) {
+                                    setIndex(0);
+                                    sendMsg(mAudioHandler, MSG_SET_SYSTEM_VOLUME, mStreamType, SENDMSG_NOOP, 0, 0,
+                                            VolumeStreamState.this, 0);
+                                }
+                            } catch (RemoteException e) {
+                                // Client has died!
+                                binderDied();
+                                mDeathHandlers.notify();
+                                return;
+                            }
+                        } else {
+                            Log.w(TAG, "stream: "+mStreamType+" was already muted by this client");
+                        }
+                        mMuteCount++;
+                    } else {
+                        if (mMuteCount == 0) {
+                            Log.e(TAG, "unexpected unmute for stream: "+mStreamType);
+                        } else {
+                            mMuteCount--;
+                            if (mMuteCount == 0) {
+                                // Unregistr from client death notification
+                                mDeathHandlers.remove(this);
+                                mICallback.unlinkToDeath(this, 0);
+                                if (muteCount() == 0) {
+                                    // If the stream is not mut any more, restore it's volume if
+                                    // ringer mode allows it
+                                    if (!isStreamAffectedByRingerMode(mStreamType) || mRingerMode == AudioManager.RINGER_MODE_NORMAL) {
+                                        setIndex(mLastAudibleIndex);
+                                        sendMsg(mAudioHandler, MSG_SET_SYSTEM_VOLUME, mStreamType, SENDMSG_NOOP, 0, 0,
+                                                VolumeStreamState.this, 0);
+                                    }
+                                }
+                            }
+                        }
+                    }
+                    mDeathHandlers.notify();
+                }
+            }
+
+            public void binderDied() {
+                Log.w(TAG, "Volume service client died for stream: "+mStreamType);
+                if (mMuteCount != 0) {
+                    // Reset all active mute requests from this client.
+                    mMuteCount = 1;
+                    mute(false);
+                }
+            }
+        }
+
+        private int muteCount() {
+            int count = 0;
+            int size = mDeathHandlers.size();
+            for (int i = 0; i < size; i++) {
+                count += mDeathHandlers.get(i).mMuteCount;
+            }
+            return count;
+        }
+
+        private VolumeDeathHandler getDeathHandler(IBinder cb, boolean state) {
+            synchronized(mDeathHandlers) {
+                VolumeDeathHandler handler;
+                int size = mDeathHandlers.size();
+                for (int i = 0; i < size; i++) {
+                    handler = mDeathHandlers.get(i);
+                    if (cb.equals(handler.mICallback)) {
+                        return handler;
+                    }
+                }
+                // If this is the first mute request for this client, create a new
+                // client death handler. Otherwise, it is an out of sequence unmute request.
+                if (state) {
+                    handler = new VolumeDeathHandler(cb);
+                } else {
+                    Log.w(TAG, "stream was not muted by this client");
+                    handler = null;
+                }
+                return handler;
+            }
+        }
+    }
+
+    /** Thread that handles native AudioSystem control. */
+    private class AudioSystemThread extends Thread {
+        AudioSystemThread() {
+            super("AudioService");
+        }
+
+        @Override
+        public void run() {
+            // Set this thread up so the handler will work on it
+            Looper.prepare();
+
+            synchronized(AudioService.this) {
+                mAudioHandler = new AudioHandler();
+
+                // Notify that the handler has been created
+                AudioService.this.notify();
+            }
+
+            // Listen for volume change requests that are set by VolumePanel
+            Looper.loop();
+        }
+    }
+
+    /** Handles internal volume messages in separate volume thread. */
+    private class AudioHandler extends Handler {
+
+        private void setSystemVolume(VolumeStreamState streamState) {
+
+            // Adjust volume
+            AudioSystem
+                    .setVolume(streamState.mStreamType, streamState.mVolumes[streamState.mIndex]);
+
+            // Post a persist volume msg
+            sendMsg(mAudioHandler, MSG_PERSIST_VOLUME, streamState.mStreamType,
+                    SENDMSG_REPLACE, 0, 0, streamState, PERSIST_DELAY);
+        }
+
+        private void persistVolume(VolumeStreamState streamState) {
+            System.putInt(mContentResolver, streamState.mVolumeIndexSettingName,
+                    streamState.mIndex);
+            System.putInt(mContentResolver, streamState.mLastAudibleVolumeIndexSettingName,
+                    streamState.mLastAudibleIndex);
+        }
+
+        private void persistRingerMode() {
+            System.putInt(mContentResolver, System.MODE_RINGER, mRingerMode);
+        }
+
+        private void persistVibrateSetting() {
+            System.putInt(mContentResolver, System.VIBRATE_ON, mVibrateSetting);
+        }
+
+        private void playSoundEffect(int effectType, int volume) {
+            synchronized (mSoundEffectsLock) {
+                if (mSoundPool == null) {
+                    return;
+                }
+
+                if (SOUND_EFFECT_FILES_MAP[effectType][1] > 0) {
+                    float v = (float) volume / 1000.0f;
+                    mSoundPool.play(SOUND_EFFECT_FILES_MAP[effectType][1], v, v, 0, 0, 1.0f);
+                } else {
+                    MediaPlayer mediaPlayer = new MediaPlayer();
+                    if (mediaPlayer != null) {
+                        try {
+                            String filePath = Environment.getRootDirectory() + SOUND_EFFECTS_PATH + SOUND_EFFECT_FILES[SOUND_EFFECT_FILES_MAP[effectType][0]];
+                            mediaPlayer.setDataSource(filePath);
+                            mediaPlayer.setAudioStreamType(AudioSystem.STREAM_SYSTEM);
+                            mediaPlayer.prepare();
+                            mediaPlayer.setOnCompletionListener(new OnCompletionListener() {
+                                public void onCompletion(MediaPlayer mp) {
+                                    cleanupPlayer(mp);
+                                }
+                            });
+                            mediaPlayer.setOnErrorListener(new OnErrorListener() {
+                                public boolean onError(MediaPlayer mp, int what, int extra) {
+                                    cleanupPlayer(mp);
+                                    return true;
+                                }
+                            });
+                            mediaPlayer.start();
+                        } catch (IOException ex) {
+                            Log.w(TAG, "MediaPlayer IOException: "+ex);
+                        } catch (IllegalArgumentException ex) {
+                            Log.w(TAG, "MediaPlayer IllegalArgumentException: "+ex);
+                        } catch (IllegalStateException ex) {
+                            Log.w(TAG, "MediaPlayer IllegalStateException: "+ex);
+                        }
+                    }
+                }
+            }
+        }
+
+        private void cleanupPlayer(MediaPlayer mp) {
+            if (mp != null) {
+                try {
+                    mp.stop();
+                    mp.release();
+                } catch (IllegalStateException ex) {
+                    Log.w(TAG, "MediaPlayer IllegalStateException: "+ex);
+                }
+            }
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            int baseMsgWhat = getMsgBase(msg.what);
+
+            switch (baseMsgWhat) {
+
+                case MSG_SET_SYSTEM_VOLUME:
+                    setSystemVolume((VolumeStreamState) msg.obj);
+                    break;
+
+                case MSG_PERSIST_VOLUME:
+                    persistVolume((VolumeStreamState) msg.obj);
+                    break;
+
+                case MSG_PERSIST_RINGER_MODE:
+                    persistRingerMode();
+                    break;
+
+                case MSG_PERSIST_VIBRATE_SETTING:
+                    persistVibrateSetting();
+                    break;
+
+                case MSG_MEDIA_SERVER_DIED:
+                    Log.e(TAG, "Media server died.");
+                    // Force creation of new IAudioflinger interface
+                    mMediaServerOk = false;
+                    AudioSystem.getMode();
+                    break;
+
+                case MSG_MEDIA_SERVER_STARTED:
+                    Log.e(TAG, "Media server started.");
+                    // Restore audio routing and stream volumes
+                    applyAudioSettings();
+                    int numStreamTypes = AudioSystem.getNumStreamTypes();
+                    for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
+                        int volume;
+                        VolumeStreamState streamState = mStreamStates[streamType];
+                        if (streamState.muteCount() == 0) {
+                            volume = streamState.mVolumes[streamState.mIndex];
+                        } else {
+                            volume = streamState.mVolumes[0];
+                        }
+                        AudioSystem.setVolume(streamType, volume);
+                    }
+                    setRingerMode(mRingerMode);
+                    mMediaServerOk = true;
+                    break;
+
+                case MSG_PLAY_SOUND_EFFECT:
+                    playSoundEffect(msg.arg1, msg.arg2);
+                    break;
+            }
+        }
+    }
+
+}
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
new file mode 100644
index 0000000..d0fa795
--- /dev/null
+++ b/media/java/android/media/AudioSystem.java
@@ -0,0 +1,223 @@
+/*
+ * 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.
+ */
+
+package android.media;
+
+
+/* IF YOU CHANGE ANY OF THE CONSTANTS IN THIS FILE, DO NOT FORGET
+ * TO UPDATE THE CORRESPONDING NATIVE GLUE.  THANK YOU FOR YOUR COOPERATION
+ */
+
+/**
+ * @hide
+ */
+public class AudioSystem
+{
+    /* FIXME: Need to finalize this and correlate with native layer */
+    /*
+     * If these are modified, please also update Settings.System.VOLUME_SETTINGS
+     * and attrs.xml
+     */
+    /* The audio stream for phone calls */
+    public static final int STREAM_VOICE_CALL = 0;
+    /* The audio stream for system sounds */
+    public static final int STREAM_SYSTEM = 1;
+    /* The audio stream for the phone ring and message alerts */
+    public static final int STREAM_RING = 2;
+    /* The audio stream for music playback */
+    public static final int STREAM_MUSIC = 3;
+    /* The audio stream for alarms */
+    public static final int STREAM_ALARM = 4;
+    /* The audio stream for notifications */
+    public static final int STREAM_NOTIFICATION = 5;
+    /* @hide The audio stream for phone calls when connected on bluetooth */
+    public static final int STREAM_BLUETOOTH_SCO = 6;
+    /**
+     * @deprecated Use {@link #numStreamTypes() instead}
+     */
+    public static final int NUM_STREAMS = 5;
+
+    // Expose only the getter method publicly so we can change it in the future
+    private static final int NUM_STREAM_TYPES = 7;
+    public static final int getNumStreamTypes() { return NUM_STREAM_TYPES; }
+
+    /* max and min volume levels */
+    /* Maximum volume setting, for use with setVolume(int,int) */
+    public static final int MAX_VOLUME = 100;
+    /* Minimum volume setting, for use with setVolume(int,int) */
+    public static final int MIN_VOLUME = 0;
+
+    /*
+     * Sets the volume of a specified audio stream.
+     *
+     * param type   the stream type to set the volume of (e.g. STREAM_MUSIC)
+     * param volume the volume level to set (0-100)
+     * return command completion status see AUDIO_STATUS_OK, see AUDIO_STATUS_ERROR
+     */
+    public static native int setVolume(int type, int volume);
+
+    /*
+     * Returns the volume of a specified audio stream.
+     *
+     * param type the stream type to get the volume of (e.g. STREAM_MUSIC)
+     * return the current volume (0-100)
+     */
+    public static native int getVolume(int type);
+
+    /*
+     * Sets the microphone mute on or off.
+     *
+     * param on set <var>true</var> to mute the microphone;
+     *           <var>false</var> to turn mute off
+     * return command completion status see AUDIO_STATUS_OK, see AUDIO_STATUS_ERROR
+     */
+    public static native int muteMicrophone(boolean on);
+
+    /*
+     * Checks whether the microphone mute is on or off.
+     *
+     * return true if microphone is muted, false if it's not
+     */
+    public static native boolean isMicrophoneMuted();
+
+    /*
+     * Sets the audio mode.
+     *
+     * param mode  the requested audio mode (NORMAL, RINGTONE, or IN_CALL).
+     *              Informs the HAL about the current audio state so that
+     *              it can route the audio appropriately.
+     * return command completion status see AUDIO_STATUS_OK, see AUDIO_STATUS_ERROR
+     */
+    public static native int setMode(int mode);
+
+    /*
+     * Returns the current audio mode.
+     *
+     * return      the current audio mode (NORMAL, RINGTONE, or IN_CALL).
+     *              Returns the current current audio state from the HAL.
+     */
+    public static native int getMode();
+
+    /* modes for setMode/getMode/setRoute/getRoute */
+    public static final int MODE_INVALID            = -2;
+    public static final int MODE_CURRENT            = -1;
+    public static final int MODE_NORMAL             = 0;
+    public static final int MODE_RINGTONE           = 1;
+    public static final int MODE_IN_CALL            = 2;
+    public static final int NUM_MODES               = 3;
+
+
+    /* Routing bits for setRouting/getRouting API */
+    public static final int ROUTE_EARPIECE          = (1 << 0);
+    public static final int ROUTE_SPEAKER           = (1 << 1);
+
+    /** @deprecated use {@link #ROUTE_BLUETOOTH_SCO} */
+    @Deprecated public static final int ROUTE_BLUETOOTH = (1 << 2);
+    public static final int ROUTE_BLUETOOTH_SCO     = (1 << 2);
+    public static final int ROUTE_HEADSET           = (1 << 3);
+    public static final int ROUTE_BLUETOOTH_A2DP    = (1 << 4);
+    public static final int ROUTE_ALL               = 0xFFFFFFFF;
+
+    /*
+     * Sets the audio routing for a specified mode
+     *
+     * param mode   audio mode to change route. E.g., MODE_RINGTONE.
+     * param routes bit vector of routes requested, created from one or
+     *               more of ROUTE_xxx types. Set bits indicate that route should be on
+     * param mask   bit vector of routes to change, created from one or more of
+     * ROUTE_xxx types. Unset bits indicate the route should be left unchanged
+     * return command completion status see AUDIO_STATUS_OK, see AUDIO_STATUS_ERROR
+     */
+    public static native int setRouting(int mode, int routes, int mask);
+
+    /*
+     * Returns the current audio routing bit vector for a specified mode.
+     *
+     * param mode audio mode to change route (e.g., MODE_RINGTONE)
+     * return an audio route bit vector that can be compared with ROUTE_xxx
+     * bits
+     */
+    public static native int getRouting(int mode);
+
+    /*
+     * Checks whether any music is active.
+     *
+     * return true if any music tracks are active.
+     */
+    public static native boolean isMusicActive();
+
+    /*
+     * Sets a generic audio configuration parameter. The use of these parameters
+     * are platform dependant, see libaudio
+     *
+     * ** Temporary interface - DO NOT USE
+     *
+     * TODO: Replace with a more generic key:value get/set mechanism
+     *
+     * param key   name of parameter to set. Must not be null.
+     * param value value of parameter. Must not be null.
+     */
+    public static native void setParameter(String key, String value);
+
+    /*
+    private final static String TAG = "audio";
+
+    private void log(String msg) {
+        Log.d(TAG, "[AudioSystem] " + msg);
+    }
+    */
+
+    // These match the enum in libs/android_runtime/android_media_AudioSystem.cpp
+    /* Command sucessful or Media server restarted. see ErrorCallback */
+    public static final int AUDIO_STATUS_OK = 0;
+    /* Command failed or unspecified audio error.  see ErrorCallback */
+    public static final int AUDIO_STATUS_ERROR = 1;
+    /* Media server died. see ErrorCallback */
+    public static final int AUDIO_STATUS_SERVER_DIED = 100;
+
+    private static ErrorCallback mErrorCallback;
+
+    /*
+     * Handles the audio error callback.
+     */
+    public interface ErrorCallback
+    {
+        /*
+         * Callback for audio server errors.
+         * param error   error code:
+         * - AUDIO_STATUS_OK
+         * - AUDIO_STATUS_SERVER_DIED
+         * - UDIO_STATUS_ERROR
+         */
+        void onError(int error);
+    };
+
+    /*
+     * Registers a callback to be invoked when an error occurs.
+     * param cb the callback to run
+     */
+    public static void setErrorCallback(ErrorCallback cb)
+    {
+        mErrorCallback = cb;
+    }
+
+    private static void errorCallbackFromNative(int error)
+    {
+        if (mErrorCallback != null) {
+            mErrorCallback.onError(error);
+        }
+    }
+}
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
new file mode 100644
index 0000000..997cd44
--- /dev/null
+++ b/media/java/android/media/AudioTrack.java
@@ -0,0 +1,1050 @@
+/*
+ * 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.
+ */
+
+package android.media;
+
+import java.lang.ref.WeakReference;
+import java.lang.IllegalArgumentException;
+import java.lang.IllegalStateException;
+
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.media.AudioManager;
+import android.util.Log;
+
+
+/**
+ * The AudioTrack class manages and plays a single audio resource for Java applications.
+ * It allows to stream PCM audio buffers to the audio hardware for playback. This is
+ * achieved by "pushing" the data to the AudioTrack object using one of the
+ *  {@link #write(byte[], int, int)} and {@link #write(short[], int, int)} methods.
+ * <p>An AudioTrack instance can operate under two modes: static of streaming.<br>
+ * The Streaming mode consists in continuously writing data to the AudioTrack, using one
+ * of the write() methods. These are blocking and return when the data has been transferred
+ * from the Java layer to the native layer, and is queued for playback. The streaming mode
+ *  is most useful when playing blocks of audio data that for instance are:
+ * <ul>
+ *   <li>too big to fit in memory because of the duration of the sound to play,</li>
+ *   <li>too big to fit in memory because of the characteristics of the audio data
+ *         (high sampling rate, bits per sample ...)</li>
+ *   <li>chosen, received or generated as the audio keeps playing.</li>
+ * </ul>
+ * The static mode is to be chosen when dealing with short sounds that fit in memory and
+ * that need to be played with the smallest latency possible. Static mode AudioTrack instances can
+ * play the sound without the need to transfer the audio data from Java to the audio hardware
+ * each time the sound is to be played. The static mode will therefore be preferred for UI and
+ * game sounds that are played often, and with the smallest overhead possible.
+ * <p>Upon creation, an AudioTrack object initializes its associated audio buffer.
+ * The size of this buffer, specified during the construction, determines how long an AudioTrack
+ * can play before running out of data.<br>
+ * For an AudioTrack using the static mode, this size is the maximum size of the sound that can
+ * be played from it.<br>
+ * For the streaming mode, data will be written to the hardware in chunks of
+ * sizes inferior to the total buffer size.
+ */
+public class AudioTrack
+{
+    //---------------------------------------------------------
+    // Constants
+    //--------------------
+    /** Minimum value for a channel volume */
+    private static final float VOLUME_MIN = 0.0f;
+    /** Maximum value for a channel volume */
+    private static final float VOLUME_MAX = 1.0f;
+
+    /** state of an AudioTrack this is stopped */
+    public static final int PLAYSTATE_STOPPED = 1;  // matches SL_PLAYSTATE_STOPPED
+    /** state of an AudioTrack this is paused */
+    public static final int PLAYSTATE_PAUSED  = 2;  // matches SL_PLAYSTATE_PAUSED
+    /** state of an AudioTrack this is playing */
+    public static final int PLAYSTATE_PLAYING = 3;  // matches SL_PLAYSTATE_PLAYING
+
+    /**
+     * Creation mode where audio data is transferred from Java to the native layer
+     * only once before the audio starts playing.
+     */
+    public static final int MODE_STATIC = 0;
+    /**
+     * Creation mode where audio data is streamed from Java to the native layer
+     * as the audio is playing.
+     */
+    public static final int MODE_STREAM = 1;
+
+    /**
+     * State of an AudioTrack that was not successfully initialized upon creation
+     */
+    public static final int STATE_UNINITIALIZED = 0;
+    /**
+     * State of an AudioTrack that is ready to be used.
+     */
+    public static final int STATE_INITIALIZED   = 1;
+    /**
+     * State of a successfully initialized AudioTrack that uses static data,
+     * but that hasn't received that data yet.
+     */
+    public static final int STATE_NO_STATIC_DATA = 2;
+
+    // Error codes:
+    // to keep in sync with frameworks/base/core/jni/android_media_AudioTrack.cpp
+    /**
+     * Denotes a successful operation.
+     */
+    public  static final int SUCCESS                               = 0;
+    /**
+     * Denotes a generic operation failure.
+     */
+    public  static final int ERROR                                 = -1;
+    /**
+     * Denotes a failure due to the use of an invalid value.
+     */
+    public  static final int ERROR_BAD_VALUE                       = -2;
+    /**
+     * Denotes a failure due to the improper use of a method.
+     */
+    public  static final int ERROR_INVALID_OPERATION               = -3;
+
+    private static final int ERROR_NATIVESETUP_AUDIOSYSTEM         = -16;
+    private static final int ERROR_NATIVESETUP_INVALIDCHANNELCOUNT = -17;
+    private static final int ERROR_NATIVESETUP_INVALIDFORMAT       = -18;
+    private static final int ERROR_NATIVESETUP_INVALIDSTREAMTYPE   = -19;
+    private static final int ERROR_NATIVESETUP_NATIVEINITFAILED    = -20;
+
+    // Events:
+    // to keep in sync with frameworks/base/include/media/AudioTrack.h
+    /**
+     * Event id for when the playback head has reached a previously set marker.
+     */
+    private static final int NATIVE_EVENT_MARKER  = 3;
+    /**
+     * Event id for when the previously set update period has passed during playback.
+     */
+    private static final int NATIVE_EVENT_NEW_POS = 4;
+
+    private final static String TAG = "AudioTrack-Java";
+
+
+    //--------------------------------------------------------------------------
+    // Member variables
+    //--------------------
+    /**
+     * Indicates the state of the AudioTrack instance
+     */
+    private int mState = STATE_UNINITIALIZED;
+    /**
+     * Indicates the play state of the AudioTrack instance
+     */
+    private int mPlayState = PLAYSTATE_STOPPED;
+    /**
+     * Lock to make sure mPlayState updates are reflecting the actual state of the object.
+     */
+    private final Object mPlayStateLock = new Object();
+    /**
+     * The listener the AudioTrack notifies previously set marker is reached.
+     *  @see #setMarkerReachedListener(OnMarkerReachedListener)
+     */
+    private OnMarkerReachedListener mMarkerListener = null;
+    /**
+     * Lock to protect marker listener updates against event notifications
+     */
+    private final Object mMarkerListenerLock = new Object();
+    /**
+     * The listener the AudioTrack notifies periodically during playback.
+     *  @see #setPeriodicNotificationListener(OnPeriodicNotificationListener)
+     */
+    private OnPeriodicNotificationListener mPeriodicListener = null;
+    /**
+     * Lock to protect periodic listener updates against event notifications
+     */
+    private final Object mPeriodicListenerLock = new Object();
+    /**
+     * Size of the native audio buffer.
+     */
+    private int mNativeBufferSizeInBytes = 0;
+    /**
+     * Handler for events coming from the native code
+     */
+    private NativeEventHandler mNativeEventHandler = null;
+    /**
+     * The audio data sampling rate in Hz.
+     */
+    private int mSampleRate = 22050;
+    /**
+     * The number of input audio channels (1 is mono, 2 is stereo)
+     */
+    private int mChannelCount = 1;
+    /**
+     * The type of the audio stream to play. See
+     *   {@link AudioManager#STREAM_VOICE_CALL}, {@link AudioManager#STREAM_SYSTEM},
+     *   {@link AudioManager#STREAM_RING}, {@link AudioManager#STREAM_MUSIC} and
+     *   {@link AudioManager#STREAM_ALARM}
+     */
+    private int mStreamType = AudioManager.STREAM_MUSIC;
+    /**
+     * The way audio is consumed by the hardware, streaming or static.
+     */
+    private int mDataLoadMode = MODE_STREAM;
+    /**
+     * The current audio channel configuration
+     */
+    private int mChannelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_MONO;
+    /**
+     * The encoding of the audio samples.
+     * @see AudioFormat#ENCODING_PCM_8BIT
+     * @see AudioFormat#ENCODING_PCM_16BIT
+     */
+    private int mAudioFormat = AudioFormat.ENCODING_PCM_16BIT;
+
+
+    //--------------------------------
+    // Used exclusively by native code
+    //--------------------
+    /**
+     * Accessed by native methods: provides access to C++ AudioTrack object
+     */
+    @SuppressWarnings("unused")
+    private int mNativeTrackInJavaObj;
+    /**
+     * Accessed by native methods: provides access to the JNI data (i.e. resources used by
+     * the native AudioTrack object, but not stored in it).
+     */
+    @SuppressWarnings("unused")
+    private int mJniData;
+
+
+    //--------------------------------------------------------------------------
+    // Constructor, Finalize
+    //--------------------
+    /**
+     * Class constructor.
+     * @param streamType the type of the audio stream. See
+
+     *   {@link AudioManager#STREAM_VOICE_CALL}, {@link AudioManager#STREAM_SYSTEM},
+     *   {@link AudioManager#STREAM_RING}, {@link AudioManager#STREAM_MUSIC} and
+     *   {@link AudioManager#STREAM_ALARM}
+     * @param sampleRateInHz the sample rate expressed in Hertz. Examples of rates are (but
+     *   not limited to) 44100, 22050 and 11025.
+     * @param channelConfig describes the configuration of the audio channels.
+
+     *   See {@link AudioFormat#CHANNEL_CONFIGURATION_MONO} and
+     *   {@link AudioFormat#CHANNEL_CONFIGURATION_STEREO}
+
+     * @param audioFormat the format in which the audio data is represented.
+     *   See {@link AudioFormat#ENCODING_PCM_16BIT} and
+     *   {@link AudioFormat#ENCODING_PCM_8BIT}
+     * @param bufferSizeInBytes the total size (in bytes) of the buffer where audio data is read
+     *   from for playback. If using the AudioTrack in streaming mode, you can write data into
+     *   this buffer in smaller chunks than this size. If using the AudioTrack in static mode,
+     *   this is the maximum size of the sound that will be played for this instance.
+     * @param mode streaming or static buffer. See {@link #MODE_STATIC} and {@link #MODE_STREAM}
+     * @throws java.lang.IllegalArgumentException
+     */
+    public AudioTrack(int streamType, int sampleRateInHz, int channelConfig, int audioFormat,
+            int bufferSizeInBytes, int mode)
+    throws IllegalArgumentException {
+        mState = STATE_UNINITIALIZED;
+
+        audioParamCheck(streamType, sampleRateInHz, channelConfig, audioFormat, mode);
+
+        audioBuffSizeCheck(bufferSizeInBytes);
+
+        // native initialization
+        int initResult = native_setup(new WeakReference<AudioTrack>(this),
+                mStreamType, mSampleRate, mChannelCount, mAudioFormat,
+                mNativeBufferSizeInBytes, mDataLoadMode);
+        if (initResult != SUCCESS) {
+            loge("Error code "+initResult+" when initializing AudioTrack.");
+            return; // with mState == STATE_UNINITIALIZED
+        }
+
+        if (mDataLoadMode == MODE_STATIC) {
+            mState = STATE_NO_STATIC_DATA;
+        } else {
+            mState = STATE_INITIALIZED;
+        }
+    }
+
+
+    // Convenience method for the constructor's parameter checks.
+    // This is where constructor IllegalArgumentException-s are thrown
+    // postconditions:
+    //    mStreamType is valid
+    //    mChannelCount is valid
+    //    mAudioFormat is valid
+    //    mSampleRate is valid
+    //    mDataLoadMode is valid
+    private void audioParamCheck(int streamType, int sampleRateInHz,
+                                 int channelConfig, int audioFormat, int mode) {
+
+        //--------------
+        // stream type
+        if( (streamType != AudioManager.STREAM_ALARM) && (streamType != AudioManager.STREAM_MUSIC)
+           && (streamType != AudioManager.STREAM_RING) && (streamType != AudioManager.STREAM_SYSTEM)
+           && (streamType != AudioManager.STREAM_VOICE_CALL)
+           && (streamType != AudioManager.STREAM_NOTIFICATION)
+           && (streamType != AudioManager.STREAM_BLUETOOTH_SCO)) {
+            throw (new IllegalArgumentException("Invalid stream type."));
+        } else {
+            mStreamType = streamType;
+        }
+
+        //--------------
+        // sample rate
+        if ( (sampleRateInHz < 4000) || (sampleRateInHz > 48000) ) {
+            throw (new IllegalArgumentException(sampleRateInHz
+                    + "Hz is not a supported sample rate."));
+        } else {
+            mSampleRate = sampleRateInHz;
+        }
+
+        //--------------
+        // channel config
+        switch (channelConfig) {
+        case AudioFormat.CHANNEL_CONFIGURATION_DEFAULT:
+        case AudioFormat.CHANNEL_CONFIGURATION_MONO:
+            mChannelCount = 1;
+            mChannelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_MONO;
+            break;
+        case AudioFormat.CHANNEL_CONFIGURATION_STEREO:
+            mChannelCount = 2;
+            mChannelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_STEREO;
+            break;
+        default:
+            mChannelCount = 0;
+            mChannelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_INVALID;
+            throw(new IllegalArgumentException("Unsupported channel configuration."));
+        }
+
+        //--------------
+        // audio format
+        switch (audioFormat) {
+        case AudioFormat.ENCODING_DEFAULT:
+            mAudioFormat = AudioFormat.ENCODING_PCM_16BIT;
+            break;
+        case AudioFormat.ENCODING_PCM_16BIT:
+        case AudioFormat.ENCODING_PCM_8BIT:
+            mAudioFormat = audioFormat;
+            break;
+        default:
+            mAudioFormat = AudioFormat.ENCODING_INVALID;
+            throw(new IllegalArgumentException("Unsupported sample encoding."
+                + " Should be ENCODING_PCM_8BIT or ENCODING_PCM_16BIT."));
+        }
+
+        //--------------
+        // audio load mode
+        if ( (mode != MODE_STREAM) && (mode != MODE_STATIC) ) {
+            throw(new IllegalArgumentException("Invalid mode."));
+        } else {
+            mDataLoadMode = mode;
+        }
+    }
+
+
+    // Convenience method for the contructor's audio buffer size check.
+    // preconditions:
+    //    mChannelCount is valid
+    //    mAudioFormat is valid
+    // postcondition:
+    //    mNativeBufferSizeInBytes is valid (multiple of frame size, positive)
+    private void audioBuffSizeCheck(int audioBufferSize) {
+        // NB: this section is only valid with PCM data.
+        //     To update when supporting compressed formats
+        int frameSizeInBytes = mChannelCount
+                * (mAudioFormat == AudioFormat.ENCODING_PCM_8BIT ? 1 : 2);
+        if ((audioBufferSize % frameSizeInBytes != 0) || (audioBufferSize < 1)) {
+            throw (new IllegalArgumentException("Invalid audio buffer size."));
+        }
+
+        mNativeBufferSizeInBytes = audioBufferSize;
+    }
+
+
+    // Convenience method for the creation of the native event handler
+    // It is called only when a non-null event listener is set.
+    // precondition:
+    //    mNativeEventHandler is null
+    private void createNativeEventHandler() {
+        Looper looper;
+        if ((looper = Looper.myLooper()) != null) {
+            mNativeEventHandler = new NativeEventHandler(this, looper);
+        } else if ((looper = Looper.getMainLooper()) != null) {
+            mNativeEventHandler = new NativeEventHandler(this, looper);
+        } else {
+            mNativeEventHandler = null;
+        }
+    }
+
+
+    /**
+     * Releases the native AudioTrack resources.
+     */
+    public void release() {
+        // even though native_release() stops the native AudioTrack, we need to stop
+        // AudioTrack subclasses too.
+        try {
+            stop();
+        } catch(IllegalStateException ise) { 
+            // don't raise an exception, we're releasing the resources.
+        }
+        native_release();
+        mState = STATE_UNINITIALIZED;
+    }
+
+    @Override
+    protected void finalize() {
+        native_finalize();
+    }
+
+    //--------------------------------------------------------------------------
+    // Getters
+    //--------------------
+    /**
+     * Returns the minimum valid volume value. Volume values set under this one will
+     * be clamped at this value.
+     * @return the minimum volume expressed as a linear attenuation.
+     */
+    static public float getMinVolume() {
+        return AudioTrack.VOLUME_MIN;
+    }
+
+    /**
+     * Returns the maximum valid volume value. Volume values set above this one will
+     * be clamped at this value.
+     * @return the maximum volume expressed as a linear attenuation.
+     */
+    static public float getMaxVolume() {
+        return AudioTrack.VOLUME_MAX;
+    }
+
+    /**
+     * Returns the configured audio data sample rate in Hz
+     */
+    public int getSampleRate() {
+        return mSampleRate;
+    }
+    
+    /**
+     * @hide
+     * Returns the current playback rate in Hz. Note that this rate may differ from one set using
+     * {@link #setPlaybackRate(int)} as the value effectively set is implementation-dependent.
+     */
+    public int getPlaybackRate() {
+        return native_get_playback_rate();
+    }
+
+    /**
+     * Returns the configured audio data format. See {@link AudioFormat#ENCODING_PCM_16BIT}
+     * and {@link AudioFormat#ENCODING_PCM_8BIT}.
+     */
+    public int getAudioFormat() {
+        return mAudioFormat;
+    }
+
+    /**
+     * Returns the type of audio stream this AudioTrack is configured for.
+     * Compare the result against {@link AudioManager#STREAM_VOICE_CALL},
+     * {@link AudioManager#STREAM_SYSTEM}, {@link AudioManager#STREAM_RING},
+     * {@link AudioManager#STREAM_MUSIC} or {@link AudioManager#STREAM_ALARM}
+     */
+    public int getStreamType() {
+        return mStreamType;
+    }
+
+    /**
+     * Returns the configured channel configuration.
+
+     * See {@link AudioFormat#CHANNEL_CONFIGURATION_MONO}
+     * and {@link AudioFormat#CHANNEL_CONFIGURATION_STEREO}.
+     */
+    public int getChannelConfiguration() {
+        return mChannelConfiguration;
+    }
+
+    /**
+     * Returns the configured number of channels.
+     */
+    public int getChannelCount() {
+        return mChannelCount;
+    }
+
+    /**
+     * Returns the state of the AudioTrack instance. This is useful after the
+     * AudioTrack instance has been created to check if it was initialized
+     * properly. This ensures that the appropriate hardware resources have been
+     * acquired.
+     */
+    public int getState() {
+        return mState;
+    }
+
+    /**
+     * Returns the playback state of the AudioTrack instance.
+     * @see #PLAYSTATE_STOPPED
+     * @see #PLAYSTATE_PAUSED
+     * @see #PLAYSTATE_PLAYING
+     */
+    public int getPlayState() {
+        return mPlayState;
+    }
+
+    /**
+     *  Returns the native frame count used by the hardware
+     */
+    protected int getNativeFrameCount() {
+        return native_get_native_frame_count();
+    }
+
+    /**
+     * @return marker position in frames
+     */
+    public int getNotificationMarkerPosition() {
+        return native_get_marker_pos();
+    }
+
+    /**
+     * @return update period in frames
+     */
+    public int getPositionNotificationPeriod() {
+        return native_get_pos_update_period();
+    }
+
+    /**
+     * @return playback head position in frames
+     */
+    public int getPlaybackHeadPosition() {
+        return native_get_position();
+    }
+
+    /**
+     *  Returns the hardware output sample rate
+     */
+    static public int getNativeOutputSampleRate(int streamType) {
+        return native_get_output_sample_rate(streamType);
+    }
+    
+    /**
+     * {@hide}
+     * Returns the minimum buffer size required for the successful creation of an AudioTrack
+     * object to be created in the {@link #MODE_STREAM} mode.
+     * @param sampleRateInHz the sample rate expressed in Hertz.
+     * @param channelConfig describes the configuration of the audio channels. 
+     *   See {@link AudioFormat#CHANNEL_CONFIGURATION_MONO} and
+     *   {@link AudioFormat#CHANNEL_CONFIGURATION_STEREO}
+     * @param audioFormat the format in which the audio data is represented. 
+     *   See {@link AudioFormat#ENCODING_PCM_16BIT} and 
+     *   {@link AudioFormat#ENCODING_PCM_8BIT}
+     * @return {@link #ERROR_BAD_VALUE} if an invalid parameter was passed,
+     *   or {@link #ERROR} if the implementation was unable to query the hardware for its output 
+     *     properties, 
+     *   or the minimum buffer size expressed  in number of bytes.
+     */
+    static public int getMinBufferSize(int sampleRateInHz, int channelConfig, int audioFormat) {
+        int channelCount = 0;
+        switch(channelConfig) {
+        case AudioFormat.CHANNEL_CONFIGURATION_MONO:
+            channelCount = 1;
+            break;
+        case AudioFormat.CHANNEL_CONFIGURATION_STEREO:
+            channelCount = 2;
+            break;
+        default:
+            loge("getMinBufferSize(): Invalid channel configuration.");
+            return AudioTrack.ERROR_BAD_VALUE;
+        }
+        
+        if ((audioFormat != AudioFormat.ENCODING_PCM_16BIT) 
+            && (audioFormat != AudioFormat.ENCODING_PCM_8BIT)) {
+            loge("getMinBufferSize(): Invalid audio format.");
+            return AudioTrack.ERROR_BAD_VALUE;
+        }
+        
+        if ( (sampleRateInHz < 4000) || (sampleRateInHz > 48000) ) {
+            loge("getMinBufferSize(): " + sampleRateInHz +"Hz is not a supported sample rate.");
+            return AudioTrack.ERROR_BAD_VALUE;
+        }
+        
+        int size = native_get_min_buff_size(sampleRateInHz, channelCount, audioFormat);
+        if ((size == -1) || (size == 0)) {
+            loge("getMinBufferSize(): error querying hardware");
+            return AudioTrack.ERROR;
+        }
+        else {
+            return size;
+        }
+    }
+
+
+    //--------------------------------------------------------------------------
+    // Initialization / configuration
+    //--------------------
+    /**
+     * Sets the listener the AudioTrack notifies when a previously set marker is reached.
+     * @param listener
+     */
+    public void setMarkerReachedListener(OnMarkerReachedListener listener) {
+        synchronized (mMarkerListenerLock) {
+            mMarkerListener = listener;
+        }
+        if ((listener != null) && (mNativeEventHandler == null)) {
+            createNativeEventHandler();
+        }
+    }
+
+
+    /**
+     * Sets the listener the AudioTrack notifies periodically during playback.
+     * @param listener
+     */
+    public void setPeriodicNotificationListener(OnPeriodicNotificationListener listener) {
+        synchronized (mPeriodicListenerLock) {
+            mPeriodicListener = listener;
+        }
+        if ((listener != null) && (mNativeEventHandler == null)) {
+            createNativeEventHandler();
+        }
+    }
+
+
+     /**
+     * Sets the specified left/right output volume values on the AudioTrack. Values are clamped
+     * to the ({@link #getMinVolume()}, {@link #getMaxVolume()}) interval if outside this range.
+     * @param leftVolume output attenuation for the left channel. A value of 0.0f is silence,
+     *      a value of 1.0f is no attenuation.
+     * @param rightVolume output attenuation for the right channel
+     * @return error code or success, see {@link #SUCCESS},
+     *    {@link #ERROR_INVALID_OPERATION}
+     */
+    public int setStereoVolume(float leftVolume, float rightVolume) {
+        if (mState != STATE_INITIALIZED) {
+            return ERROR_INVALID_OPERATION;
+        }
+
+        // clamp the volumes
+        if (leftVolume < getMinVolume()) {
+            leftVolume = getMinVolume();
+        }
+        if (leftVolume > getMaxVolume()) {
+            leftVolume = getMaxVolume();
+        }
+        if (rightVolume < getMinVolume()) {
+            rightVolume = getMinVolume();
+        }
+        if (rightVolume > getMaxVolume()) {
+            rightVolume = getMaxVolume();
+        }
+
+        native_setVolume(leftVolume, rightVolume);
+
+        return SUCCESS;
+    }
+
+
+    /**
+     * Sets the playback sample rate for this track. This sets the sampling rate at which
+     * the audio data will be consumed and played back, not the original sampling rate of the
+     * content. Setting it to half the sample rate of the content will cause the playback to
+     * last twice as long, but will also result result in a negative pitch shift.
+     * The current implementation supports a maximum sample rate of twice the hardware output
+     * sample rate (see {@link #getNativeOutputSampleRate(int)}). Use {@link #getSampleRate()} to
+     * check the rate actually used in hardware after potential clamping.
+     * @param sampleRateInHz
+     * @return error code or success, see {@link #SUCCESS}, {@link #ERROR_BAD_VALUE},
+     *    {@link #ERROR_INVALID_OPERATION}
+     */
+    public int setPlaybackRate(int sampleRateInHz) {
+        if (mState != STATE_INITIALIZED) {
+            return ERROR_INVALID_OPERATION;
+        }
+        if (sampleRateInHz <= 0) {
+            return ERROR_BAD_VALUE;
+        }
+        native_set_playback_rate(sampleRateInHz);
+        return SUCCESS;
+    }
+
+
+    /**
+     *
+     * @param markerInFrames marker in frames
+     * @return error code or success, see {@link #SUCCESS}, {@link #ERROR_BAD_VALUE},
+     *  {@link #ERROR_INVALID_OPERATION}
+     */
+    public int setNotificationMarkerPosition(int markerInFrames) {
+        if (mState != STATE_INITIALIZED) {
+            return ERROR_INVALID_OPERATION;
+        }
+        return native_set_marker_pos(markerInFrames);
+    }
+
+
+    /**
+     * @param periodInFrames update period in frames
+     * @return error code or success, see {@link #SUCCESS}, {@link #ERROR_INVALID_OPERATION}
+     */
+    public int setPositionNotificationPeriod(int periodInFrames) {
+        if (mState != STATE_INITIALIZED) {
+            return ERROR_INVALID_OPERATION;
+        }
+        return native_set_pos_update_period(periodInFrames);
+    }
+
+
+    /**
+     * Sets the playback head position. The track must be stopped for the position to be changed.
+     * @param positionInFrames playback head position in frames
+     * @return error code or success, see {@link #SUCCESS}, {@link #ERROR_BAD_VALUE},
+     *    {@link #ERROR_INVALID_OPERATION}
+     */
+    public int setPlaybackHeadPosition(int positionInFrames) {
+        synchronized(mPlayStateLock) {
+            if ((mPlayState == PLAYSTATE_STOPPED) || (mPlayState == PLAYSTATE_PAUSED)) {
+                return native_set_position(positionInFrames);
+            } else {
+                return ERROR_INVALID_OPERATION;
+            }
+        }
+    }
+
+    /**
+     * Sets the loop points and the loop count. The loop can be infinite.
+     * @param startInFrames loop start marker in frames
+     * @param endInFrames loop end marker in frames
+     * @param loopCount the number of times the loop is looped.
+     *    A value of -1 means infinite looping.
+     * @return error code or success, see {@link #SUCCESS}, {@link #ERROR_BAD_VALUE},
+     *    {@link #ERROR_INVALID_OPERATION}
+     */
+    public int setLoopPoints(int startInFrames, int endInFrames, int loopCount) {
+        if (mDataLoadMode == MODE_STREAM) {
+            return ERROR_INVALID_OPERATION;
+        }
+        return native_set_loop(startInFrames, endInFrames, loopCount);
+    }
+
+    /**
+     * Sets the initialization state of the instance. To be used in an AudioTrack subclass
+     * constructor to set a subclass-specific post-initialization state.
+     * @param state the state of the AudioTrack instance
+     */
+    protected void setState(int state) {
+        mState = state;
+    }
+
+
+    //---------------------------------------------------------
+    // Transport control methods
+    //--------------------
+    /**
+     * Starts playing an AudioTrack.
+     * @throws IllegalStateException
+     */
+    public void play()
+    throws IllegalStateException {
+        if (mState != STATE_INITIALIZED) {
+            throw(new IllegalStateException("play() called on uninitialized AudioTrack."));
+        }
+
+        synchronized(mPlayStateLock) {
+            native_start();
+            mPlayState = PLAYSTATE_PLAYING;
+        }
+    }
+
+    /**
+     * Stops playing the audio data.
+     * @throws IllegalStateException
+     */
+    public void stop()
+    throws IllegalStateException {
+        if (mState != STATE_INITIALIZED) {
+            throw(new IllegalStateException("stop() called on uninitialized AudioTrack."));
+        }
+
+        // stop playing
+        synchronized(mPlayStateLock) {
+            native_stop();
+            mPlayState = PLAYSTATE_STOPPED;
+        }
+    }
+
+    /**
+     * Pauses the playback of the audio data.
+     * @throws IllegalStateException
+     */
+    public void pause()
+    throws IllegalStateException {
+        if (mState != STATE_INITIALIZED) {
+            throw(new IllegalStateException("pause() called on uninitialized AudioTrack."));
+        }
+        //logd("pause()");
+
+        // pause playback
+        synchronized(mPlayStateLock) {
+            native_pause();
+            mPlayState = PLAYSTATE_PAUSED;
+        }
+    }
+
+
+    //---------------------------------------------------------
+    // Audio data supply
+    //--------------------
+
+    /**
+     * Flushes the audio data currently queued for playback.
+     */
+
+    public void flush() {
+        if (mState == STATE_INITIALIZED) {
+            // flush the data in native layer
+            native_flush();
+        }
+
+    }
+
+    /**
+     * Writes the audio data to the audio hardware for playback.
+     * @param audioData the array that holds the data to play.
+     * @param offsetInBytes the offset in audioData where the data to play starts.
+     * @param sizeInBytes the number of bytes to read in audioData after the offset.
+     * @return the number of bytes that were written or {@link #ERROR_INVALID_OPERATION}
+     *    if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if
+     *    the parameters don't resolve to valid data and indexes.
+     */
+
+    public int write(byte[] audioData,int offsetInBytes, int sizeInBytes) {
+        if ((mDataLoadMode == MODE_STATIC)
+                && (mState == STATE_NO_STATIC_DATA)
+                && (sizeInBytes > 0)) {
+            mState = STATE_INITIALIZED;
+        }
+
+        if (mState != STATE_INITIALIZED) {
+            return ERROR_INVALID_OPERATION;
+        }
+
+        if ( (audioData == null) || (offsetInBytes < 0 ) || (sizeInBytes < 0) 
+                || (offsetInBytes + sizeInBytes > audioData.length)) {
+            return ERROR_BAD_VALUE;
+        }
+
+        return native_write_byte(audioData, offsetInBytes, sizeInBytes, mAudioFormat);
+    }
+
+
+    /**
+     * Writes the audio data to the audio hardware for playback.
+     * @param audioData the array that holds the data to play.
+     * @param offsetInShorts the offset in audioData where the data to play starts.
+     * @param sizeInShorts the number of bytes to read in audioData after the offset.
+     * @return the number of shorts that were written or {@link #ERROR_INVALID_OPERATION}
+      *    if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if
+      *    the parameters don't resolve to valid data and indexes.
+     */
+
+    public int write(short[] audioData, int offsetInShorts, int sizeInShorts) {
+        if ((mDataLoadMode == MODE_STATIC)
+                && (mState == STATE_NO_STATIC_DATA)
+                && (sizeInShorts > 0)) {
+            mState = STATE_INITIALIZED;
+        }
+        
+        if (mState != STATE_INITIALIZED) {
+            return ERROR_INVALID_OPERATION;
+        }
+
+        if ( (audioData == null) || (offsetInShorts < 0 ) || (sizeInShorts < 0) 
+                || (offsetInShorts + sizeInShorts > audioData.length)) {
+            return ERROR_BAD_VALUE;
+        }
+
+        return native_write_short(audioData, offsetInShorts, sizeInShorts, mAudioFormat);
+    }
+
+
+    /**
+     * Notifies the native resource to reuse the audio data already loaded in the native
+     * layer. This call is only valid with AudioTrack instances that don't use the streaming
+     * model.
+     * @return error code or success, see {@link #SUCCESS}, {@link #ERROR_BAD_VALUE},
+     *  {@link #ERROR_INVALID_OPERATION}
+     */
+    public int reloadStaticData() {
+        if (mDataLoadMode == MODE_STREAM) {
+            return ERROR_INVALID_OPERATION;
+        }
+        return native_reload_static();
+    }
+
+
+    //---------------------------------------------------------
+    // Interface definitions
+    //--------------------
+    /**
+     * Interface definition for a callback to be invoked when an AudioTrack has
+     * reached a notification marker set by setNotificationMarkerPosition().
+     */
+    public interface OnMarkerReachedListener  {
+        /**
+         * Called on the listener to notify it that the previously set marker has been reached
+         * by the playback head.
+         */
+        void onMarkerReached(AudioTrack track);
+    }
+
+
+    /**
+     * Interface definition for a callback to be invoked for each periodic AudioTrack
+     * update during playback. The update interval is set by setPositionNotificationPeriod().
+     */
+    public interface OnPeriodicNotificationListener  {
+        /**
+         * Called on the listener to periodically notify it that the playback head has reached
+         * a multiple of the notification period.
+         */
+        void onPeriodicNotification(AudioTrack track);
+    }
+
+
+    //---------------------------------------------------------
+    // Inner classes
+    //--------------------
+    /**
+     * Helper class to handle the forwarding of native events to the appropriate listeners
+     */
+    private class NativeEventHandler extends Handler
+    {
+        private AudioTrack mAudioTrack;
+
+        public NativeEventHandler(AudioTrack mp, Looper looper) {
+            super(looper);
+            mAudioTrack = mp;
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            if (mAudioTrack == null) {
+                return;
+            }
+            switch(msg.what) {
+            case NATIVE_EVENT_MARKER:
+                synchronized (mMarkerListenerLock) {
+                    if (mAudioTrack.mMarkerListener != null) {
+                        mAudioTrack.mMarkerListener.onMarkerReached(mAudioTrack);
+                    }
+                }
+                break;
+            case NATIVE_EVENT_NEW_POS:
+                synchronized (mPeriodicListenerLock) {
+                    if (mAudioTrack.mPeriodicListener != null) {
+                        mAudioTrack.mPeriodicListener.onPeriodicNotification(mAudioTrack);
+                    }
+                }
+                break;
+            default:
+                Log.e(TAG, "[ android.media.AudioTrack.NativeEventHandler ] " +
+                        "Unknown event type: " + msg.what);
+                break;
+            }
+        }
+    }
+
+
+    //---------------------------------------------------------
+    // Java methods called from the native side
+    //--------------------
+    @SuppressWarnings("unused")
+    private static void postEventFromNative(Object audiotrack_ref,
+            int what, int arg1, int arg2, Object obj) {
+        //logd("Event posted from the native side: event="+ what + " args="+ arg1+" "+arg2);
+        AudioTrack track = (AudioTrack)((WeakReference)audiotrack_ref).get();
+        if (track == null) {
+            return;
+        }
+
+        if (track.mNativeEventHandler != null) {
+            Message m = track.mNativeEventHandler.obtainMessage(what, arg1, arg2, obj);
+            track.mNativeEventHandler.sendMessage(m);
+        }
+
+    }
+
+
+    //---------------------------------------------------------
+    // Native methods called from the Java side
+    //--------------------
+
+    private native final int native_setup(Object audiotrack_this,
+            int streamType, int sampleRate, int nbChannels, int audioFormat,
+            int buffSizeInBytes, int mode);
+
+    private native final void native_finalize();
+
+    private native final void native_release();
+
+    private native final void native_start();
+
+    private native final void native_stop();
+
+    private native final void native_pause();
+
+    private native final void native_flush();
+
+    private native final int native_write_byte(byte[] audioData,
+                                               int offsetInBytes, int sizeInBytes, int format);
+
+    private native final int native_write_short(short[] audioData,
+                                                int offsetInShorts, int sizeInShorts, int format);
+
+    private native final int native_reload_static();
+
+    private native final int native_get_native_frame_count();
+
+    private native final void native_setVolume(float leftVolume, float rightVolume);
+
+    private native final void native_set_playback_rate(int sampleRateInHz);
+    private native final int  native_get_playback_rate();
+
+    private native final int native_set_marker_pos(int marker);
+    private native final int native_get_marker_pos();
+
+    private native final int native_set_pos_update_period(int updatePeriod);
+    private native final int native_get_pos_update_period();
+
+    private native final int native_set_position(int position);
+    private native final int native_get_position();
+
+    private native final int native_set_loop(int start, int end, int loopCount);
+
+    static private native final int native_get_output_sample_rate(int streamType);
+    static private native final int native_get_min_buff_size(
+            int sampleRateInHz, int channelConfig, int audioFormat);
+
+
+    //---------------------------------------------------------
+    // Utility methods
+    //------------------
+
+    private static void logd(String msg) {
+        Log.d(TAG, "[ android.media.AudioTrack ] " + msg);
+    }
+
+    private static void loge(String msg) {
+        Log.e(TAG, "[ android.media.AudioTrack ] " + msg);
+    }
+
+}
diff --git a/media/java/android/media/FaceDetector.java b/media/java/android/media/FaceDetector.java
new file mode 100644
index 0000000..3b41cf8
--- /dev/null
+++ b/media/java/android/media/FaceDetector.java
@@ -0,0 +1,201 @@
+/*
+ * 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.
+ */
+
+package android.media;
+
+import android.graphics.Bitmap;
+import android.graphics.PointF;
+import android.util.Log;
+
+import java.lang.IllegalArgumentException;
+
+/**
+ * Identifies the faces of people in a 
+ * {@link android.graphics.Bitmap} graphic object.
+ */
+public class FaceDetector {
+
+    /**
+     * A Face contains all the information identifying the location
+     * of a face in a bitmap.
+     */
+    public class Face {
+        /** The minimum confidence factor of good face recognition */
+        public static final float CONFIDENCE_THRESHOLD = 0.4f;
+        /** The x-axis Euler angle of a face. */
+        public static final int EULER_X = 0;
+        /** The y-axis Euler angle of a face. */
+        public static final int EULER_Y = 1;
+        /** The z-axis Euler angle of a face. */
+        public static final int EULER_Z = 2;
+
+        /** 
+         * Returns a confidence factor between 0 and 1. This indicates how
+         * certain what has been found is actually a face. A confidence
+         * factor above 0.3 is usually good enough.
+         */
+        public float confidence() {
+            return mConfidence;
+        }
+        /**
+         * Sets the position of the mid-point between the eyes.
+         * @param point the PointF coordinates (float values) of the 
+         *              face's mid-point
+         */
+        public void getMidPoint(PointF point) {
+            // don't return a PointF to avoid allocations
+            point.set(mMidPointX, mMidPointY);
+        }
+        /**
+         * Returns the distance between the eyes.
+         */
+        public float eyesDistance() {
+            return mEyesDist;
+        }
+        /**
+         * Returns the face's pose. That is, the rotations around either 
+         * the X, Y or Z axis (the positions in 3-dimensional Euclidean space).
+         * 
+         * @param euler the Euler axis to retrieve an angle from 
+         *              (<var>EULER_X</var>, <var>EULER_Y</var> or 
+         *              <var>EULER_Z</var>)
+         * @return the Euler angle of the of the face, for the given axis
+         */
+        public float pose(int euler) {
+            // don't use an array to avoid allocations
+            if (euler == EULER_X)
+                return mPoseEulerX;
+            else if (euler == EULER_Y)
+                return mPoseEulerY;
+            else if (euler == EULER_Z)
+                return mPoseEulerZ;
+           throw new IllegalArgumentException();
+        }
+
+        // private ctor, user not supposed to build this object
+        private Face() {
+        }
+        private float   mConfidence;
+        private float   mMidPointX;
+        private float   mMidPointY;
+        private float   mEyesDist;
+        private float   mPoseEulerX;
+        private float   mPoseEulerY;
+        private float   mPoseEulerZ;
+    }
+
+
+    /**
+     * Creates a FaceDetector, configured with the size of the images to
+     * be analysed and the maximum number of faces that can be detected.
+     * These parameters cannot be changed once the object is constructed.
+     * 
+     * @param width  the width of the image
+     * @param height the height of the image
+     * @param maxFaces the maximum number of faces to identify
+     *
+     */
+    public FaceDetector(int width, int height, int maxFaces)
+    {
+        if (!sInitialized) {
+            return;
+        }
+        fft_initialize(width, height, maxFaces);
+        mWidth = width;
+        mHeight = height;
+        mMaxFaces = maxFaces;
+        mBWBuffer = new byte[width * height];
+    }
+
+    /**
+     * Finds all the faces found in a given {@link android.graphics.Bitmap}. 
+     * The supplied array is populated with {@link FaceDetector.Face}s for each
+     * face found. The bitmap must be in 565 format (for now).
+     * 
+     * @param bitmap the {@link android.graphics.Bitmap} graphic to be analyzed
+     * @param faces  an array in which to place all found 
+     *               {@link FaceDetector.Face}s. The array must be sized equal
+     *               to the <var>maxFaces</var> value set at initialization
+     * @return the number of faces found
+     * @throws IllegalArgumentException if the Bitmap dimensions don't match
+     *               the dimensions defined at initialization or the given array 
+     *               is not sized equal to the <var>maxFaces</var> value defined
+     *               at initialization
+     */
+    public int findFaces(Bitmap bitmap, Face[] faces)
+    {
+        if (!sInitialized) {
+            return 0;
+        }
+        if (bitmap.getWidth() != mWidth || bitmap.getHeight() != mHeight) {
+            throw new IllegalArgumentException(
+                    "bitmap size doesn't match initialization");
+        }
+        if (faces.length < mMaxFaces) {
+            throw new IllegalArgumentException(
+                    "faces[] smaller than maxFaces");
+        }
+        
+        int numFaces = fft_detect(bitmap);
+        if (numFaces >= mMaxFaces)
+            numFaces = mMaxFaces;
+        for (int i=0 ; i<numFaces ; i++) {
+            if (faces[i] == null)
+                faces[i] = new Face();
+            fft_get_face(faces[i], i);
+        }
+        return numFaces;
+    }
+
+
+    /* no user serviceable parts here ... */
+    @Override
+    protected void finalize() throws Throwable {
+        fft_destroy();
+    }
+
+    /*
+     * We use a class initializer to allow the native code to cache some
+     * field offsets.
+     */
+    private static boolean sInitialized;
+    native private static void nativeClassInit();
+
+    static {
+        sInitialized = false;
+        try {
+            System.loadLibrary("FFTEm");
+            nativeClassInit();
+            sInitialized = true;
+        } catch (UnsatisfiedLinkError e) {
+            Log.d("FFTEm", "face detection library not found!");
+        }
+    }
+
+    native private int  fft_initialize(int width, int height, int maxFaces);
+    native private int  fft_detect(Bitmap bitmap);
+    native private void fft_get_face(Face face, int i);
+    native private void fft_destroy();
+
+    private int     mFD;
+    private int     mSDK;
+    private int     mDCR;
+    private int     mWidth;
+    private int     mHeight;
+    private int     mMaxFaces;    
+    private byte    mBWBuffer[];
+}
+
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
new file mode 100644
index 0000000..f5e242d
--- /dev/null
+++ b/media/java/android/media/IAudioService.aidl
@@ -0,0 +1,74 @@
+/*
+ * 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.
+ */
+
+package android.media;
+
+/**
+ * {@hide}
+ */
+interface IAudioService {
+    
+    void adjustVolume(int direction, int flags);
+
+    void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags);
+    
+    void adjustStreamVolume(int streamType, int direction, int flags);
+    
+    void setStreamVolume(int streamType, int index, int flags);
+    
+   	void setStreamSolo(int streamType, boolean state, IBinder cb);
+   	
+   	void setStreamMute(int streamType, boolean state, IBinder cb);
+    
+    int getStreamVolume(int streamType);
+    
+    int getStreamMaxVolume(int streamType);
+    
+    void setRingerMode(int ringerMode);
+    
+    int getRingerMode();
+
+    void setVibrateSetting(int vibrateType, int vibrateSetting);
+    
+    int getVibrateSetting(int vibrateType);
+    
+    boolean shouldVibrate(int vibrateType);
+    
+    void setMicrophoneMute(boolean on);
+
+    boolean isMicrophoneMute();
+
+    void setMode(int mode);
+
+    int getMode();
+
+    void setRouting(int mode, int routes, int mask);
+
+    int getRouting(int mode);
+
+    boolean isMusicActive();
+
+    void setParameter(String key, String value);
+
+    oneway void playSoundEffect(int effectType);
+  
+    oneway void playSoundEffectVolume(int effectType, float volume);
+
+    boolean loadSoundEffects();
+  
+    oneway void unloadSoundEffects();
+
+}
diff --git a/media/java/android/media/IMediaScannerListener.aidl b/media/java/android/media/IMediaScannerListener.aidl
new file mode 100644
index 0000000..4e85563
--- /dev/null
+++ b/media/java/android/media/IMediaScannerListener.aidl
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+package android.media;
+
+import android.net.Uri;
+
+/**
+ * {@hide}
+ */
+oneway interface IMediaScannerListener
+{
+    /**
+     * Called when a IMediaScannerService.scanFile() call has completed.
+     * @param path the path to the file that has been scanned.
+     * @param uri the Uri for the file if the scanning operation succeeded 
+     * and the file was added to the media database, or null if scanning failed. 
+     */
+    void scanCompleted(String path, in Uri uri);
+}
diff --git a/media/java/android/media/IMediaScannerService.aidl b/media/java/android/media/IMediaScannerService.aidl
new file mode 100644
index 0000000..c531646
--- /dev/null
+++ b/media/java/android/media/IMediaScannerService.aidl
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+package android.media;
+
+import android.media.IMediaScannerListener;
+
+/**
+ * {@hide}
+ */
+interface IMediaScannerService
+{
+    /**
+     * Requests the media scanner to scan a file.
+     * @param path the path to the file to be scanned.
+     * @param mimeType  an optional mimeType for the file.
+     * If mimeType is null, then the mimeType will be inferred from the file extension.
+     * @param listener an optional IMediaScannerListener. 
+     * If specified, the caller will be notified when scanning is complete via the listener.
+     */
+    void requestScanFile(String path, String mimeType, in IMediaScannerListener listener);
+
+    /**
+     * Older API, left in for backward compatibility.
+     * Requests the media scanner to scan a file.
+     * @param path the path to the file to be scanned.
+     * @param mimeType  an optional mimeType for the file.
+     * If mimeType is null, then the mimeType will be inferred from the file extension.
+     */
+    void scanFile(String path, String mimeType);
+}
diff --git a/media/java/android/media/JetPlayer.java b/media/java/android/media/JetPlayer.java
new file mode 100644
index 0000000..9de0eec
--- /dev/null
+++ b/media/java/android/media/JetPlayer.java
@@ -0,0 +1,423 @@
+/*
+ * 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.
+ */
+
+package android.media;
+
+
+import java.io.FileDescriptor;
+import java.lang.ref.WeakReference;
+import java.lang.CloneNotSupportedException;
+
+import android.content.res.AssetFileDescriptor;
+import android.os.Looper;
+import android.os.Handler;
+import android.os.Message;
+import android.util.AndroidRuntimeException;
+import android.util.Log;
+
+/**
+ * JetPlayer provides access to JET content playback and control.
+ * <p>
+ * Use <code>JetPlayer.getJetPlayer()</code> to get an instance of this class.
+ * 
+ */
+public class JetPlayer
+{    
+    //--------------------------------------------
+    // Constants
+    //------------------------
+    /**
+     * The maximum number of simultaneous tracks. Use __link #getMaxTracks()} to
+     * access this value.
+     */
+    private static int MAXTRACKS = 32;
+        
+    // to keep in sync with the JetPlayer class constants
+    // defined in frameworks/base/include/media/JetPlayer.h
+    private static final int JET_EVENT                   = 1;
+    private static final int JET_USERID_UPDATE           = 2;
+    private static final int JET_NUMQUEUEDSEGMENT_UPDATE = 3;
+    private static final int JET_PAUSE_UPDATE            = 4;
+    
+    // to keep in sync with external/sonivox/arm-wt-22k/lib_src/jet_data.h
+    // Encoding of event information on 32 bits
+    private static final int JET_EVENT_VAL_MASK    = 0x0000007f; // mask for value
+    private static final int JET_EVENT_CTRL_MASK   = 0x00003f80; // mask for controller
+    private static final int JET_EVENT_CHAN_MASK   = 0x0003c000; // mask for channel
+    private static final int JET_EVENT_TRACK_MASK  = 0x00fc0000; // mask for track number
+    private static final int JET_EVENT_SEG_MASK    = 0xff000000; // mask for segment ID
+    private static final int JET_EVENT_CTRL_SHIFT  = 7;  // shift to get controller number to bit 0
+    private static final int JET_EVENT_CHAN_SHIFT  = 14; // shift to get MIDI channel to bit 0
+    private static final int JET_EVENT_TRACK_SHIFT = 18; // shift to get track ID to bit 0
+    private static final int JET_EVENT_SEG_SHIFT   = 24; // shift to get segment ID to bit 0
+
+    
+    //--------------------------------------------
+    // Member variables
+    //------------------------
+    private EventHandler            mNativeEventHandler = null;
+    
+    /**
+     * Lock to protect status listener updates against status change notifications
+     */
+    private final Object mStatusListenerLock = new Object();
+    
+    /**
+     * Lock to protect the event listener updates against event notifications
+     */
+    private final Object mEventListenerLock = new Object();
+    
+    private JetStatusUpdateListener mJetStatusUpdateListener = null;
+    
+    private JetEventListener mJetEventListener = null;
+    
+    private static JetPlayer singletonRef;
+    
+    
+    //--------------------------------
+    // Used exclusively by native code
+    //--------------------
+    /** 
+     * Accessed by native methods: provides access to C++ JetPlayer object 
+     */
+    @SuppressWarnings("unused")
+    private int mNativePlayerInJavaObj;
+
+    
+    //--------------------------------------------
+    // Constructor, finalize
+    //------------------------
+    public static JetPlayer getJetPlayer() {
+        if (singletonRef == null)
+            singletonRef = new JetPlayer();
+        return singletonRef;
+    }
+    
+    
+    public Object clone() throws CloneNotSupportedException {
+        // JetPlayer is a singleton class,
+        // so you can't clone a JetPlayer instance
+        throw new CloneNotSupportedException();    
+    }
+    
+
+    private JetPlayer() {
+                
+        native_setup(new WeakReference<JetPlayer>(this),
+                JetPlayer.getMaxTracks(), 
+                1200); //TODO parametrize this (?)
+    }
+    
+    
+    protected void finalize() { 
+        native_finalize(); 
+    }
+    
+    
+    public void release() {
+        native_release();
+    }
+    
+    
+    private void createNativeEventHandler() {
+        Looper looper;
+        if ((looper = Looper.myLooper()) != null) {
+            mNativeEventHandler = new EventHandler(this, looper);
+        } else if ((looper = Looper.getMainLooper()) != null) {
+            mNativeEventHandler = new EventHandler(this, looper);
+        } else {
+            mNativeEventHandler = null;
+        }
+    }
+    
+    
+    //--------------------------------------------
+    // Getters
+    //------------------------
+    /**
+     * Returns the maximum number of simultaneous MIDI tracks supported by the Jet player
+     */
+    public static int getMaxTracks() {
+        return JetPlayer.MAXTRACKS;
+    }
+    
+    
+    //--------------------------------------------
+    // Jet functionality
+    //------------------------
+    public boolean loadJetFile(String path) {
+        return native_loadJetFromFile(path);
+    }
+    
+    
+    public boolean loadJetFile(AssetFileDescriptor afd) {
+        long len = afd.getLength();
+        if (len < 0) {
+            throw new AndroidRuntimeException("no length for fd");
+        }
+        return native_loadJetFromFileD(
+                afd.getFileDescriptor(), afd.getStartOffset(), len);
+    }
+    
+    
+    public boolean closeJetFile() {
+        return native_closeJetFile();
+    }
+    
+    
+    public boolean play() {
+        return native_playJet();
+    }
+    
+    
+    public boolean pause() {
+        return native_pauseJet();
+    }
+    
+    
+    public boolean queueJetSegment(int segmentNum, int libNum, int repeatCount,
+        int transpose, int muteFlags, byte userID) {
+        return native_queueJetSegment(segmentNum, libNum, repeatCount, 
+                transpose, muteFlags, userID);
+    }
+    
+    
+    public boolean queueJetSegmentMuteArray(int segmentNum, int libNum, int repeatCount,
+            int transpose, boolean[] muteArray, byte userID) {
+        if (muteArray.length != JetPlayer.getMaxTracks()) {
+            return false;
+        }
+        return native_queueJetSegmentMuteArray(segmentNum, libNum, repeatCount,
+                transpose, muteArray, userID);
+    }
+    
+    
+    public boolean setMuteFlags(int muteFlags, boolean sync) {
+        return native_setMuteFlags(muteFlags, sync);
+    }
+    
+    
+    public boolean setMuteArray(boolean[] muteArray, boolean sync) {
+        if(muteArray.length != JetPlayer.getMaxTracks())
+            return false;
+        return native_setMuteArray(muteArray, sync);
+    }
+    
+    
+    public boolean setMuteFlag(int trackId, boolean muteFlag, boolean sync) {
+        return native_setMuteFlag(trackId, muteFlag, sync);
+    }
+    
+    
+    public boolean triggerClip(int clipId) {
+        return native_triggerClip(clipId);
+    }
+    
+    
+    public boolean clearQueue() {
+        return native_clearQueue();
+    }
+    
+     
+    //---------------------------------------------------------
+    // Internal class to handle events posted from native code
+    //------------------------
+    private class EventHandler extends Handler
+    {
+        private JetPlayer mJet;
+
+        public EventHandler(JetPlayer jet, Looper looper) {
+            super(looper);
+            mJet = jet;
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch(msg.what) {
+            case JET_EVENT:
+                synchronized (mEventListenerLock) {
+                    if (mJetEventListener != null) {
+                        // call the appropriate listener after decoding the event parameters
+                        // encoded in msg.arg1
+                        mJetEventListener.onJetEvent(
+                            mJet,
+                            (short)((msg.arg1 & JET_EVENT_SEG_MASK)   >> JET_EVENT_SEG_SHIFT),
+                            (byte) ((msg.arg1 & JET_EVENT_TRACK_MASK) >> JET_EVENT_TRACK_SHIFT),
+                            // JETCreator channel numbers start at 1, but the index starts at 0
+                            // in the .jet files
+                            (byte)(((msg.arg1 & JET_EVENT_CHAN_MASK)  >> JET_EVENT_CHAN_SHIFT) + 1),
+                            (byte) ((msg.arg1 & JET_EVENT_CTRL_MASK)  >> JET_EVENT_CTRL_SHIFT),
+                            (byte)  (msg.arg1 & JET_EVENT_VAL_MASK) );
+                    }
+                }
+                return;
+            case JET_USERID_UPDATE:
+                synchronized (mStatusListenerLock) {
+                    if (mJetStatusUpdateListener != null) {
+                        mJetStatusUpdateListener.onJetUserIdUpdate(mJet, msg.arg1, msg.arg2);
+                    }
+                }
+                return;
+            case JET_NUMQUEUEDSEGMENT_UPDATE:
+                synchronized (mStatusListenerLock) {
+                    if (mJetStatusUpdateListener != null) {
+                        mJetStatusUpdateListener.onJetNumQueuedSegmentUpdate(mJet, msg.arg1);
+                    }
+                }
+                return;
+            case JET_PAUSE_UPDATE:
+                synchronized (mStatusListenerLock) {
+                    if (mJetStatusUpdateListener != null)
+                        mJetStatusUpdateListener.onJetPauseUpdate(mJet, msg.arg1);
+                }
+                return;
+
+            default:
+                loge("Unknown message type " + msg.what);
+                return;
+            }
+        }
+    }
+    
+    
+    //--------------------------------------------
+    // Jet status update listener
+    //------------------------
+    public void setStatusUpdateListener(JetStatusUpdateListener listener) {
+        synchronized(mStatusListenerLock) {
+            mJetStatusUpdateListener = listener;
+        }
+        
+        if ((listener != null) && (mNativeEventHandler == null)) {
+            createNativeEventHandler();
+        }
+    }
+    
+    /**
+     * Handles the notification when the JET status is updated.
+     */
+    public interface JetStatusUpdateListener {
+        /**
+         * Callback for when JET's currently playing segment userID is updated.
+         * 
+         * @param player the JET player the status update is coming from
+         * @param userId the ID of the currently playing segment
+         * @param repeatCount the repetition count for the segment (0 means it plays once)
+         */
+        void onJetUserIdUpdate(JetPlayer player, int userId, int repeatCount);
+        
+        /**
+         * Callback for when JET's number of queued segments is updated.
+         * 
+         * @param player the JET player the status update is coming from
+         * @param nbSegments the number of segments in the JET queue
+         */
+        void onJetNumQueuedSegmentUpdate(JetPlayer player, int nbSegments);
+        
+        /**
+         * Callback for when JET pause state is updated.
+         * 
+         * @param player the JET player the status update is coming from
+         * @param paused indicates whether JET is paused or not
+         */
+        void onJetPauseUpdate(JetPlayer player, int paused);
+    }
+    
+    
+    //--------------------------------------------
+    // Jet event listener
+    //------------------------
+    public void setEventListener(JetEventListener listener) {
+        synchronized(mEventListenerLock) {
+            mJetEventListener = listener;
+        }
+        
+        if ((listener != null) && (mNativeEventHandler == null)) {
+            createNativeEventHandler();
+        }
+    }
+    
+    /**
+     * Handles the notification when the JET engine generates an event.
+     */
+    public interface JetEventListener {
+        /**
+         * Callback for when the JET engine generates a new event.
+         * 
+         * @param player the JET player the event is coming from
+         * @param segment 8 bit unsigned value
+         * @param track 6 bit unsigned value
+         * @param channel 4 bit unsigned value
+         * @param controller 7 bit unsigned value
+         * @param value 7 bit unsigned value
+         */
+        void onJetEvent(JetPlayer player,
+                short segment, byte track, byte channel, byte controller, byte value);
+    }
+    
+    
+    //--------------------------------------------
+    // Native methods
+    //------------------------
+    private native final boolean native_setup(Object Jet_this,
+                int maxTracks, int trackBufferSize);
+    private native final void    native_finalize();
+    private native final void    native_release();
+    private native final boolean native_loadJetFromFile(String pathToJetFile);
+    private native final boolean native_loadJetFromFileD(FileDescriptor fd, long offset, long len);
+    private native final boolean native_closeJetFile();
+    private native final boolean native_playJet();
+    private native final boolean native_pauseJet();
+    private native final boolean native_queueJetSegment(int segmentNum, int libNum,
+            int repeatCount, int transpose, int muteFlags, byte userID);
+    private native final boolean native_queueJetSegmentMuteArray(int segmentNum, int libNum, 
+            int repeatCount, int transpose, boolean[] muteArray, byte userID);
+    private native final boolean native_setMuteFlags(int muteFlags, boolean sync);
+    private native final boolean native_setMuteArray(boolean[]muteArray, boolean sync);
+    private native final boolean native_setMuteFlag(int trackId, boolean muteFlag, boolean sync);
+    private native final boolean native_triggerClip(int clipId);
+    private native final boolean native_clearQueue();
+    
+    //---------------------------------------------------------
+    // Called exclusively by native code
+    //--------------------
+    @SuppressWarnings("unused")
+    private static void postEventFromNative(Object jetplayer_ref,
+            int what, int arg1, int arg2) {
+        
+        JetPlayer jet = (JetPlayer)((WeakReference)jetplayer_ref).get();
+
+        if( (jet!=null) && (jet.mNativeEventHandler!=null) ){
+            Message m = jet.mNativeEventHandler.obtainMessage(what, arg1, arg2, null);
+            jet.mNativeEventHandler.sendMessage(m);
+        }
+    }
+    
+ 
+    //---------------------------------------------------------
+    // Utils
+    //--------------------
+    private final static String TAG = "JetPlayer-J";
+    
+    private static void logd(String msg) {
+        Log.d(TAG, "[ android.media.JetPlayer ] " + msg);
+    }
+    
+    private static void loge(String msg) {
+        Log.e(TAG, "[ android.media.JetPlayer ] " + msg);
+    }
+ 
+}
diff --git a/media/java/android/media/MediaFile.java b/media/java/android/media/MediaFile.java
new file mode 100644
index 0000000..f05842d
--- /dev/null
+++ b/media/java/android/media/MediaFile.java
@@ -0,0 +1,185 @@
+/*
+ * 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.
+ */
+
+package android.media;
+
+import android.content.ContentValues;
+import android.provider.MediaStore.Audio;
+import android.provider.MediaStore.Images;
+import android.provider.MediaStore.Video;
+
+import java.util.HashMap;
+import java.util.Iterator;
+
+/**
+ * MediaScanner helper class.
+ *
+ * {@hide}
+ */
+public class MediaFile {
+    // comma separated list of all file extensions supported by the media scanner
+    public static String sFileExtensions;
+
+    // Audio file types
+    public static final int FILE_TYPE_MP3     = 1;
+    public static final int FILE_TYPE_M4A     = 2;
+    public static final int FILE_TYPE_WAV     = 3;
+    public static final int FILE_TYPE_AMR     = 4;
+    public static final int FILE_TYPE_AWB     = 5;
+    public static final int FILE_TYPE_WMA     = 6;
+    public static final int FILE_TYPE_OGG     = 7;
+    private static final int FIRST_AUDIO_FILE_TYPE = FILE_TYPE_MP3;
+    private static final int LAST_AUDIO_FILE_TYPE = FILE_TYPE_OGG;
+
+    // MIDI file types
+    public static final int FILE_TYPE_MID     = 11;
+    public static final int FILE_TYPE_SMF     = 12;
+    public static final int FILE_TYPE_IMY     = 13;
+    private static final int FIRST_MIDI_FILE_TYPE = FILE_TYPE_MID;
+    private static final int LAST_MIDI_FILE_TYPE = FILE_TYPE_IMY;
+   
+    // Video file types
+    public static final int FILE_TYPE_MP4     = 21;
+    public static final int FILE_TYPE_M4V     = 22;
+    public static final int FILE_TYPE_3GPP    = 23;
+    public static final int FILE_TYPE_3GPP2   = 24;
+    public static final int FILE_TYPE_WMV     = 25;
+    private static final int FIRST_VIDEO_FILE_TYPE = FILE_TYPE_MP4;
+    private static final int LAST_VIDEO_FILE_TYPE = FILE_TYPE_WMV;
+    
+    // Image file types
+    public static final int FILE_TYPE_JPEG    = 31;
+    public static final int FILE_TYPE_GIF     = 32;
+    public static final int FILE_TYPE_PNG     = 33;
+    public static final int FILE_TYPE_BMP     = 34;
+    public static final int FILE_TYPE_WBMP    = 35;
+    private static final int FIRST_IMAGE_FILE_TYPE = FILE_TYPE_JPEG;
+    private static final int LAST_IMAGE_FILE_TYPE = FILE_TYPE_WBMP;
+   
+    // Playlist file types
+    public static final int FILE_TYPE_M3U     = 41;
+    public static final int FILE_TYPE_PLS     = 42;
+    public static final int FILE_TYPE_WPL     = 43;
+    private static final int FIRST_PLAYLIST_FILE_TYPE = FILE_TYPE_M3U;
+    private static final int LAST_PLAYLIST_FILE_TYPE = FILE_TYPE_WPL;
+    
+    static class MediaFileType {
+    
+        int fileType;
+        String mimeType;
+        
+        MediaFileType(int fileType, String mimeType) {
+            this.fileType = fileType;
+            this.mimeType = mimeType;
+        }
+    }
+    
+    private static HashMap<String, MediaFileType> sFileTypeMap 
+            = new HashMap<String, MediaFileType>();
+    private static HashMap<String, Integer> sMimeTypeMap 
+            = new HashMap<String, Integer>();            
+    static void addFileType(String extension, int fileType, String mimeType) {
+        sFileTypeMap.put(extension, new MediaFileType(fileType, mimeType));
+        sMimeTypeMap.put(mimeType, new Integer(fileType));
+    }
+    static {
+        addFileType("MP3", FILE_TYPE_MP3, "audio/mpeg");
+        addFileType("M4A", FILE_TYPE_M4A, "audio/mp4");
+        addFileType("WAV", FILE_TYPE_WAV, "audio/x-wav");
+        addFileType("AMR", FILE_TYPE_AMR, "audio/amr");
+        addFileType("AWB", FILE_TYPE_AWB, "audio/amr-wb");
+        addFileType("WMA", FILE_TYPE_WMA, "audio/x-ms-wma");    
+        addFileType("OGG", FILE_TYPE_OGG, "application/ogg");
+        addFileType("OGA", FILE_TYPE_OGG, "application/ogg");
+ 
+        addFileType("MID", FILE_TYPE_MID, "audio/midi");
+        addFileType("MIDI", FILE_TYPE_MID, "audio/midi");
+        addFileType("XMF", FILE_TYPE_MID, "audio/midi");
+        addFileType("RTTTL", FILE_TYPE_MID, "audio/midi");
+        addFileType("SMF", FILE_TYPE_SMF, "audio/sp-midi");
+        addFileType("IMY", FILE_TYPE_IMY, "audio/imelody");
+        addFileType("RTX", FILE_TYPE_MID, "audio/midi");
+        addFileType("OTA", FILE_TYPE_MID, "audio/midi");
+        
+        addFileType("MP4", FILE_TYPE_MP4, "video/mp4");
+        addFileType("M4V", FILE_TYPE_M4V, "video/mp4");
+        addFileType("3GP", FILE_TYPE_3GPP, "video/3gpp");
+        addFileType("3GPP", FILE_TYPE_3GPP, "video/3gpp");
+        addFileType("3G2", FILE_TYPE_3GPP2, "video/3gpp2");
+        addFileType("3GPP2", FILE_TYPE_3GPP2, "video/3gpp2");
+        addFileType("WMV", FILE_TYPE_WMV, "video/x-ms-wmv");
+
+        addFileType("JPG", FILE_TYPE_JPEG, "image/jpeg");
+        addFileType("JPEG", FILE_TYPE_JPEG, "image/jpeg");
+        addFileType("GIF", FILE_TYPE_GIF, "image/gif");
+        addFileType("PNG", FILE_TYPE_PNG, "image/png");
+        addFileType("BMP", FILE_TYPE_BMP, "image/x-ms-bmp");
+        addFileType("WBMP", FILE_TYPE_WBMP, "image/vnd.wap.wbmp");
+ 
+        addFileType("M3U", FILE_TYPE_M3U, "audio/x-mpegurl");
+        addFileType("PLS", FILE_TYPE_PLS, "audio/x-scpls");
+        addFileType("WPL", FILE_TYPE_WPL, "application/vnd.ms-wpl");
+
+        // compute file extensions list for native Media Scanner
+        StringBuilder builder = new StringBuilder();
+        Iterator<String> iterator = sFileTypeMap.keySet().iterator();
+        
+        while (iterator.hasNext()) {
+            if (builder.length() > 0) {
+                builder.append(',');
+            }
+            builder.append(iterator.next());
+        } 
+        sFileExtensions = builder.toString();
+    }
+    
+    public static final String UNKNOWN_STRING = "<unknown>";
+    
+    public static boolean isAudioFileType(int fileType) {
+        return ((fileType >= FIRST_AUDIO_FILE_TYPE &&
+                fileType <= LAST_AUDIO_FILE_TYPE) ||
+                (fileType >= FIRST_MIDI_FILE_TYPE &&
+                fileType <= LAST_MIDI_FILE_TYPE));
+    }
+    
+    public static boolean isVideoFileType(int fileType) {
+        return (fileType >= FIRST_VIDEO_FILE_TYPE &&
+                fileType <= LAST_VIDEO_FILE_TYPE);
+    }
+    
+    public static boolean isImageFileType(int fileType) {
+        return (fileType >= FIRST_IMAGE_FILE_TYPE &&
+                fileType <= LAST_IMAGE_FILE_TYPE);
+    }
+    
+    public static boolean isPlayListFileType(int fileType) {
+        return (fileType >= FIRST_PLAYLIST_FILE_TYPE &&
+                fileType <= LAST_PLAYLIST_FILE_TYPE);
+    }
+    
+    public static MediaFileType getFileType(String path) {
+        int lastDot = path.lastIndexOf(".");
+        if (lastDot < 0)
+            return null;
+        return sFileTypeMap.get(path.substring(lastDot + 1).toUpperCase());
+    }
+    
+    public static int getFileTypeForMimeType(String mimeType) {
+        Integer value = sMimeTypeMap.get(mimeType);
+        return (value == null ? 0 : value.intValue());
+    }
+
+}
diff --git a/media/java/android/media/MediaMetadataRetriever.java b/media/java/android/media/MediaMetadataRetriever.java
new file mode 100644
index 0000000..3a49a5f
--- /dev/null
+++ b/media/java/android/media/MediaMetadataRetriever.java
@@ -0,0 +1,256 @@
+/*
+ * 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.
+ */
+
+package android.media;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.res.AssetFileDescriptor;
+import android.graphics.Bitmap;
+import android.net.Uri;
+import android.os.ParcelFileDescriptor;
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.io.FileNotFoundException;
+
+/**
+ * MediaMetadataRetriever class provides a unified interface for retrieving
+ * frame and meta data from an input media file.
+ * {@hide}
+ */
+public class MediaMetadataRetriever
+{
+    static {
+        System.loadLibrary("media_jni");
+    }
+
+    // The field below is accessed by native methods
+    @SuppressWarnings("unused")
+    private int mNativeContext;
+ 
+    public MediaMetadataRetriever() {
+        native_setup();
+    }
+
+    /**
+     * Call this method before setDataSource() so that the mode becomes
+     * effective for subsequent operations. This method can be called only once
+     * at the beginning if the intended mode of operation for a
+     * MediaMetadataRetriever object remains the same for its whole lifetime,
+     * and thus it is unnecessary to call this method each time setDataSource()
+     * is called. If this is not never called (which is allowed), by default the
+     * intended mode of operation is to both capture frame and retrieve meta
+     * data (i.e., MODE_GET_METADATA_ONLY | MODE_CAPTURE_FRAME_ONLY).
+     * Often, this may not be what one wants, since doing this has negative
+     * performance impact on execution time of a call to setDataSource(), since
+     * both types of operations may be time consuming.
+     * 
+     * @param mode The intended mode of operation. Can be any combination of 
+     * MODE_GET_METADATA_ONLY and MODE_CAPTURE_FRAME_ONLY:
+     * 1. MODE_GET_METADATA_ONLY & MODE_CAPTURE_FRAME_ONLY: 
+     *    For neither frame capture nor meta data retrieval
+     * 2. MODE_GET_METADATA_ONLY: For meta data retrieval only
+     * 3. MODE_CAPTURE_FRAME_ONLY: For frame capture only
+     * 4. MODE_GET_METADATA_ONLY | MODE_CAPTURE_FRAME_ONLY: 
+     *    For both frame capture and meta data retrieval
+     */
+    public native void setMode(int mode);
+    
+    /**
+     * @return the current mode of operation. A negative return value indicates
+     * some runtime error has occurred.
+     */
+    public native int getMode();
+
+    /**
+     * Sets the data source (file pathname) to use. Call this
+     * method before the rest of the methods in this class. This method may be
+     * time-consuming.
+     * 
+     * @param path The path of the input media file.
+     * @throws IllegalArgumentException If the path is invalid.
+     */
+    public native void setDataSource(String path) throws IllegalArgumentException;
+    
+    /**
+     * Sets the data source (FileDescriptor) to use.  It is the caller's
+     * responsibility to close the file descriptor. It is safe to do so as soon
+     * as this call returns. Call this method before the rest of the methods in
+     * this class. This method may be time-consuming.
+     * 
+     * @param fd the FileDescriptor for the file you want to play
+     * @param offset the offset into the file where the data to be played starts,
+     * in bytes. It must be non-negative
+     * @param length the length in bytes of the data to be played. It must be
+     * non-negative.
+     * @throws IllegalArgumentException if the arguments are invalid
+     */
+    public native void setDataSource(FileDescriptor fd, long offset, long length)
+            throws IllegalArgumentException;
+    
+    /**
+     * Sets the data source (FileDescriptor) to use. It is the caller's
+     * responsibility to close the file descriptor. It is safe to do so as soon
+     * as this call returns. Call this method before the rest of the methods in
+     * this class. This method may be time-consuming.
+     * 
+     * @param fd the FileDescriptor for the file you want to play
+     * @throws IllegalArgumentException if the FileDescriptor is invalid
+     */
+    public void setDataSource(FileDescriptor fd)
+            throws IllegalArgumentException {
+        // intentionally less than LONG_MAX
+        setDataSource(fd, 0, 0x7ffffffffffffffL);
+    }
+    
+    /**
+     * Sets the data source as a content Uri. Call this method before 
+     * the rest of the methods in this class. This method may be time-consuming.
+     * 
+     * @param context the Context to use when resolving the Uri
+     * @param uri the Content URI of the data you want to play
+     * @throws IllegalArgumentException if the Uri is invalid
+     * @throws SecurityException if the Uri cannot be used due to lack of
+     * permission.
+     */
+    public void setDataSource(Context context, Uri uri)
+        throws IllegalArgumentException, SecurityException {
+        if (uri == null) {
+            throw new IllegalArgumentException();
+        }
+        
+        String scheme = uri.getScheme();
+        if(scheme == null || scheme.equals("file")) {
+            setDataSource(uri.getPath());
+            return;
+        }
+
+        AssetFileDescriptor fd = null;
+        try {
+            ContentResolver resolver = context.getContentResolver();
+            try {
+                fd = resolver.openAssetFileDescriptor(uri, "r");
+            } catch(FileNotFoundException e) {
+                throw new IllegalArgumentException();
+            }
+            if (fd == null) {
+                throw new IllegalArgumentException();
+            }
+            FileDescriptor descriptor = fd.getFileDescriptor();
+            if (!descriptor.valid()) {
+                throw new IllegalArgumentException();
+            }
+            // Note: using getDeclaredLength so that our behavior is the same
+            // as previous versions when the content provider is returning
+            // a full file.
+            if (fd.getDeclaredLength() < 0) {
+                setDataSource(descriptor);
+            } else {
+                setDataSource(descriptor, fd.getStartOffset(), fd.getDeclaredLength());
+            }
+            return;
+        } catch (SecurityException ex) {
+        } finally {
+            try {
+                if (fd != null) {
+                    fd.close();
+                }
+            } catch(IOException ioEx) {
+            }
+        }
+        setDataSource(uri.toString());
+    }
+
+    /**
+     * Call this method after setDataSource(). This method retrieves the 
+     * meta data value associated with the keyCode.
+     * 
+     * The keyCode currently supported is listed below as METADATA_XXX
+     * constants. With any other value, it returns a null pointer.
+     * 
+     * @param keyCode One of the constants listed below at the end of the class.
+     * @return The meta data value associate with the given keyCode on success; 
+     * null on failure.
+     */
+    public native String extractMetadata(int keyCode);
+
+    /**
+     * Call this method after setDataSource(). This method finds a
+     * representative frame if successful and returns it as a bitmap. This is
+     * useful for generating a thumbnail for an input media source.
+     * 
+     * @return A Bitmap containing a representative video frame, which 
+     *         can be null, if such a frame cannot be retrieved.
+     */
+    public native Bitmap captureFrame();
+    
+    /**
+     * Call this method after setDataSource(). This method finds the optional
+     * graphic or album art associated (embedded or external url linked) the 
+     * related data source.
+     * 
+     * @return null if no such graphic is found.
+     */
+    public native byte[] extractAlbumArt();
+
+    /**
+     * Call it when one is done with the object. This method releases the memory
+     * allocated internally.
+     */
+    public native void release();
+    private native void native_setup(); 
+
+    private native final void native_finalize();
+
+    @Override
+    protected void finalize() throws Throwable {
+        try {
+            native_finalize();
+        } finally {
+            super.finalize();
+        }
+    }
+
+    public static final int MODE_GET_METADATA_ONLY  = 0x01;
+    public static final int MODE_CAPTURE_FRAME_ONLY = 0x02;
+
+    /*
+     * Do not change these values without updating their counterparts
+     * in include/media/mediametadataretriever.h!
+     */
+    public static final int METADATA_KEY_CD_TRACK_NUMBER = 0;
+    public static final int METADATA_KEY_ALBUM           = 1;
+    public static final int METADATA_KEY_ARTIST          = 2;
+    public static final int METADATA_KEY_AUTHOR          = 3;
+    public static final int METADATA_KEY_COMPOSER        = 4;
+    public static final int METADATA_KEY_DATE            = 5;
+    public static final int METADATA_KEY_GENRE           = 6;
+    public static final int METADATA_KEY_TITLE           = 7;
+    public static final int METADATA_KEY_YEAR            = 8;
+    public static final int METADATA_KEY_DURATION        = 9;
+    public static final int METADATA_KEY_NUM_TRACKS      = 10;
+    public static final int METADATA_KEY_IS_DRM_CRIPPLED = 11;
+    public static final int METADATA_KEY_CODEC           = 12;
+    public static final int METADATA_KEY_RATING          = 13;
+    public static final int METADATA_KEY_COMMENT         = 14;
+    public static final int METADATA_KEY_COPYRIGHT       = 15;
+    public static final int METADATA_KEY_BIT_RATE        = 16;
+    public static final int METADATA_KEY_FRAME_RATE      = 17;
+    public static final int METADATA_KEY_VIDEO_FORMAT    = 18;
+    public static final int METADATA_KEY_VIDEO_HEIGHT    = 19;
+    public static final int METADATA_KEY_VIDEO_WIDTH     = 20;
+    // Add more here...
+}
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
new file mode 100644
index 0000000..369af3b
--- /dev/null
+++ b/media/java/android/media/MediaPlayer.java
@@ -0,0 +1,1211 @@
+/*
+ * 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.
+ */
+
+package android.media;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.res.AssetFileDescriptor;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.ParcelFileDescriptor;
+import android.os.PowerManager;
+import android.util.Log;
+import android.view.Surface;
+import android.view.SurfaceHolder;
+import android.graphics.Bitmap;
+import android.media.AudioManager;
+
+import java.io.FileDescriptor;
+import java.io.IOException;
+
+import java.lang.ref.WeakReference;
+
+/**
+ * MediaPlayer class can be used to control playback
+ * of audio/video files and streams. An example on how to use the methods in
+ * this class can be found in {@link android.widget.VideoView}.
+ * Please see <a href="{@docRoot}guide/topics/media/index.html">Audio and Video</a>
+ * for additional help using MediaPlayer.
+ *
+ * <p>Topics covered here are:
+ * <ol>
+ * <li><a href="#StateDiagram">State Diagram</a>
+ * <li><a href="#Valid_and_Invalid_States">Valid and Invalid States</a>
+ * <li><a href="#Permissions">Permissions</a>
+ * </ol>
+ *
+ * <a name="StateDiagram"></a>
+ * <h3>State Diagram</h3>
+ *
+ * <p>Playback control of audio/video files and streams is managed as a state
+ * machine. The following diagram shows the life cycle and the states of a
+ * MediaPlayer object driven by the supported playback control operations.
+ * The ovals represent the states a MediaPlayer object may reside
+ * in. The arcs represent the playback control operations that drive the object
+ * state transition. There are two types of arcs. The arcs with a single arrow 
+ * head represent synchronous method calls, while those with
+ * a double arrow head represent asynchronous method calls.</p>
+ *
+ * <p><img src="../../../images/mediaplayer_state_diagram.gif"
+ *         alt="MediaPlayer State diagram"
+ *         border="0" /></p>
+ *
+ * <p>From this state diagram, one can see that a MediaPlayer object has the
+ *    following states:</p>
+ * <ul>
+ *     <li>When a MediaPlayer object is just created using <code>new</code> or 
+ *         after {@link #reset()} is called, it is in the <em>Idle</em> state; and after 
+ *         {@link #release()} is called, it is in the <em>End</em> state. Between these 
+ *         two states is the life cycle of the MediaPlayer object. 
+ *         <ul>
+ *         <li>There is a subtle but important difference between a newly constructed 
+ *         MediaPlayer object and the MediaPlayer object after {@link #reset()} 
+ *         is called. It is a programming error to invoke methods such 
+ *         as {@link #getCurrentPosition()}, 
+ *         {@link #getDuration()}, {@link #getVideoHeight()}, 
+ *         {@link #getVideoWidth()}, {@link #setAudioStreamType(int)},
+ *         {@link #setLooping(boolean)},
+ *         {@link #setVolume(float, float)}, {@link #pause()}, {@link #start()}, 
+ *         {@link #stop()}, {@link #seekTo(int)}, {@link #prepare()} or 
+ *         {@link #prepareAsync()} in the <em>Idle</em> state for both cases. If any of these 
+ *         methods is called right after a MediaPlayer object is constructed, 
+ *         the user supplied callback method OnErrorListener.onError() won't be 
+ *         called by the internal player engine and the object state remains
+ *         unchanged; but if these methods are called right after {@link #reset()}, 
+ *         the user supplied callback method OnErrorListener.onError() will be
+ *         invoked by the internal player engine and the object will be 
+ *         transfered to the <em>Error</em> state. </li>
+ *         <li>It is also recommended that once 
+ *         a MediaPlayer object is no longer being used, call {@link #release()} immediately 
+ *         so that resources used by the internal player engine associated with the 
+ *         MediaPlayer object can be released immediately. Resource may include
+ *         singleton resources such as hardware acceleration components and 
+ *         failure to call {@link #release()} may cause subsequent instances of
+ *         MediaPlayer objects to fallback to software implementations or fail
+ *         altogether. Once the MediaPlayer
+ *         object is in the <em>End</em> state, it can no longer be used and 
+ *         there is no way to bring it back to any other state. </li>
+ *         <li>Furthermore, 
+ *         the MediaPlayer objects created using <code>new</code> is in the 
+ *         <em>Idle</em> state, while those created with one 
+ *         of the overloaded convenient <code>create</code> methods are <em>NOT</em> 
+ *         in the <em>Idle</em> state. In fact, the objects are in the <em>Prepared</em>
+ *         state if the creation using <code>create</code> method is successful.
+ *         </li>
+ *         </ul>
+ *         </li>
+ *     <li>In general, some playback control operation may fail due to various
+ *         reasons, such as unsupported audio/video format, poorly interleaved
+ *         audio/video, resolution too high, streaming timeout, and the like.
+ *         Thus, error reporting and recovery is an important concern under
+ *         these circumstances. Sometimes, due to programming errors, invoking a playback 
+ *         control operation in an invalid state may also occur. Under all these
+ *         error conditions, the internal player engine invokes a user supplied
+ *         OnErrorListener.onError() method if an OnErrorListener has been
+ *         registered beforehand via
+ *         {@link #setOnErrorListener(android.media.MediaPlayer.OnErrorListener)}.
+ *         <ul>
+ *         <li>It is important to note that once an error occurs, the 
+ *         MediaPlayer object enters the <em>Error</em> state (except as noted 
+ *         above), even if an error listener has not been registered by the application.</li>
+ *         <li>In order to reuse a MediaPlayer object that is in the <em>
+ *         Error</em> state and recover from the error, 
+ *         {@link #reset()} can be called to restore the object to its <em>Idle</em>
+ *         state.</li>
+ *         <li>It is good programming practice to have your application 
+ *         register a OnErrorListener to look out for error notifications from 
+ *         the internal player engine.</li> 
+ *         <li>IlleglStateException is
+ *         thrown to prevent programming errors such as calling {@link #prepare()},
+ *         {@link #prepareAsync()}, or one of the overloaded <code>setDataSource
+ *         </code> methods in an invalid state. </li>
+ *         </ul>
+ *         </li>
+ *     <li>Calling
+ *         {@link #setDataSource(FileDescriptor)}, or
+ *         {@link #setDataSource(String)}, or
+ *         {@link #setDataSource(Context, Uri)}, or
+ *         {@link #setDataSource(FileDescriptor, long, long)} transfers a 
+ *         MediaPlayer object in the <em>Idle</em> state to the
+ *         <em>Initialized</em> state.
+ *         <ul>
+ *         <li>An IllegalStateException is thrown if 
+ *         setDataSource() is called in any other state.</li>
+ *         <li>It is good programming 
+ *         practice to always look out for <code>IllegalArgumentException</code> 
+ *         and <code>IOException</code> that may be thrown from the overloaded
+ *         <code>setDataSource</code> methods.</li>
+ *         </ul>
+ *         </li>
+ *     <li>A MediaPlayer object must first enter the <em>Prepared</em> state
+ *         before playback can be started. 
+ *         <ul>
+ *         <li>There are two ways (synchronous vs.
+ *         asynchronous) that the <em>Prepared</em> state can be reached:
+ *         either a call to {@link #prepare()} (synchronous) which
+ *         transfers the object to the <em>Prepared</em> state once the method call
+ *         returns, or a call to {@link #prepareAsync()} (asynchronous) which
+ *         first transfers the object to the <em>Preparing</em> state after the 
+ *         call returns (which occurs almost right way) while the internal 
+ *         player engine continues working on the rest of preparation work
+ *         until the preparation work completes. When the preparation completes or when {@link #prepare()} call returns,
+ *         the internal player engine then calls a user supplied callback method,
+ *         onPrepared() of the OnPreparedListener interface, if an
+ *         OnPreparedListener is registered beforehand via {@link
+ *         #setOnPreparedListener(android.media.MediaPlayer.OnPreparedListener)}.</li>
+ *         <li>It is important to note that
+ *         the <em>Preparing</em> state is a transient state, and the behavior
+ *         of calling any method with side effect while a MediaPlayer object is
+ *         in the <em>Preparing</em> state is undefined.</li>
+ *         <li>An IllegalStateException is 
+ *         thrown if {@link #prepare()} or {@link #prepareAsync()} is called in 
+ *         any other state.</li> 
+ *         <li>While in the <em>Prepared</em> state, properties 
+ *         such as audio/sound volume, screenOnWhilePlaying, looping can be 
+ *         adjusted by invoking the corresponding set methods.</li>
+ *         </ul>
+ *         </li>
+ *     <li>To start the playback, {@link #start()} must be called. After 
+ *         {@link #start()} returns successfully, the MediaPlayer object is in the
+ *         <em>Started</em> state. {@link #isPlaying()} can be called to test 
+ *         whether the MediaPlayer object is in the <em>Started</em> state.
+ *         <ul>
+ *         <li>While in the <em>Started</em> state, the internal player engine calls
+ *         a user supplied OnBufferingUpdateListener.onBufferingUpdate() callback
+ *         method if a OnBufferingUpdateListener has been registered beforehand 
+ *         via {@link #setOnBufferingUpdateListener(OnBufferingUpdateListener)}.
+ *         This callback allows applications to keep track of the buffering status
+ *         while streaming audio/video.</li>
+ *         <li>Calling {@link #start()} has not effect
+ *         on a MediaPlayer object that is already in the <em>Started</em> state.</li>
+ *         </ul>
+ *         </li>
+ *     <li>Playback can be paused and stopped, and the current playback position
+ *         can be adjusted. Playback can be paused via {@link #pause()}. When the call to 
+ *         {@link #pause()} returns, the MediaPlayer object enters the
+ *         <em>Paused</em> state. Note that the transition from the <em>Started</em> 
+ *         state to the <em>Paused</em> state and vice versa happens 
+ *         asynchronously in the player engine. It may take some time before 
+ *         the state is updated in calls to {@link #isPlaying()}, and it can be 
+ *         a number of seconds in the case of streamed content.
+ *         <ul>
+ *         <li>Calling {@link #start()} to resume playback for a paused 
+ *         MediaPlayer object, and the resumed playback
+ *         position is the same as where it was paused. When the call to 
+ *         {@link #start()} returns, the paused MediaPlayer object goes back to
+ *         the <em>Started</em> state.</li>
+ *         <li>Calling {@link #pause()} has no effect on
+ *         a MediaPlayer object that is already in the <em>Paused</em> state.</li>
+ *         </ul>
+ *         </li>
+ *     <li>Calling  {@link #stop()} stops playback and causes a 
+ *         MediaPlayer in the <em>Started</em>, <em>Paused</em>, <em>Prepared
+ *         </em> or <em>PlaybackCompleted</em> state to enter the 
+ *         <em>Stopped</em> state.
+ *         <ul>
+ *         <li>Once in the <em>Stopped</em> state, playback cannot be started 
+ *         until {@link #prepare()} or {@link #prepareAsync()} are called to set
+ *         the MediaPlayer object to the <em>Prepared</em> state again.</li>
+ *         <li>Calling {@link #stop()} has no effect on a MediaPlayer 
+ *         object that is already in the <em>Stopped</em> state.</li>
+ *         </ul>
+ *         </li>
+ *     <li>The playback position can be adjusted with a call to 
+ *         {@link #seekTo(int)}. 
+ *         <ul>
+ *         <li>Although the asynchronuous {@link #seekTo(int)}
+ *         call returns right way, the actual seek operation may take a while to
+ *         finish, especially for audio/video being streamed. When the actual 
+ *         seek operation completes, the internal player engine calls a user 
+ *         supplied OnSeekComplete.onSeekComplete() if an OnSeekCompleteListener
+ *         has been registered beforehand via 
+ *         {@link #setOnSeekCompleteListener(OnSeekCompleteListener)}.</li>
+ *         <li>Please
+ *         note that {@link #seekTo(int)} can also be called in the other states,
+ *         such as <em>Prepared</em>, <em>Paused</em> and <em>PlaybackCompleted
+ *         </em> state.</li>
+ *         <li>Furthermore, the actual current playback position
+ *         can be retrieved with a call to {@link #getCurrentPosition()}, which
+ *         is helpful for applications such as a Music player that need to keep 
+ *         track of the playback progress.</li>
+ *         </ul>
+ *         </li>
+ *     <li>When the playback reaches the end of stream, the playback completes.
+ *         <ul>
+ *         <li>If the looping mode was being set to <var>true</var>with
+ *         {@link #setLooping(boolean)}, the MediaPlayer object shall remain in
+ *         the <em>Started</em> state.</li>
+ *         <li>If the looping mode was set to <var>false
+ *         </var>, the player engine calls a user supplied callback method,
+ *         OnCompletion.onCompletion(), if a OnCompletionListener is registered
+ *         beforehand via {@link #setOnCompletionListener(OnCompletionListener)}.
+ *         The invoke of the callback signals that the object is now in the <em>
+ *         PlaybackCompleted</em> state.</li>
+ *         <li>While in the <em>PlaybackCompleted</em>
+ *         state, calling {@link #start()} can restart the playback from the
+ *         beginning of the audio/video source.</li>
+ * </ul>
+ *
+ *
+ * <a name="Valid_and_Invalid_States"></a>
+ * <h3>Valid and invalid states</h3>
+ *
+ * <table border="0" cellspacing="0" cellpadding="0">
+ * <tr><td>Method Name </p></td>
+ *     <td>Valid Sates </p></td>
+ *     <td>Invalid States </p></td>
+ *     <td>Comments </p></td></tr>
+ * <tr><td>getCurrentPosition </p></td>
+ *     <td>{Idle, Initialized, Prepared, Started, Paused, Stopped, 
+ *         PlaybackCompleted} </p></td>
+ *     <td>{Error}</p></td>
+ *     <td>Successful invoke of this method in a valid state does not change the
+ *         state. Calling this method in an invalid state transfers the object
+ *         to the <em>Error</em> state. </p></td></tr>
+ * <tr><td>getDuration </p></td>
+ *     <td>{Prepared, Started, Paused, Stopped, PlaybackCompleted} </p></td>
+ *     <td>{Idle, Initialized, Error} </p></td>
+ *     <td>Successful invoke of this method in a valid state does not change the
+ *         state. Calling this method in an invalid state transfers the object 
+ *         to the <em>Error</em> state. </p></td></tr>
+ * <tr><td>getVideoHeight </p></td>
+ *     <td>{Idle, Initialized, Prepared, Started, Paused, Stopped, 
+ *         PlaybackCompleted}</p></td>
+ *     <td>{Error}</p></td>
+ *     <td>Successful invoke of this method in a valid state does not change the
+ *         state. Calling this method in an invalid state transfers the object 
+ *         to the <em>Error</em> state.  </p></td></tr>
+ * <tr><td>getVideoWidth </p></td>
+ *     <td>{Idle, Initialized, Prepared, Started, Paused, Stopped,
+ *         PlaybackCompleted}</p></td>
+ *     <td>{Error}</p></td>
+ *     <td>Successful invoke of this method in a valid state does not change 
+ *         the state. Calling this method in an invalid state transfers the 
+ *         object to the <em>Error</em> state. </p></td></tr>
+ * <tr><td>isPlaying </p></td>
+ *     <td>{Idle, Initialized, Prepared, Started, Paused, Stopped, 
+ *          PlaybackCompleted}</p></td>
+ *     <td>{Error}</p></td>
+ *     <td>Successful invoke of this method in a valid state does not change
+ *         the state. Calling this method in an invalid state transfers the 
+ *         object to the <em>Error</em> state. </p></td></tr>
+ * <tr><td>pause </p></td>
+ *     <td>{Started, Paused}</p></td>
+ *     <td>{Idle, Initialized, Prepared, Stopped, PlaybackCompleted, Error}</p></td>
+ *     <td>Successful invoke of this method in a valid state transfers the 
+ *         object to the <em>Paused</em> state. Calling this method in an 
+ *         invalid state transfers the object to the <em>Error</em> state.</p></td></tr>
+ * <tr><td>prepare </p></td>
+ *     <td>{Initialized, Stopped} </p></td>
+ *     <td>{Idle, Prepared, Started, Paused, PlaybackCompleted, Error} </p></td>
+ *     <td>Successful invoke of this method in a valid state transfers the 
+ *         object to the <em>Prepared</em> state. Calling this method in an 
+ *         invalid state throws an IllegalStateException.</p></td></tr>
+ * <tr><td>prepareAsync </p></td>
+ *     <td>{Initialized, Stopped} </p></td>
+ *     <td>{Idle, Prepared, Started, Paused, PlaybackCompleted, Error} </p></td>
+ *     <td>Successful invoke of this method in a valid state transfers the 
+ *         object to the <em>Preparing</em> state. Calling this method in an
+ *         invalid state throws an IllegalStateException.</p></td></tr>
+ * <tr><td>release </p></td>
+ *     <td>any </p></td>
+ *     <td>{} </p></td>
+ *     <td>After {@link #release()}, the object is no longer available. </p></td></tr>
+ * <tr><td>reset </p></td>
+ *     <td>{Idle, Initialized, Prepared, Started, Paused, Stopped, 
+ *         PlaybackCompleted, Error}</p></td>
+ *     <td>{}</p></td>
+ *     <td>After {@link #reset()}, the object is like being just created.</p></td></tr>
+ * <tr><td>seekTo </p></td>
+ *     <td>{Prepared, Started, Paused, PlaybackCompleted} </p></td>
+ *     <td>{Idle, Initialized, Stopped, Error}</p></td>
+ *     <td>Successful invoke of this method in a valid state does not change 
+ *         the state. Calling this method in an invalid state transfers the 
+ *         object to the <em>Error</em> state. </p></td></tr>
+ * <tr><td>setAudioStreamType </p></td>
+ *     <td>{Idle, Initialized, Stopped, Prepared, Started, Paused, 
+ *          PlaybackCompleted}</p></td>
+ *     <td>{Error}</p></td>
+ *     <td>Successful invoke of this method does not change the state.</p></td></tr>
+ * <tr><td>setDataSource </p></td>
+ *     <td>{Idle} </p></td>
+ *     <td>{Initialized, Prepared, Started, Paused, Stopped, PlaybackCompleted,
+ *          Error} </p></td>
+ *     <td>Successful invoke of this method in a valid state transfers the 
+ *         object to the <em>Initialized</em> state. Calling this method in an 
+ *         invalid state throws an IllegalStateException.</p></td></tr>
+ * <tr><td>setDisplay </p></td>
+ *     <td>any </p></td>
+ *     <td>{} </p></td>
+ *     <td>This method can be called in any state and calling it does not change
+ *         the object state. </p></td></tr>
+ * <tr><td>setLooping </p></td>
+ *     <td>{Idle, Initialized, Stopped, Prepared, Started, Paused, 
+ *         PlaybackCompleted}</p></td>
+ *     <td>{Error}</p></td>
+ *     <td>Successful invoke of this method in a valid state does not change 
+ *         the state. Calling this method in an 
+ *         invalid state transfers the object to the <em>Error</em> state.</p></td></tr>
+ * <tr><td>isLooping </p></td>
+ *     <td>any </p></td>
+ *     <td>{} </p></td>
+ *     <td>This method can be called in any state and calling it does not change
+ *         the object state. </p></td></tr>
+ * <tr><td>setOnBufferingUpdateListener </p></td>
+ *     <td>any </p></td>
+ *     <td>{} </p></td>
+ *     <td>This method can be called in any state and calling it does not change
+ *         the object state. </p></td></tr>
+ * <tr><td>setOnCompletionListener </p></td>
+ *     <td>any </p></td>
+ *     <td>{} </p></td>
+ *     <td>This method can be called in any state and calling it does not change
+ *         the object state. </p></td></tr>
+ * <tr><td>setOnErrorListener </p></td>
+ *     <td>any </p></td>
+ *     <td>{} </p></td>
+ *     <td>This method can be called in any state and calling it does not change
+ *         the object state. </p></td></tr>
+ * <tr><td>setOnPreparedListener </p></td>
+ *     <td>any </p></td>
+ *     <td>{} </p></td>
+ *     <td>This method can be called in any state and calling it does not change
+ *         the object state. </p></td></tr>
+ * <tr><td>setOnSeekCompleteListener </p></td>
+ *     <td>any </p></td>
+ *     <td>{} </p></td>
+ *     <td>This method can be called in any state and calling it does not change
+ *         the object state. </p></td></tr>
+ * <tr><td>setScreenOnWhilePlaying</></td>
+ *     <td>any </p></td>
+ *     <td>{} </p></td>
+ *     <td>This method can be called in any state and calling it does not change
+ *         the object state.  </p></td></tr>
+ * <tr><td>setVolume </p></td>
+ *     <td>{Idle, Initialized, Stopped, Prepared, Started, Paused, 
+ *          PlaybackCompleted}</p></td>
+ *     <td>{Error}</p></td>
+ *     <td>Successful invoke of this method does not change the state.
+ * <tr><td>setWakeMode </p></td>
+ *     <td>any </p></td>
+ *     <td>{} </p></td>
+ *     <td>This method can be called in any state and calling it does not change
+ *         the object state.</p></td></tr>
+ * <tr><td>start </p></td>
+ *     <td>{Prepared, Started, Paused, PlaybackCompleted}</p></td>
+ *     <td>{Idle, Initialized, Stopped, Error}</p></td>
+ *     <td>Successful invoke of this method in a valid state transfers the 
+ *         object to the <em>Started</em> state. Calling this method in an 
+ *         invalid state transfers the object to the <em>Error</em> state.</p></td></tr>
+ * <tr><td>stop </p></td>
+ *     <td>{Prepared, Started, Stopped, Paused, PlaybackCompleted}</p></td>
+ *     <td>{Idle, Initialized, Error}</p></td>
+ *     <td>Successful invoke of this method in a valid state transfers the 
+ *         object to the <em>Stopped</em> state. Calling this method in an 
+ *         invalid state transfers the object to the <em>Error</em> state.</p></td></tr>
+ * </table>
+ *
+ * <a name="Permissions"></a>
+ * <h3>Permissions</h3>
+ * <p>One may need to declare a corresponding WAKE_LOCK permission {@link
+ * android.R.styleable#AndroidManifestUsesPermission &lt;uses-permission&gt;}
+ * element.
+ *
+ */
+public class MediaPlayer
+{    
+    static {
+        System.loadLibrary("media_jni");
+    }
+    
+    private final static String TAG = "MediaPlayer";
+    
+    private int mNativeContext; // accessed by native methods
+    private int mListenerContext; // accessed by native methods
+    private Surface mSurface; // accessed by native methods
+    private SurfaceHolder  mSurfaceHolder;
+    private EventHandler mEventHandler;
+    private PowerManager.WakeLock mWakeLock = null;
+    private boolean mScreenOnWhilePlaying;
+    private boolean mStayAwake;
+    
+    /**
+     * Default constructor. Consider using one of the create() methods for 
+     * synchronously instantiating a MediaPlayer from a Uri or resource.
+     * <p>When done with the MediaPlayer, you should call  {@link #release()},
+     * to free the resources. If not released, too many MediaPlayer instances may
+     * result in an exception.</p>
+     */
+    public MediaPlayer() {
+   
+        Looper looper;
+        if ((looper = Looper.myLooper()) != null) {
+            mEventHandler = new EventHandler(this, looper);
+        } else if ((looper = Looper.getMainLooper()) != null) {
+            mEventHandler = new EventHandler(this, looper);
+        } else {
+            mEventHandler = null;
+        }
+
+        /* Native setup requires a weak reference to our object.
+         * It's easier to create it here than in C++.
+         */
+        native_setup(new WeakReference<MediaPlayer>(this));
+    }
+  
+    /**
+     * Sets the SurfaceHolder to use for displaying the video portion of the media.
+     * This call is optional. Not calling it when playing back a video will
+     * result in only the audio track being played.
+     * 
+     * @param sh the SurfaceHolder to use for video display
+     */
+    public void setDisplay(SurfaceHolder sh) {
+        mSurfaceHolder = sh;
+        mSurface = sh.getSurface();
+        updateSurfaceScreenOn();
+    }
+
+    /**
+     * Convenience method to create a MediaPlayer for a given Uri.
+     * On success, {@link #prepare()} will already have been called and must not be called again.
+     * <p>When done with the MediaPlayer, you should call  {@link #release()},
+     * to free the resources. If not released, too many MediaPlayer instances will
+     * result in an exception.</p>
+     * 
+     * @param context the Context to use 
+     * @param uri the Uri from which to get the datasource
+     * @return a MediaPlayer object, or null if creation failed
+     */
+    public static MediaPlayer create(Context context, Uri uri) {
+        return create (context, uri, null);
+    }
+    
+    /**
+     * Convenience method to create a MediaPlayer for a given Uri.
+     * On success, {@link #prepare()} will already have been called and must not be called again.
+     * <p>When done with the MediaPlayer, you should call  {@link #release()},
+     * to free the resources. If not released, too many MediaPlayer instances will
+     * result in an exception.</p>
+     * 
+     * @param context the Context to use 
+     * @param uri the Uri from which to get the datasource
+     * @param holder the SurfaceHolder to use for displaying the video
+     * @return a MediaPlayer object, or null if creation failed
+     */
+    public static MediaPlayer create(Context context, Uri uri, SurfaceHolder holder) {
+        
+        try {
+            MediaPlayer mp = new MediaPlayer();
+            mp.setDataSource(context, uri);
+            if (holder != null) {
+                mp.setDisplay(holder);
+            }
+            mp.prepare();
+            return mp;
+        } catch (IOException ex) {
+            Log.d(TAG, "create failed:", ex);
+            // fall through
+        } catch (IllegalArgumentException ex) {
+            Log.d(TAG, "create failed:", ex);
+            // fall through
+        } catch (SecurityException ex) {
+            Log.d(TAG, "create failed:", ex);
+            // fall through
+        }
+
+        return null;
+    }
+
+    /**
+     * Convenience method to create a MediaPlayer for a given resource id.
+     * On success, {@link #prepare()} will already have been called and must not be called again.
+     * <p>When done with the MediaPlayer, you should call  {@link #release()},
+     * to free the resources. If not released, too many MediaPlayer instances will
+     * result in an exception.</p>
+     * 
+     * @param context the Context to use 
+     * @param resid the raw resource id (<var>R.raw.&lt;something></var>) for 
+     *              the resource to use as the datasource
+     * @return a MediaPlayer object, or null if creation failed
+     */
+    public static MediaPlayer create(Context context, int resid) {
+        try {
+            AssetFileDescriptor afd = context.getResources().openRawResourceFd(resid);
+            if (afd == null) return null;
+
+            MediaPlayer mp = new MediaPlayer();
+            mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
+            afd.close();
+            mp.prepare();
+            return mp;
+        } catch (IOException ex) {
+            Log.d(TAG, "create failed:", ex);
+            // fall through
+        } catch (IllegalArgumentException ex) {
+            Log.d(TAG, "create failed:", ex);
+           // fall through
+        } catch (SecurityException ex) {
+            Log.d(TAG, "create failed:", ex);
+            // fall through
+        }
+        return null;
+    }
+    
+    /**
+     * Sets the data source as a content Uri.
+     * 
+     * @param context the Context to use when resolving the Uri
+     * @param uri the Content URI of the data you want to play
+     * @throws IllegalStateException if it is called in an invalid state
+     */
+    public void setDataSource(Context context, Uri uri)
+        throws IOException, IllegalArgumentException, SecurityException, IllegalStateException {
+        
+        String scheme = uri.getScheme();
+        if(scheme == null || scheme.equals("file")) {
+            setDataSource(uri.getPath());
+            return;
+        }
+
+        AssetFileDescriptor fd = null;
+        try {
+            ContentResolver resolver = context.getContentResolver();
+            fd = resolver.openAssetFileDescriptor(uri, "r");
+            if (fd == null) {
+                return;
+            }
+            // Note: using getDeclaredLength so that our behavior is the same
+            // as previous versions when the content provider is returning
+            // a full file.
+            if (fd.getDeclaredLength() < 0) {
+                setDataSource(fd.getFileDescriptor());
+            } else {
+                setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getDeclaredLength());
+            }
+            return;
+        } catch (SecurityException ex) {
+        } catch (IOException ex) {
+        } finally {
+            if (fd != null) {
+                fd.close();
+            }
+        }
+        setDataSource(uri.toString());
+        return;
+    }
+
+    /**
+     * Sets the data source (file-path or http/rtsp URL) to use.
+     * 
+     * @param path the path of the file, or the http/rtsp URL of the stream you want to play
+     * @throws IllegalStateException if it is called in an invalid state
+     */
+    public native void setDataSource(String path) throws IOException, IllegalArgumentException, IllegalStateException;
+
+    /**
+     * Sets the data source (FileDescriptor) to use. It is the caller's responsibility
+     * to close the file descriptor. It is safe to do so as soon as this call returns.
+     * 
+     * @param fd the FileDescriptor for the file you want to play
+     * @throws IllegalStateException if it is called in an invalid state
+     */
+    public void setDataSource(FileDescriptor fd) 
+            throws IOException, IllegalArgumentException, IllegalStateException {
+        // intentionally less than LONG_MAX
+        setDataSource(fd, 0, 0x7ffffffffffffffL);
+    }
+    
+    /**
+     * Sets the data source (FileDescriptor) to use.  It is the caller's responsibility
+     * to close the file descriptor. It is safe to do so as soon as this call returns.
+     * 
+     * @param fd the FileDescriptor for the file you want to play
+     * @param offset the offset into the file where the data to be played starts, in bytes
+     * @param length the length in bytes of the data to be played
+     * @throws IllegalStateException if it is called in an invalid state
+     */
+    public native void setDataSource(FileDescriptor fd, long offset, long length) 
+            throws IOException, IllegalArgumentException, IllegalStateException;
+
+    /**
+     * Prepares the player for playback, synchronously.
+     * 
+     * After setting the datasource and the display surface, you need to either
+     * call prepare() or prepareAsync(). For files, it is OK to call prepare(),
+     * which blocks until MediaPlayer is ready for playback.
+     * 
+     * @throws IllegalStateException if it is called in an invalid state
+     */
+    public native void prepare() throws IOException, IllegalStateException;
+    
+    /**
+     * Prepares the player for playback, asynchronously.
+     * 
+     * After setting the datasource and the display surface, you need to either
+     * call prepare() or prepareAsync(). For streams, you should call prepareAsync(),
+     * which returns immediately, rather than blocking until enough data has been
+     * buffered.
+     * 
+     * @throws IllegalStateException if it is called in an invalid state
+     */
+    public native void prepareAsync() throws IllegalStateException;
+    
+    /**
+     * Starts or resumes playback. If playback had previously been paused,
+     * playback will continue from where it was paused. If playback had
+     * been stopped, or never started before, playback will start at the
+     * beginning.
+     * 
+     * @throws IllegalStateException if it is called in an invalid state
+     */
+    public  void start() throws IllegalStateException {
+        stayAwake(true);
+        _start();
+    }
+
+    private native void _start() throws IllegalStateException;
+    
+    /**
+     * Stops playback after playback has been stopped or paused. 
+     * 
+     * @throws IllegalStateException if the internal player engine has not been
+     * initialized.
+     */
+    public void stop() throws IllegalStateException {
+        stayAwake(false);
+        _stop();
+    }
+
+    private native void _stop() throws IllegalStateException;
+    
+    /**
+     * Pauses playback. Call start() to resume.
+     * 
+     * @throws IllegalStateException if the internal player engine has not been
+     * initialized.
+     */
+    public void pause() throws IllegalStateException {
+        stayAwake(false);
+        _pause();
+    }
+
+    private native void _pause() throws IllegalStateException;
+    
+    /**
+     * Set the low-level power management behavior for this MediaPlayer.  This
+     * can be used when the MediaPlayer is not playing through a SurfaceHolder
+     * set with {@link #setDisplay(SurfaceHolder)} and thus can use the
+     * high-level {@link #setScreenOnWhilePlaying(boolean)} feature.
+     * 
+     * <p>This function has the MediaPlayer access the low-level power manager
+     * service to control the device's power usage while playing is occurring.
+     * The parameter is a combination of {@link android.os.PowerManager} wake flags.
+     * Use of this method requires {@link android.Manifest.permission#WAKE_LOCK}
+     * permission.
+     * By default, no attempt is made to keep the device awake during playback.
+     * 
+     * @param context the Context to use
+     * @param mode    the power/wake mode to set
+     * @see android.os.PowerManager
+     */
+    public void setWakeMode(Context context, int mode) {
+        boolean washeld = false;
+        if (mWakeLock != null) {
+            if (mWakeLock.isHeld()) {
+                washeld = true;
+                mWakeLock.release();
+            }
+            mWakeLock = null;
+        }
+
+        PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
+        mWakeLock = pm.newWakeLock(mode|PowerManager.ON_AFTER_RELEASE, MediaPlayer.class.getName());
+        mWakeLock.setReferenceCounted(false);
+        if (washeld) {
+            mWakeLock.acquire();
+        }
+    }
+    
+    /**
+     * Control whether we should use the attached SurfaceHolder to keep the
+     * screen on while video playback is occurring.  This is the preferred
+     * method over {@link #setWakeMode} where possible, since it doesn't
+     * require that the application have permission for low-level wake lock
+     * access.
+     * 
+     * @param screenOn Supply true to keep the screen on, false to allow it
+     * to turn off.
+     */
+    public void setScreenOnWhilePlaying(boolean screenOn) {
+        if (mScreenOnWhilePlaying != screenOn) {
+            mScreenOnWhilePlaying = screenOn;
+            updateSurfaceScreenOn();
+        }
+    }
+    
+    private void stayAwake(boolean awake) {
+        if (mWakeLock != null) {
+            if (awake && !mWakeLock.isHeld()) {
+                mWakeLock.acquire();
+            } else if (!awake && mWakeLock.isHeld()) {
+                mWakeLock.release();
+            }
+        }
+        mStayAwake = awake;
+        updateSurfaceScreenOn();
+    }
+    
+    private void updateSurfaceScreenOn() {
+        if (mSurfaceHolder != null) {
+            mSurfaceHolder.setKeepScreenOn(mScreenOnWhilePlaying && mStayAwake);
+        }
+    }
+    
+    /**
+     * Returns the width of the video.
+     * 
+     * @return the width of the video, or 0 if there is no video,
+     * no display surface was set, or prepare()/prepareAsync()
+     * have not completed yet
+     */
+    public native int getVideoWidth();
+    
+    /**
+     * Returns the height of the video.
+     * 
+     * @return the height of the video, or 0 if there is no video,
+     * no display surface was set, or prepare()/prepareAsync()
+     * have not completed yet
+     */
+    public native int getVideoHeight();
+    
+    /**
+     * Checks whether the MediaPlayer is playing.
+     * 
+     * @return true if currently playing, false otherwise
+     */
+    public native boolean isPlaying();
+    
+    /**
+     * Seeks to specified time position.
+     * 
+     * @param msec the offset in milliseconds from the start to seek to
+     * @throws IllegalStateException if the internal player engine has not been
+     * initialized
+     */
+    public native void seekTo(int msec) throws IllegalStateException;
+    
+    /**
+     * Gets the current playback position.
+     * 
+     * @return the current position in milliseconds
+     */
+    public native int getCurrentPosition();
+    
+    /**
+     * Gets the duration of the file.
+     * 
+     * @return the duration in milliseconds
+     */
+    public native int getDuration();
+    
+    /**
+     * Releases resources associated with this MediaPlayer object.
+     * It is considered good practice to call this method when you're
+     * done using the MediaPlayer.
+     */
+    public void release() {
+        stayAwake(false);
+        updateSurfaceScreenOn();
+        mOnPreparedListener = null;
+        mOnBufferingUpdateListener = null;
+        mOnCompletionListener = null;
+        mOnSeekCompleteListener = null;
+        mOnErrorListener = null;
+        mOnVideoSizeChangedListener = null;
+        _release();
+    }
+
+    private native void _release();
+    
+    /**
+     * Resets the MediaPlayer to its uninitialized state. After calling
+     * this method, you will have to initialize it again by setting the
+     * data source and calling prepare().
+     */
+    public void reset() {
+        stayAwake(false);
+        _reset();
+        // make sure none of the listeners get called anymore
+        mEventHandler.removeCallbacksAndMessages(null);
+    }
+    
+    private native void _reset();
+    
+    /**
+     * Sets the audio stream type for this MediaPlayer. See {@link AudioManager}
+     * for a list of stream types.
+     *  
+     * @param streamtype the audio stream type
+     * @see android.media.AudioManager
+     */
+    public native void setAudioStreamType(int streamtype);
+
+    /**
+     * Sets the player to be looping or non-looping.
+     * 
+     * @param looping whether to loop or not
+     */
+    public native void setLooping(boolean looping);
+
+    /**
+     * Checks whether the MediaPlayer is looping or non-looping.
+     * 
+     * @return true if the MediaPlayer is currently looping, false otherwise
+     */
+    public native boolean isLooping();
+
+    /**
+     * Sets the volume on this player. 
+     * This API is recommended for balancing the output of audio streams
+     * within an application. Unless you are writing an application to
+     * control user settings, this API should be used in preference to
+     * {@link AudioManager#setStreamVolume(int, int, int)} which sets the volume of ALL streams of
+     * a particular type. Note that the passed volume values are raw scalars.
+     * UI controls should be scaled logarithmically.
+     *
+     * @param leftVolume left volume scalar
+     * @param rightVolume right volume scalar
+     */
+    public native void setVolume(float leftVolume, float rightVolume);
+
+    /**
+     * Currently not implemented, returns null.
+     * @deprecated
+     * @hide
+     */
+    public native Bitmap getFrameAt(int msec) throws IllegalStateException;
+ 
+    private native final void native_setup(Object mediaplayer_this);
+    private native final void native_finalize();
+    @Override
+    protected void finalize() { native_finalize(); }
+
+    /* Do not change these values without updating their counterparts
+     * in include/media/mediaplayer.h!
+     */
+    private static final int MEDIA_NOP = 0; // interface test message
+    private static final int MEDIA_PREPARED = 1;
+    private static final int MEDIA_PLAYBACK_COMPLETE = 2;
+    private static final int MEDIA_BUFFERING_UPDATE = 3;
+    private static final int MEDIA_SEEK_COMPLETE = 4;
+    private static final int MEDIA_SET_VIDEO_SIZE = 5;
+    private static final int MEDIA_ERROR = 100;
+
+    // error codes from framework that indicate content issues
+    // contained in arg1 of error message
+
+    // Seek not supported - live stream
+    private static final int ERROR_SEEK_NOT_SUPPORTED = 42;
+
+    // A/V interleave exceeds the progressive streaming buffer
+    private static final int ERROR_CONTENT_IS_POORLY_INTERLEAVED = 43;
+
+    // video decoder is falling behind - content is too complex
+    private static final int ERROR_VIDEO_TRACK_IS_FALLING_BEHIND = 44;
+
+    private class EventHandler extends Handler
+    {
+        private MediaPlayer mMediaPlayer;
+
+        public EventHandler(MediaPlayer mp, Looper looper) {
+            super(looper);
+            mMediaPlayer = mp;
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            if (mMediaPlayer.mNativeContext == 0) {
+                Log.w(TAG, "mediaplayer went away with unhandled events");
+                return;
+            }
+            switch(msg.what) {
+            case MEDIA_PREPARED:
+                if (mOnPreparedListener != null)
+                    mOnPreparedListener.onPrepared(mMediaPlayer);
+                return;
+
+            case MEDIA_PLAYBACK_COMPLETE:
+                if (mOnCompletionListener != null)
+                    mOnCompletionListener.onCompletion(mMediaPlayer);
+                stayAwake(false);
+                return;
+
+            case MEDIA_BUFFERING_UPDATE:
+                if (mOnBufferingUpdateListener != null)
+                    mOnBufferingUpdateListener.onBufferingUpdate(mMediaPlayer, msg.arg1);
+                return;
+
+            case MEDIA_SEEK_COMPLETE:
+              if (mOnSeekCompleteListener != null)
+                  mOnSeekCompleteListener.onSeekComplete(mMediaPlayer);
+              return;
+
+            case MEDIA_SET_VIDEO_SIZE:
+              if (mOnVideoSizeChangedListener != null)
+                  mOnVideoSizeChangedListener.onVideoSizeChanged(mMediaPlayer, msg.arg1, msg.arg2);
+              return;
+
+            case MEDIA_ERROR:
+                Log.e(TAG, "Error (" + msg.arg1 + "," + msg.arg2 + ")");
+                boolean error_was_handled = false;
+                if (mOnErrorListener != null) {
+                    error_was_handled = mOnErrorListener.onError(mMediaPlayer, msg.arg1, msg.arg2);
+                }
+                if (mOnCompletionListener != null && ! error_was_handled) {
+                    mOnCompletionListener.onCompletion(mMediaPlayer);
+                }
+                stayAwake(false);
+                return;
+            case MEDIA_NOP: // interface test message - ignore
+                break;
+
+            default:
+                Log.e(TAG, "Unknown message type " + msg.what);
+                return;
+            }
+        }
+    }
+
+    /**
+     * Called from native code when an interesting event happens.  This method
+     * just uses the EventHandler system to post the event back to the main app thread.
+     * We use a weak reference to the original MediaPlayer object so that the native
+     * code is safe from the object disappearing from underneath it.  (This is
+     * the cookie passed to native_setup().)
+     */
+    private static void postEventFromNative(Object mediaplayer_ref,
+                                            int what, int arg1, int arg2, Object obj)
+    {
+        MediaPlayer mp = (MediaPlayer)((WeakReference)mediaplayer_ref).get();
+        if (mp == null) {
+            return;
+        }
+
+        if (mp.mEventHandler != null) {
+            Message m = mp.mEventHandler.obtainMessage(what, arg1, arg2, obj);
+            mp.mEventHandler.sendMessage(m);
+        }
+    }
+
+    /**
+     * Interface definition for a callback to be invoked when the media
+     * source is ready for playback.
+     */
+    public interface OnPreparedListener
+    {
+        /**
+         * Called when the media file is ready for playback.
+         * 
+         * @param mp the MediaPlayer that is ready for playback
+         */
+        void onPrepared(MediaPlayer mp);
+    }
+
+    /**
+     * Register a callback to be invoked when the media source is ready
+     * for playback.
+     *
+     * @param l the callback that will be run
+     */
+    public void setOnPreparedListener(OnPreparedListener l)
+    {
+        mOnPreparedListener = l;
+    }
+
+    private OnPreparedListener mOnPreparedListener;
+
+    /**
+     * Interface definition for a callback to be invoked when playback of
+     * a media source has completed.
+     */
+    public interface OnCompletionListener
+    {
+        /**
+         * Called when the end of a media source is reached during playback.
+         * 
+         * @param mp the MediaPlayer that reached the end of the file
+         */
+        void onCompletion(MediaPlayer mp);
+    }
+
+    /**
+     * Register a callback to be invoked when the end of a media source
+     * has been reached during playback.
+     *
+     * @param l the callback that will be run
+     */
+    public void setOnCompletionListener(OnCompletionListener l)
+    {
+        mOnCompletionListener = l;
+    }
+
+    private OnCompletionListener mOnCompletionListener;
+
+    /**
+     * Interface definition of a callback to be invoked indicating buffering
+     * status of a media resource being streamed over the network.
+     */
+    public interface OnBufferingUpdateListener
+    {
+        /**
+         * Called to update status in buffering a media stream.
+         * 
+         * @param mp      the MediaPlayer the update pertains to
+         * @param percent the percentage (0-100) of the buffer
+         *                that has been filled thus far
+         */
+        void onBufferingUpdate(MediaPlayer mp, int percent);
+    }
+   
+    /**
+     * Register a callback to be invoked when the status of a network
+     * stream's buffer has changed.
+     *
+     * @param l the callback that will be run
+     */
+    public void setOnBufferingUpdateListener(OnBufferingUpdateListener l)
+    {
+        mOnBufferingUpdateListener = l;
+    }
+
+    private OnBufferingUpdateListener mOnBufferingUpdateListener;
+    
+    /**
+     * Interface definition of a callback to be invoked indicating
+     * the completion of a seek operation.
+     */
+    public interface OnSeekCompleteListener
+    {
+        /**
+         * Called to indicate the completion of a seek operation.
+         * 
+         * @param mp the MediaPlayer that issued the seek operation
+         */
+        public void onSeekComplete(MediaPlayer mp);
+    }
+    
+    /**
+     * Register a callback to be invoked when a seek operation has been
+     * completed.
+     * 
+     * @param l the callback that will be run
+     */
+    public void setOnSeekCompleteListener(OnSeekCompleteListener l)
+    {
+        mOnSeekCompleteListener = l;
+    }
+    
+    private OnSeekCompleteListener mOnSeekCompleteListener;
+
+    /**
+     * Interface definition of a callback to be invoked when the
+     * video size is first known or updated
+     * FIXME: Unhide this API after approval
+     * @hide
+     */
+    public interface OnVideoSizeChangedListener
+    {
+        /**
+         * Called to indicate the video size
+         * 
+         * @param mp        the MediaPlayer associated with this callback
+         * @param width     the width of the video
+         * @param height    the height of the video
+         * @hide
+         */
+        public void onVideoSizeChanged(MediaPlayer mp, int width, int height);
+    }
+    
+    /**
+     * Register a callback to be invoked when the video size is
+     * known or updated.
+     * 
+     * @param l the callback that will be run
+     * @hide
+     */
+    public void setOnVideoSizeChangedListener(OnVideoSizeChangedListener l)
+    {
+        mOnVideoSizeChangedListener = l;
+    }
+    
+    private OnVideoSizeChangedListener mOnVideoSizeChangedListener;
+
+    /* Do not change these values without updating their counterparts
+     * in include/media/mediaplayer.h!
+     */
+    /** Unspecified media player error.
+     * @see android.media.MediaPlayer.OnErrorListener
+     */
+    public static final int MEDIA_ERROR_UNKNOWN = 1;
+    /** Media server died. In this case, the application must release the
+     * MediaPlayer object and instantiate a new one. 
+     * @see android.media.MediaPlayer.OnErrorListener
+     */
+    public static final int MEDIA_ERROR_SERVER_DIED = 100;
+    
+
+    /**
+     * Interface definition of a callback to be invoked when there
+     * has been an error during an asynchronous operation (other errors
+     * will throw exceptions at method call time).
+     */
+    public interface OnErrorListener
+    {
+        /**
+         * Called to indicate an error.
+         * 
+         * @param mp      the MediaPlayer the error pertains to
+         * @param what    the type of error that has occurred:
+         * <ul>
+         * <li>{@link #MEDIA_ERROR_UNKNOWN}
+         * <li>{@link #MEDIA_ERROR_SERVER_DIED}
+         * </ul>
+         * @param extra   an extra code, specific to the error type
+         * @return True if the method handled the error, false if it didn't.
+         * Returning false, or not having an OnErrorListener at all, will
+         * cause the OnCompletionListener to be called.
+         */
+        boolean onError(MediaPlayer mp, int what, int extra);
+    }
+   
+    /**
+     * Register a callback to be invoked when an error has happened
+     * during an asynchronous operation.
+     * 
+     * @param l the callback that will be run
+     */
+    public void setOnErrorListener(OnErrorListener l)
+    {
+        mOnErrorListener = l;
+    }
+
+    private OnErrorListener mOnErrorListener;
+}
diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java
new file mode 100644
index 0000000..4906cbb
--- /dev/null
+++ b/media/java/android/media/MediaRecorder.java
@@ -0,0 +1,491 @@
+/*
+ * 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.
+ */
+
+package android.media;
+
+import android.hardware.Camera;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.util.Log;
+import android.view.Surface;
+import java.io.IOException;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.FileDescriptor;
+import java.lang.ref.WeakReference;
+
+/**
+ * Used to record audio and video. The recording control is based on a
+ * simple state machine (see below).
+ *
+ * <p><img src="{@docRoot}images/mediarecorder_state_diagram.gif" border="0" />
+ * </p>
+ *
+ * <p>A common case of using MediaRecorder to record audio works as follows:
+ *
+ * <pre>MediaRecorder recorder = new MediaRecorder();
+ * recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
+ * recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
+ * recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
+ * recorder.setOutputFile(PATH_NAME);
+ * recorder.prepare();
+ * recorder.start();   // Recording is now started
+ * ...
+ * recorder.stop();
+ * recorder.reset();   // You can reuse the object by going back to setAudioSource() step
+ * recorder.release(); // Now the object cannot be reused
+ * </pre>
+ *
+ * <p>See the <a href="{@docRoot}guide/topics/media/index.html">Audio and Video</a>
+ * documentation for additional help with using MediaRecorder.
+ */
+public class MediaRecorder
+{
+    static {
+        System.loadLibrary("media_jni");
+    }
+    private final static String TAG = "MediaRecorder";
+
+    // The two fields below are accessed by native methods
+    @SuppressWarnings("unused")
+    private int mNativeContext;
+
+    @SuppressWarnings("unused")
+    private Surface mSurface;
+
+    private String mPath;
+    private FileDescriptor mFd;
+    private EventHandler mEventHandler;
+    private OnErrorListener mOnErrorListener;
+
+    /**
+     * Default constructor.
+     */
+    public MediaRecorder() {
+
+        Looper looper;
+        if ((looper = Looper.myLooper()) != null) {
+            mEventHandler = new EventHandler(this, looper);
+        } else if ((looper = Looper.getMainLooper()) != null) {
+            mEventHandler = new EventHandler(this, looper);
+        } else {
+            mEventHandler = null;
+        }
+
+        /* Native setup requires a weak reference to our object.
+         * It's easier to create it here than in C++.
+         */
+        native_setup(new WeakReference<MediaRecorder>(this));
+    }
+
+    /**
+     * Sets a Camera to use for recording. Use this function to switch
+     * quickly between preview and capture mode without a teardown of
+     * the camera object. Must call before prepare().
+     *
+     * @param c the Camera to use for recording
+     */
+    public native void setCamera(Camera c);
+
+    /**
+     * Sets a Surface to show a preview of recorded media (video). Calls this
+     * before prepare() to make sure that the desirable preview display is
+     * set.
+     *
+     * @param sv the Surface to use for the preview
+     */
+    public void setPreviewDisplay(Surface sv) {
+        mSurface = sv;
+    }
+
+    /**
+     * Defines the audio source. These constants are used with
+     * {@link MediaRecorder#setAudioSource(int)}.
+     */
+    public final class AudioSource {
+      /* Do not change these values without updating their counterparts
+       * in include/media/mediarecorder.h!
+       */
+        private AudioSource() {}
+        public static final int DEFAULT = 0;
+        /** Microphone audio source */
+        public static final int MIC = 1;
+    }
+
+    /**
+     * Defines the video source. These constants are used with
+     * {@link MediaRecorder#setVideoSource(int)}.
+     */
+    public final class VideoSource {
+      /* Do not change these values without updating their counterparts
+       * in include/media/mediarecorder.h!
+       */
+        private VideoSource() {}
+        public static final int DEFAULT = 0;
+        /** Camera video source */
+        public static final int CAMERA = 1;
+    }
+
+    /**
+     * Defines the output format. These constants are used with
+     * {@link MediaRecorder#setOutputFormat(int)}.
+     */
+    public final class OutputFormat {
+      /* Do not change these values without updating their counterparts
+       * in include/media/mediarecorder.h!
+       */
+        private OutputFormat() {}
+        public static final int DEFAULT = 0;
+        /** 3GPP media file format*/
+        public static final int THREE_GPP = 1;
+        /** MPEG4 media file format*/
+        public static final int MPEG_4 = 2;
+        /** Raw AMR file format */
+        public static final int RAW_AMR = 3;
+    };
+
+    /**
+     * Defines the audio encoding. These constants are used with
+     * {@link MediaRecorder#setAudioEncoder(int)}.
+     */
+    public final class AudioEncoder {
+      /* Do not change these values without updating their counterparts
+       * in include/media/mediarecorder.h!
+       */
+        private AudioEncoder() {}
+        public static final int DEFAULT = 0;
+        /** AMR (Narrowband) audio codec */
+        public static final int AMR_NB = 1;
+        //public static final AAC = 2;  currently unsupported
+    }
+
+    /**
+     * Defines the video encoding. These constants are used with
+     * {@link MediaRecorder#setVideoEncoder(int)}.
+     */
+    public final class VideoEncoder {
+      /* Do not change these values without updating their counterparts
+       * in include/media/mediarecorder.h!
+       */
+        private VideoEncoder() {}
+        public static final int DEFAULT = 0;
+        public static final int H263 = 1;
+        public static final int H264 = 2;
+        public static final int MPEG_4_SP = 3;
+    }
+
+    /**
+     * Sets the audio source to be used for recording. If this method is not
+     * called, the output file will not contain an audio track. The source needs
+     * to be specified before setting recording-parameters or encoders. Call
+     * this only before setOutputFormat().
+     *
+     * @param audio_source the audio source to use
+     * @throws IllegalStateException if it is called after setOutputFormat()
+     * @see android.media.MediaRecorder.AudioSource
+     */
+    public native void setAudioSource(int audio_source)
+            throws IllegalStateException;
+
+    /**
+     * Sets the video source to be used for recording. If this method is not
+     * called, the output file will not contain an video track. The source needs
+     * to be specified before setting recording-parameters or encoders. Call
+     * this only before setOutputFormat().
+     *
+     * @param video_source the video source to use
+     * @throws IllegalStateException if it is called after setOutputFormat()
+     * @see android.media.MediaRecorder.VideoSource
+     */
+    public native void setVideoSource(int video_source)
+            throws IllegalStateException;
+
+    /**
+     * Sets the format of the output file produced during recording. Call this
+     * after setAudioSource()/setVideoSource() but before prepare().
+     *
+     * @param output_format the output format to use. The output format
+     * needs to be specified before setting recording-parameters or encoders.
+     * @throws IllegalStateException if it is called after prepare() or before
+     * setAudioSource()/setVideoSource().
+     * @see android.media.MediaRecorder.OutputFormat
+     */
+    public native void setOutputFormat(int output_format)
+            throws IllegalStateException;
+
+    /**
+     * Sets the width and height of the video to be captured.  Must be called
+     * after setVideoSource(). Call this after setOutFormat() but before
+     * prepare().
+     *
+     * @param width the width of the video to be captured
+     * @param height the height of the video to be captured
+     * @throws IllegalStateException if it is called after
+     * prepare() or before setOutputFormat()
+     */
+    public native void setVideoSize(int width, int height)
+            throws IllegalStateException;
+
+    /**
+     * Sets the frame rate of the video to be captured.  Must be called
+     * after setVideoSource(). Call this after setOutFormat() but before
+     * prepare().
+     *
+     * @param rate the number of frames per second of video to capture
+     * @throws IllegalStateException if it is called after
+     * prepare() or before setOutputFormat().
+     *
+     * NOTE: On some devices that have auto-frame rate, this sets the
+     * maximum frame rate, not a constant frame rate. Actual frame rate
+     * will vary according to lighting conditions.
+     */
+    public native void setVideoFrameRate(int rate) throws IllegalStateException;
+
+    /**
+     * Sets the audio encoder to be used for recording. If this method is not
+     * called, the output file will not contain an audio track. Call this after
+     * setOutputFormat() but before prepare().
+     *
+     * @param audio_encoder the audio encoder to use.
+     * @throws IllegalStateException if it is called before
+     * setOutputFormat() or after prepare().
+     * @see android.media.MediaRecorder.AudioEncoder
+     */
+    public native void setAudioEncoder(int audio_encoder)
+            throws IllegalStateException;
+
+    /**
+     * Sets the video encoder to be used for recording. If this method is not
+     * called, the output file will not contain an video track. Call this after
+     * setOutputFormat() and before prepare().
+     *
+     * @param video_encoder the video encoder to use.
+     * @throws IllegalStateException if it is called before
+     * setOutputFormat() or after prepare()
+     * @see android.media.MediaRecorder.VideoEncoder
+     */
+    public native void setVideoEncoder(int video_encoder)
+            throws IllegalStateException;
+
+    /**
+     * Pass in the file descriptor of the file to be written. Call this after
+     * setOutputFormat() but before prepare().
+     *
+     * @param fd an open file descriptor to be written into.
+     * @throws IllegalStateException if it is called before
+     * setOutputFormat() or after prepare()
+     */
+    public void setOutputFile(FileDescriptor fd) throws IllegalStateException
+    {
+        mPath = null;
+        mFd = fd;
+    }
+
+    /**
+     * Sets the path of the output file to be produced. Call this after
+     * setOutputFormat() but before prepare().
+     *
+     * @param path The pathname to use.
+     * @throws IllegalStateException if it is called before
+     * setOutputFormat() or after prepare()
+     */
+    public void setOutputFile(String path) throws IllegalStateException
+    {
+        mFd = null;
+        mPath = path;
+    }
+
+    // native implementation
+    private native void _setOutputFile(FileDescriptor fd, long offset, long length)
+        throws IllegalStateException, IOException;
+    private native void _prepare() throws IllegalStateException, IOException;
+
+    /**
+     * Prepares the recorder to begin capturing and encoding data. This method
+     * must be called after setting up the desired audio and video sources,
+     * encoders, file format, etc., but before start().
+     *
+     * @throws IllegalStateException if it is called after
+     * start() or before setOutputFormat().
+     * @throws IOException if prepare fails otherwise.
+     */
+    public void prepare() throws IllegalStateException, IOException
+    {
+        if (mPath != null) {
+            FileOutputStream fos = new FileOutputStream(mPath);
+            try {
+                _setOutputFile(fos.getFD(), 0, 0);
+            } finally {
+                fos.close();
+            }
+        } else if (mFd != null) {
+            _setOutputFile(mFd, 0, 0);
+        } else {
+            throw new IOException("No valid output file");
+        }
+        _prepare();
+    }
+
+    /**
+     * Begins capturing and encoding data to the file specified with
+     * setOutputFile(). Call this after prepare().
+     *
+     * @throws IllegalStateException if it is called before
+     * prepare().
+     */
+    public native void start() throws IllegalStateException;
+
+    /**
+     * Stops recording. Call this after start(). Once recording is stopped,
+     * you will have to configure it again as if it has just been constructed.
+     *
+     * @throws IllegalStateException if it is called before start()
+     */
+    public native void stop() throws IllegalStateException;
+
+    /**
+     * Restarts the MediaRecorder to its idle state. After calling
+     * this method, you will have to configure it again as if it had just been
+     * constructed.
+     */
+    public void reset() {
+        native_reset();
+
+        // make sure none of the listeners get called anymore
+        mEventHandler.removeCallbacksAndMessages(null);
+    }
+
+    private native void native_reset();
+
+    /**
+     * Returns the maximum absolute amplitude that was sampled since the last
+     * call to this method. Call this only after the setAudioSource().
+     *
+     * @return the maximum absolute amplitude measured since the last call, or
+     * 0 when called for the first time
+     * @throws IllegalStateException if it is called before
+     * the audio source has been set.
+     */
+    public native int getMaxAmplitude() throws IllegalStateException;
+
+    /* Do not change this value without updating its counterpart
+     * in include/media/mediarecorder.h!
+     */
+    /** Unspecified media recorder error.
+     * @see android.media.MediaRecorder.OnErrorListener
+     */
+    public static final int MEDIA_RECORDER_ERROR_UNKNOWN = 1;
+
+    /**
+     * Interface definition for a callback to be invoked when an error
+     * occurs while recording.
+     */
+    public interface OnErrorListener
+    {
+        /**
+         * Called when an error occurs while recording.
+         * 
+         * @param mr the MediaRecorder that encountered the error
+         * @param what    the type of error that has occurred:
+         * <ul>
+         * <li>{@link #MEDIA_RECORDER_ERROR_UNKNOWN}
+         * </ul>
+         * @param extra   an extra code, specific to the error type
+         */
+        void onError(MediaRecorder mr, int what, int extra);
+    }
+
+    /**
+     * Register a callback to be invoked when an error occurs while
+     * recording.
+     *
+     * @param l the callback that will be run
+     */
+    public void setOnErrorListener(OnErrorListener l)
+    {
+        mOnErrorListener = l;
+    }
+
+    private class EventHandler extends Handler
+    {
+        private MediaRecorder mMediaRecorder;
+
+        public EventHandler(MediaRecorder mr, Looper looper) {
+            super(looper);
+            mMediaRecorder = mr;
+        }
+
+        /* Do not change this value without updating its counterpart
+         * in include/media/mediarecorder.h!
+         */
+        private static final int MEDIA_RECORDER_EVENT_ERROR = 1;
+
+        @Override
+        public void handleMessage(Message msg) {
+            if (mMediaRecorder.mNativeContext == 0) {
+                Log.w(TAG, "mediarecorder went away with unhandled events");
+                return;
+            }
+            switch(msg.what) {
+            case MEDIA_RECORDER_EVENT_ERROR:
+                if (mOnErrorListener != null)
+                    mOnErrorListener.onError(mMediaRecorder, msg.arg1, msg.arg2);
+
+                return;
+
+            default:
+                Log.e(TAG, "Unknown message type " + msg.what);
+                return;
+            }
+        }
+    }
+
+    /**
+     * Called from native code when an interesting event happens.  This method
+     * just uses the EventHandler system to post the event back to the main app thread.
+     * We use a weak reference to the original MediaRecorder object so that the native
+     * code is safe from the object disappearing from underneath it.  (This is
+     * the cookie passed to native_setup().)
+     */
+    private static void postEventFromNative(Object mediarecorder_ref,
+                                            int what, int arg1, int arg2, Object obj)
+    {
+        MediaRecorder mr = (MediaRecorder)((WeakReference)mediarecorder_ref).get();
+        if (mr == null) {
+            return;
+        }
+
+        if (mr.mEventHandler != null) {
+            Message m = mr.mEventHandler.obtainMessage(what, arg1, arg2, obj);
+            mr.mEventHandler.sendMessage(m);
+        }
+    }
+
+    /**
+     * Releases resources associated with this MediaRecorder object.
+     * It is good practice to call this method when you're done
+     * using the MediaRecorder.
+     */
+    public native void release();
+
+    private native final void native_setup(Object mediarecorder_this) throws IllegalStateException;
+
+    private native final void native_finalize();
+
+    @Override
+    protected void finalize() { native_finalize(); }
+}
diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java
new file mode 100644
index 0000000..fc8476d
--- /dev/null
+++ b/media/java/android/media/MediaScanner.java
@@ -0,0 +1,1352 @@
+/*
+ * 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.
+ */
+
+package android.media;
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.IContentProvider;
+import android.content.ContentUris;
+import android.database.Cursor;
+import android.database.SQLException;
+import android.graphics.BitmapFactory;
+import android.net.Uri;
+import android.os.Process;
+import android.os.RemoteException;
+import android.os.SystemProperties;
+import android.provider.MediaStore;
+import android.provider.Settings;
+import android.provider.MediaStore.Audio;
+import android.provider.MediaStore.Images;
+import android.provider.MediaStore.Video;
+import android.provider.MediaStore.Audio.Genres;
+import android.provider.MediaStore.Audio.Playlists;
+import android.sax.Element;
+import android.sax.ElementListener;
+import android.sax.RootElement;
+import android.text.TextUtils;
+import android.util.Config;
+import android.util.Log;
+import android.util.Xml;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+
+import java.io.*;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+
+/**
+ * Internal service that no-one should use directly.
+ *
+ * {@hide}
+ */
+public class MediaScanner
+{    
+    static {
+        System.loadLibrary("media_jni");
+    }
+
+    private final static String TAG = "MediaScanner";
+
+    private static final String[] AUDIO_PROJECTION = new String[] {
+            Audio.Media._ID, // 0
+            Audio.Media.DATA, // 1
+            Audio.Media.DATE_MODIFIED, // 2
+    };
+    
+    private static final int ID_AUDIO_COLUMN_INDEX = 0;
+    private static final int PATH_AUDIO_COLUMN_INDEX = 1;
+    private static final int DATE_MODIFIED_AUDIO_COLUMN_INDEX = 2;
+ 
+    private static final String[] VIDEO_PROJECTION = new String[] {
+            Video.Media._ID, // 0
+            Video.Media.DATA, // 1
+            Video.Media.DATE_MODIFIED, // 2
+    };
+    
+    private static final int ID_VIDEO_COLUMN_INDEX = 0;
+    private static final int PATH_VIDEO_COLUMN_INDEX = 1;
+    private static final int DATE_MODIFIED_VIDEO_COLUMN_INDEX = 2;
+
+    private static final String[] IMAGES_PROJECTION = new String[] {
+            Images.Media._ID, // 0
+            Images.Media.DATA, // 1
+            Images.Media.DATE_MODIFIED, // 2
+    };
+    
+    private static final int ID_IMAGES_COLUMN_INDEX = 0;
+    private static final int PATH_IMAGES_COLUMN_INDEX = 1;
+    private static final int DATE_MODIFIED_IMAGES_COLUMN_INDEX = 2;
+    
+    private static final String[] PLAYLISTS_PROJECTION = new String[] {
+            Audio.Playlists._ID, // 0
+            Audio.Playlists.DATA, // 1
+            Audio.Playlists.DATE_MODIFIED, // 2
+    };
+
+    private static final String[] PLAYLIST_MEMBERS_PROJECTION = new String[] {
+            Audio.Playlists.Members.PLAYLIST_ID, // 0
+     };
+
+    private static final int ID_PLAYLISTS_COLUMN_INDEX = 0;
+    private static final int PATH_PLAYLISTS_COLUMN_INDEX = 1;
+    private static final int DATE_MODIFIED_PLAYLISTS_COLUMN_INDEX = 2;
+
+    private static final String[] GENRE_LOOKUP_PROJECTION = new String[] {
+            Audio.Genres._ID, // 0
+            Audio.Genres.NAME, // 1
+    };
+
+    private static final String RINGTONES_DIR = "/ringtones/";
+    private static final String NOTIFICATIONS_DIR = "/notifications/";
+    private static final String ALARMS_DIR = "/alarms/";
+    private static final String MUSIC_DIR = "/music/";
+    private static final String PODCAST_DIR = "/podcasts/";
+    
+    private static final String[] ID3_GENRES = {
+        // ID3v1 Genres
+        "Blues",
+        "Classic Rock",
+        "Country",
+        "Dance",
+        "Disco",
+        "Funk",
+        "Grunge",
+        "Hip-Hop",
+        "Jazz",
+        "Metal",
+        "New Age",
+        "Oldies",
+        "Other",
+        "Pop",
+        "R&B",
+        "Rap",
+        "Reggae",
+        "Rock",
+        "Techno",
+        "Industrial",
+        "Alternative",
+        "Ska",
+        "Death Metal",
+        "Pranks",
+        "Soundtrack",
+        "Euro-Techno",
+        "Ambient",
+        "Trip-Hop",
+        "Vocal",
+        "Jazz+Funk",
+        "Fusion",
+        "Trance",
+        "Classical",
+        "Instrumental",
+        "Acid",
+        "House",
+        "Game",
+        "Sound Clip",
+        "Gospel",
+        "Noise",
+        "AlternRock",
+        "Bass",
+        "Soul",
+        "Punk",
+        "Space",
+        "Meditative",
+        "Instrumental Pop",
+        "Instrumental Rock",
+        "Ethnic",
+        "Gothic",
+        "Darkwave",
+        "Techno-Industrial",
+        "Electronic",
+        "Pop-Folk",
+        "Eurodance",
+        "Dream",
+        "Southern Rock",
+        "Comedy",
+        "Cult",
+        "Gangsta",
+        "Top 40",
+        "Christian Rap",
+        "Pop/Funk",
+        "Jungle",
+        "Native American",
+        "Cabaret",
+        "New Wave",
+        "Psychadelic",
+        "Rave",
+        "Showtunes",
+        "Trailer",
+        "Lo-Fi",
+        "Tribal",
+        "Acid Punk",
+        "Acid Jazz",
+        "Polka",
+        "Retro",
+        "Musical",
+        "Rock & Roll",
+        "Hard Rock",
+        // The following genres are Winamp extensions
+        "Folk",
+        "Folk-Rock",
+        "National Folk",
+        "Swing",
+        "Fast Fusion",
+        "Bebob",
+        "Latin",
+        "Revival",
+        "Celtic",
+        "Bluegrass",
+        "Avantgarde",
+        "Gothic Rock",
+        "Progressive Rock",
+        "Psychedelic Rock",
+        "Symphonic Rock",
+        "Slow Rock",
+        "Big Band",
+        "Chorus",
+        "Easy Listening",
+        "Acoustic",
+        "Humour",
+        "Speech",
+        "Chanson",
+        "Opera",
+        "Chamber Music",
+        "Sonata",
+        "Symphony",
+        "Booty Bass",
+        "Primus",
+        "Porn Groove",
+        "Satire",
+        "Slow Jam",
+        "Club",
+        "Tango",
+        "Samba",
+        "Folklore",
+        "Ballad",
+        "Power Ballad",
+        "Rhythmic Soul",
+        "Freestyle",
+        "Duet",
+        "Punk Rock",
+        "Drum Solo",
+        "A capella",
+        "Euro-House",
+        "Dance Hall"
+    };
+
+    private int mNativeContext;
+    private Context mContext;
+    private IContentProvider mMediaProvider;
+    private Uri mAudioUri;
+    private Uri mVideoUri;
+    private Uri mImagesUri;
+    private Uri mThumbsUri;
+    private Uri mGenresUri;
+    private Uri mPlaylistsUri;
+    private boolean mProcessPlaylists, mProcessGenres;
+
+    // used when scanning the image database so we know whether we have to prune
+    // old thumbnail files
+    private int mOriginalCount;
+    /** Whether the scanner has set a default sound for the ringer ringtone. */
+    private boolean mDefaultRingtoneSet;
+    /** Whether the scanner has set a default sound for the notification ringtone. */
+    private boolean mDefaultNotificationSet;
+    /** The filename for the default sound for the ringer ringtone. */
+    private String mDefaultRingtoneFilename;
+    /** The filename for the default sound for the notification ringtone. */
+    private String mDefaultNotificationFilename;
+    /**
+     * The prefix for system properties that define the default sound for
+     * ringtones. Concatenate the name of the setting from Settings
+     * to get the full system property.
+     */
+    private static final String DEFAULT_RINGTONE_PROPERTY_PREFIX = "ro.config.";
+    
+    // set to true if file path comparisons should be case insensitive.
+    // this should be set when scanning files on a case insensitive file system.
+    private boolean mCaseInsensitivePaths;
+    
+    private BitmapFactory.Options mBitmapOptions = new BitmapFactory.Options();
+
+    private static class FileCacheEntry {
+        Uri mTableUri;
+        long mRowId;
+        String mPath;
+        long mLastModified;
+        boolean mSeenInFileSystem;
+        boolean mLastModifiedChanged;
+        
+        FileCacheEntry(Uri tableUri, long rowId, String path, long lastModified) {
+            mTableUri = tableUri;
+            mRowId = rowId;
+            mPath = path;
+            mLastModified = lastModified;
+            mSeenInFileSystem = false;
+            mLastModifiedChanged = false;
+        }
+
+        @Override
+        public String toString() {
+            return mPath;
+        }
+    }
+    
+    // hashes file path to FileCacheEntry.  
+    // path should be lower case if mCaseInsensitivePaths is true
+    private HashMap<String, FileCacheEntry> mFileCache; 
+
+    private ArrayList<FileCacheEntry> mPlayLists;
+    private HashMap<String, Uri> mGenreCache;
+
+
+    public MediaScanner(Context c) {
+        native_setup();
+        mContext = c;
+        mBitmapOptions.inSampleSize = 1;
+        mBitmapOptions.inJustDecodeBounds = true;
+        
+        setDefaultRingtoneFileNames();
+    }
+
+    private void setDefaultRingtoneFileNames() {
+        mDefaultRingtoneFilename = SystemProperties.get(DEFAULT_RINGTONE_PROPERTY_PREFIX
+                + Settings.System.RINGTONE);
+        mDefaultNotificationFilename = SystemProperties.get(DEFAULT_RINGTONE_PROPERTY_PREFIX
+                + Settings.System.NOTIFICATION_SOUND);
+    }
+    
+    private MyMediaScannerClient mClient = new MyMediaScannerClient();
+    
+    private class MyMediaScannerClient implements MediaScannerClient {
+    
+        private String mArtist;
+        private String mAlbumArtist;    // use this if mArtist is missing
+        private String mAlbum;
+        private String mTitle;
+        private String mComposer;
+        private String mGenre;
+        private String mMimeType;
+        private int mFileType;
+        private int mTrack;
+        private int mYear;
+        private int mDuration;
+        private String mPath;
+        private long mLastModified;
+        private long mFileSize;
+    
+        public FileCacheEntry beginFile(String path, String mimeType, long lastModified, long fileSize) {
+            
+            // special case certain file names
+            // I use regionMatches() instead of substring() below 
+            // to avoid memory allocation
+            int lastSlash = path.lastIndexOf('/');
+            if (lastSlash >= 0 && lastSlash + 2 < path.length()) {
+                // ignore those ._* files created by MacOS
+                if (path.regionMatches(lastSlash + 1, "._", 0, 2)) {
+                    return null;
+                }
+                
+                // ignore album art files created by Windows Media Player:
+                // Folder.jpg, AlbumArtSmall.jpg, AlbumArt_{...}_Large.jpg and AlbumArt_{...}_Small.jpg
+                if (path.regionMatches(true, path.length() - 4, ".jpg", 0, 4)) {
+                    if (path.regionMatches(true, lastSlash + 1, "AlbumArt_{", 0, 10) ||
+                            path.regionMatches(true, lastSlash + 1, "AlbumArt.", 0, 9)) {
+                        return null;
+                    }
+                    int length = path.length() - lastSlash - 1;
+                    if ((length == 17 && path.regionMatches(true, lastSlash + 1, "AlbumArtSmall", 0, 13)) ||
+                            (length == 10 && path.regionMatches(true, lastSlash + 1, "Folder", 0, 6))) {
+                        return null;
+                    }
+                }
+            }
+            
+            mMimeType = null;
+            // try mimeType first, if it is specified
+            if (mimeType != null) {
+                mFileType = MediaFile.getFileTypeForMimeType(mimeType);
+                if (mFileType != 0) {
+                    mMimeType = mimeType;
+                }
+            }
+            mFileSize = fileSize;
+
+            // if mimeType was not specified, compute file type based on file extension.
+            if (mMimeType == null) {
+                MediaFile.MediaFileType mediaFileType = MediaFile.getFileType(path);
+                if (mediaFileType != null) {
+                    mFileType = mediaFileType.fileType;
+                    mMimeType = mediaFileType.mimeType;
+                }
+            }
+            
+            String key = path;
+            if (mCaseInsensitivePaths) {
+                key = path.toLowerCase();
+            }
+            FileCacheEntry entry = mFileCache.get(key);
+            if (entry == null) {
+                entry = new FileCacheEntry(null, 0, path, 0);
+                mFileCache.put(key, entry);
+            }
+            entry.mSeenInFileSystem = true;
+            
+            // add some slack to avoid a rounding error
+            long delta = lastModified - entry.mLastModified;
+            if (delta > 1 || delta < -1) {
+                entry.mLastModified = lastModified;
+                entry.mLastModifiedChanged = true;
+            }
+                           
+            if (mProcessPlaylists && MediaFile.isPlayListFileType(mFileType)) {
+                mPlayLists.add(entry);
+                // we don't process playlists in the main scan, so return null
+                return null;
+            }
+            
+            // clear all the metadata
+            mArtist = null;
+            mAlbumArtist = null;
+            mAlbum = null;
+            mTitle = null;
+            mComposer = null;
+            mGenre = null;
+            mTrack = 0;
+            mYear = 0;
+            mDuration = 0;
+            mPath = path;
+            mLastModified = lastModified;
+            
+            return entry;
+        }
+        
+        public void scanFile(String path, long lastModified, long fileSize) {
+            doScanFile(path, null, lastModified, fileSize, false);
+        }
+
+        public void scanFile(String path, String mimeType, long lastModified, long fileSize) {
+            doScanFile(path, mimeType, lastModified, fileSize, false);
+        }
+
+        public Uri doScanFile(String path, String mimeType, long lastModified, long fileSize, boolean scanAlways) {
+            Uri result = null;
+//            long t1 = System.currentTimeMillis();
+            try {
+                FileCacheEntry entry = beginFile(path, mimeType, lastModified, fileSize);
+                // rescan for metadata if file was modified since last scan
+                if (entry != null && (entry.mLastModifiedChanged || scanAlways)) {
+                    boolean ringtones = (path.indexOf(RINGTONES_DIR) > 0);
+                    boolean notifications = (path.indexOf(NOTIFICATIONS_DIR) > 0);
+                    boolean alarms = (path.indexOf(ALARMS_DIR) > 0);
+                    boolean podcasts = (path.indexOf(PODCAST_DIR) > 0);
+                    boolean music = (path.indexOf(MUSIC_DIR) > 0) ||
+                        (!ringtones && !notifications && !alarms && !podcasts);
+
+                    if (mFileType == MediaFile.FILE_TYPE_MP3 ||
+                            mFileType == MediaFile.FILE_TYPE_MP4 ||
+                            mFileType == MediaFile.FILE_TYPE_M4A ||
+                            mFileType == MediaFile.FILE_TYPE_3GPP ||
+                            mFileType == MediaFile.FILE_TYPE_3GPP2 ||
+                            mFileType == MediaFile.FILE_TYPE_OGG ||
+                            mFileType == MediaFile.FILE_TYPE_MID ||
+                            mFileType == MediaFile.FILE_TYPE_WMA) {
+                        // we only extract metadata from MP3, M4A, OGG, MID and WMA files.
+                        // check MP4 files, to determine if they contain only audio.
+                        processFile(path, mimeType, this);
+                    } else if (MediaFile.isImageFileType(mFileType)) {
+                        // we used to compute the width and height but it's not worth it
+                    }
+                    
+                    result = endFile(entry, ringtones, notifications, alarms, music, podcasts);
+                }
+            } catch (RemoteException e) {
+                Log.e(TAG, "RemoteException in MediaScanner.scanFile()", e);
+            }
+//            long t2 = System.currentTimeMillis();
+//            Log.v(TAG, "scanFile: " + path + " took " + (t2-t1));
+            return result;
+        }
+
+        private int parseSubstring(String s, int start, int defaultValue) {
+            int length = s.length();
+            if (start == length) return defaultValue;
+
+            char ch = s.charAt(start++);
+            // return defaultValue if we have no integer at all
+            if (ch < '0' || ch > '9') return defaultValue;
+            
+            int result = ch - '0';
+            while (start < length) {
+                ch = s.charAt(start++);
+                if (ch < '0' || ch > '9') return result;
+                result = result * 10 + (ch - '0');
+            }
+            
+            return result;
+        }                                
+                                
+        public void handleStringTag(String name, String value) {
+            if (name.equalsIgnoreCase("title") || name.startsWith("title;")) {
+                mTitle = value.trim();
+            } else if (name.equalsIgnoreCase("artist") || name.startsWith("artist;")) {
+                mArtist = value.trim();
+            } else if (name.equalsIgnoreCase("albumartist") || name.startsWith("albumartist;")) {
+                mAlbumArtist = value.trim();
+            } else if (name.equalsIgnoreCase("album") || name.startsWith("album;")) {
+                mAlbum = value.trim();
+            } else if (name.equalsIgnoreCase("composer") || name.startsWith("composer;")) {
+                mComposer = value.trim();
+            } else if (name.equalsIgnoreCase("genre") || name.startsWith("genre;")) {
+                // handle numeric genres, which PV sometimes encodes like "(20)"
+                if (value.length() > 0) {
+                    int genreCode = -1;
+                    char ch = value.charAt(0);
+                    if (ch == '(') {
+                        genreCode = parseSubstring(value, 1, -1);
+                    } else if (ch >= '0' && ch <= '9') {
+                        genreCode = parseSubstring(value, 0, -1);
+                    }
+                    if (genreCode >= 0 && genreCode < ID3_GENRES.length) {
+                        value = ID3_GENRES[genreCode];
+                    }
+                }
+                mGenre = value;
+            } else if (name.equalsIgnoreCase("year") || name.startsWith("year;")) {
+                mYear = parseSubstring(value, 0, 0);
+            } else if (name.equalsIgnoreCase("tracknumber") || name.startsWith("tracknumber;")) {
+                // track number might be of the form "2/12"
+                // we just read the number before the slash
+                int num = parseSubstring(value, 0, 0);
+                mTrack = (mTrack / 1000) * 1000 + num; 
+            } else if (name.equalsIgnoreCase("discnumber") ||
+                    name.equals("set") || name.startsWith("set;")) {
+                // set number might be of the form "1/3"
+                // we just read the number before the slash
+                int num = parseSubstring(value, 0, 0);
+                mTrack = (num * 1000) + (mTrack % 1000);
+            } else if (name.equalsIgnoreCase("duration")) {
+                mDuration = parseSubstring(value, 0, 0);
+            }
+        }
+        
+        public void setMimeType(String mimeType) {
+            mMimeType = mimeType;
+            mFileType = MediaFile.getFileTypeForMimeType(mimeType);
+        }
+        
+        /**
+         * Formats the data into a values array suitable for use with the Media
+         * Content Provider.
+         * 
+         * @return a map of values
+         */
+        private ContentValues toValues() {
+            ContentValues map = new ContentValues();
+
+            map.put(MediaStore.MediaColumns.DATA, mPath);
+            map.put(MediaStore.MediaColumns.TITLE, mTitle);
+            map.put(MediaStore.MediaColumns.DATE_MODIFIED, mLastModified);
+            map.put(MediaStore.MediaColumns.SIZE, mFileSize);
+            map.put(MediaStore.MediaColumns.MIME_TYPE, mMimeType);
+            
+            if (MediaFile.isVideoFileType(mFileType)) {
+                map.put(Video.Media.ARTIST, (mArtist != null && mArtist.length() > 0 ? mArtist : MediaFile.UNKNOWN_STRING));
+                map.put(Video.Media.ALBUM, (mAlbum != null && mAlbum.length() > 0 ? mAlbum : MediaFile.UNKNOWN_STRING));
+                map.put(Video.Media.DURATION, mDuration);
+                // FIXME - add RESOLUTION
+            } else if (MediaFile.isImageFileType(mFileType)) {
+                // FIXME - add DESCRIPTION
+                // map.put(field, value);
+            } else if (MediaFile.isAudioFileType(mFileType)) {
+                map.put(Audio.Media.ARTIST, (mArtist != null && mArtist.length() > 0 ? mArtist : MediaFile.UNKNOWN_STRING));
+                map.put(Audio.Media.ALBUM, (mAlbum != null && mAlbum.length() > 0 ? mAlbum : MediaFile.UNKNOWN_STRING));
+                map.put(Audio.Media.COMPOSER, mComposer);
+                if (mYear != 0) {
+                    map.put(Audio.Media.YEAR, mYear);
+                }
+                map.put(Audio.Media.TRACK, mTrack);
+                map.put(Audio.Media.DURATION, mDuration);
+            }
+            return map;
+        }
+    
+        private Uri endFile(FileCacheEntry entry, boolean ringtones, boolean notifications,
+                boolean alarms, boolean music, boolean podcasts) 
+                throws RemoteException {
+            // update database
+            Uri tableUri;
+            boolean isAudio = MediaFile.isAudioFileType(mFileType);
+            boolean isVideo = MediaFile.isVideoFileType(mFileType);
+            boolean isImage = MediaFile.isImageFileType(mFileType);
+            if (isVideo) {
+                tableUri = mVideoUri;
+            } else if (isImage) {
+                tableUri = mImagesUri;
+            } else if (isAudio) {
+                tableUri = mAudioUri;
+            } else {
+                // don't add file to database if not audio, video or image
+                return null;
+            }
+            entry.mTableUri = tableUri;
+            
+             // use album artist if artist is missing
+            if (mArtist == null || mArtist.length() == 0) {
+                mArtist = mAlbumArtist;
+            }
+
+            ContentValues values = toValues();
+            String title = values.getAsString(MediaStore.MediaColumns.TITLE);
+            if (TextUtils.isEmpty(title)) {
+                title = values.getAsString(MediaStore.MediaColumns.DATA);
+                // extract file name after last slash
+                int lastSlash = title.lastIndexOf('/');
+                if (lastSlash >= 0) {
+                    lastSlash++;
+                    if (lastSlash < title.length()) {
+                        title = title.substring(lastSlash);
+                    }
+                }
+                // truncate the file extension (if any)
+                int lastDot = title.lastIndexOf('.');
+                if (lastDot > 0) {
+                    title = title.substring(0, lastDot);
+                }
+                values.put(MediaStore.MediaColumns.TITLE, title);
+            }
+            if (isAudio) {
+                values.put(Audio.Media.IS_RINGTONE, ringtones);
+                values.put(Audio.Media.IS_NOTIFICATION, notifications);
+                values.put(Audio.Media.IS_ALARM, alarms);
+                values.put(Audio.Media.IS_MUSIC, music);
+                values.put(Audio.Media.IS_PODCAST, podcasts);
+            } else if (isImage) {
+                // nothing right now
+            }
+            
+            Uri result = null;
+            long rowId = entry.mRowId;
+            if (rowId == 0) {
+                // new file, insert it
+                result = mMediaProvider.insert(tableUri, values);
+                if (result != null) {
+                    rowId = ContentUris.parseId(result);
+                    entry.mRowId = rowId;
+                }
+            } else {
+                // updated file
+                result = ContentUris.withAppendedId(tableUri, rowId);
+                mMediaProvider.update(result, values, null, null);
+            }
+            if (mProcessGenres && mGenre != null) {
+                String genre = mGenre;
+                Uri uri = mGenreCache.get(genre);
+                if (uri == null) {
+                    Cursor cursor = null;
+                    try {
+                        // see if the genre already exists
+                        cursor = mMediaProvider.query(
+                                mGenresUri,
+                                GENRE_LOOKUP_PROJECTION, MediaStore.Audio.Genres.NAME + "=?",
+                                        new String[] { genre }, null);
+                        if (cursor == null || cursor.getCount() == 0) {
+                            // genre does not exist, so create the genre in the genre table
+                            values.clear();
+                            values.put(MediaStore.Audio.Genres.NAME, genre);
+                            uri = mMediaProvider.insert(mGenresUri, values);
+                        } else {
+                            // genre already exists, so compute its Uri
+                            cursor.moveToNext();
+                            uri = ContentUris.withAppendedId(mGenresUri, cursor.getLong(0));
+                        }
+                        if (uri != null) {
+                            uri = Uri.withAppendedPath(uri, Genres.Members.CONTENT_DIRECTORY);
+                            mGenreCache.put(genre, uri);
+                        }
+                    } finally {
+                        // release the cursor if it exists
+                        if (cursor != null) {
+                            cursor.close();
+                        }
+                    }
+                }
+              
+                if (uri != null) {
+                    // add entry to audio_genre_map  
+                    values.clear();
+                    values.put(MediaStore.Audio.Genres.Members.AUDIO_ID, Long.valueOf(rowId));
+                    mMediaProvider.insert(uri, values);
+                }
+            }
+            
+            if (notifications && !mDefaultNotificationSet) {
+                if (TextUtils.isEmpty(mDefaultNotificationFilename) ||
+                        doesPathHaveFilename(entry.mPath, mDefaultNotificationFilename)) {
+                    setSettingIfNotSet(Settings.System.NOTIFICATION_SOUND, tableUri, rowId);
+                    mDefaultNotificationSet = true;
+                }
+            } else if (ringtones && !mDefaultRingtoneSet) {
+                if (TextUtils.isEmpty(mDefaultRingtoneFilename) ||
+                        doesPathHaveFilename(entry.mPath, mDefaultRingtoneFilename)) {
+                    setSettingIfNotSet(Settings.System.RINGTONE, tableUri, rowId);
+                    mDefaultRingtoneSet = true;
+                }
+            }
+            
+            return result;
+        }
+        
+        private boolean doesPathHaveFilename(String path, String filename) {
+            int pathFilenameStart = path.lastIndexOf(File.separatorChar) + 1;
+            int filenameLength = filename.length();
+            return path.regionMatches(pathFilenameStart, filename, 0, filenameLength) &&
+                    pathFilenameStart + filenameLength == path.length();
+        }
+        
+        private void setSettingIfNotSet(String settingName, Uri uri, long rowId) {
+            
+            String existingSettingValue = Settings.System.getString(mContext.getContentResolver(),
+                    settingName);
+            
+            if (TextUtils.isEmpty(existingSettingValue)) {
+                // Set the setting to the given URI
+                Settings.System.putString(mContext.getContentResolver(), settingName,
+                        ContentUris.withAppendedId(uri, rowId).toString());
+            }
+        }
+        
+    }; // end of anonymous MediaScannerClient instance
+    
+    private void prescan(String filePath) throws RemoteException {
+        Cursor c = null;
+        String where = null;
+        String[] selectionArgs = null;
+         
+        if (mFileCache == null) {
+            mFileCache = new HashMap<String, FileCacheEntry>();
+        } else {
+            mFileCache.clear();
+        }
+        if (mPlayLists == null) {
+            mPlayLists = new ArrayList<FileCacheEntry>();
+        } else {
+            mPlayLists.clear();
+        }
+  
+        // Build the list of files from the content provider
+        try {
+            // Read existing files from the audio table
+            if (filePath != null) {
+                where = MediaStore.Audio.Media.DATA + "=?";
+                selectionArgs = new String[] { filePath };
+            }
+            c = mMediaProvider.query(mAudioUri, AUDIO_PROJECTION, where, selectionArgs, null);
+ 
+            if (c != null) {
+                try {
+                    while (c.moveToNext()) {
+                        long rowId = c.getLong(ID_AUDIO_COLUMN_INDEX);
+                        String path = c.getString(PATH_AUDIO_COLUMN_INDEX);
+                        long lastModified = c.getLong(DATE_MODIFIED_AUDIO_COLUMN_INDEX);
+                        
+                        String key = path;
+                        if (mCaseInsensitivePaths) {
+                            key = path.toLowerCase();
+                        }
+                        mFileCache.put(key, new FileCacheEntry(mAudioUri, rowId, path,
+                                lastModified));
+                    }
+                } finally {
+                    c.close();
+                    c = null;
+                }
+            }
+
+            // Read existing files from the video table
+            if (filePath != null) {
+                where = MediaStore.Video.Media.DATA + "=?";
+            } else {
+                where = null;
+            }
+            c = mMediaProvider.query(mVideoUri, VIDEO_PROJECTION, where, selectionArgs, null);
+ 
+            if (c != null) {
+                try {
+                    while (c.moveToNext()) {
+                        long rowId = c.getLong(ID_VIDEO_COLUMN_INDEX);
+                        String path = c.getString(PATH_VIDEO_COLUMN_INDEX);
+                        long lastModified = c.getLong(DATE_MODIFIED_VIDEO_COLUMN_INDEX);
+                        
+                        String key = path;
+                        if (mCaseInsensitivePaths) {
+                            key = path.toLowerCase();
+                        }
+                        mFileCache.put(key, new FileCacheEntry(mVideoUri, rowId, path,
+                                lastModified));
+                    }
+                } finally {
+                    c.close();
+                    c = null;
+                }
+            }
+
+            // Read existing files from the images table
+            if (filePath != null) {
+                where = MediaStore.Images.Media.DATA + "=?";
+            } else {
+                where = null;
+            }
+            mOriginalCount = 0;
+            c = mMediaProvider.query(mImagesUri, IMAGES_PROJECTION, where, selectionArgs, null);
+ 
+            if (c != null) {
+                try {
+                    mOriginalCount = c.getCount();
+                    while (c.moveToNext()) {
+                        long rowId = c.getLong(ID_IMAGES_COLUMN_INDEX);
+                        String path = c.getString(PATH_IMAGES_COLUMN_INDEX);
+                       long lastModified = c.getLong(DATE_MODIFIED_IMAGES_COLUMN_INDEX);
+    
+                        String key = path;
+                        if (mCaseInsensitivePaths) {
+                            key = path.toLowerCase();
+                        }
+                        mFileCache.put(key, new FileCacheEntry(mImagesUri, rowId, path,
+                                lastModified));
+                    }
+                } finally {
+                    c.close();
+                    c = null;
+                }
+            }
+            
+            if (mProcessPlaylists) {
+                // Read existing files from the playlists table
+                if (filePath != null) {
+                    where = MediaStore.Audio.Playlists.DATA + "=?";
+                } else {
+                    where = null;
+                }
+                c = mMediaProvider.query(mPlaylistsUri, PLAYLISTS_PROJECTION, where, selectionArgs, null);
+     
+                if (c != null) {
+                    try {
+                        while (c.moveToNext()) {
+                            String path = c.getString(PATH_IMAGES_COLUMN_INDEX);
+            
+                            if (path != null && path.length() > 0) {
+                                long rowId = c.getLong(ID_PLAYLISTS_COLUMN_INDEX);
+                                long lastModified = c.getLong(DATE_MODIFIED_PLAYLISTS_COLUMN_INDEX);
+    
+                                String key = path;
+                                if (mCaseInsensitivePaths) {
+                                    key = path.toLowerCase();
+                                }
+                                mFileCache.put(key, new FileCacheEntry(mPlaylistsUri, rowId, path,
+                                        lastModified));
+                            }
+                        }
+                    } finally {
+                        c.close();
+                        c = null;
+                    }
+                }
+            }
+        }
+        finally {
+            if (c != null) {
+                c.close();
+            }
+        }
+    }
+    
+    private boolean inScanDirectory(String path, String[] directories) {
+        for (int i = 0; i < directories.length; i++) {
+            if (path.startsWith(directories[i])) {
+                return true;
+            }
+        }
+        return false;
+    }
+    
+    private void pruneDeadThumbnailFiles() {
+        HashSet<String> existingFiles = new HashSet<String>();
+        String directory = "/sdcard/DCIM/.thumbnails";
+        String [] files = (new File(directory)).list();
+        if (files == null)
+            files = new String[0];
+        
+        for (int i = 0; i < files.length; i++) {
+            String fullPathString = directory + "/" + files[i];
+            existingFiles.add(fullPathString);
+        }
+        
+        try {
+            Cursor c = mMediaProvider.query(
+                    mThumbsUri, 
+                    new String [] { "_data" }, 
+                    null, 
+                    null, 
+                    null);
+            Log.v(TAG, "pruneDeadThumbnailFiles... " + c);
+            if (c != null && c.moveToFirst()) {
+                do {
+                    String fullPathString = c.getString(0);
+                    existingFiles.remove(fullPathString);
+                } while (c.moveToNext());
+            }
+            
+            for (String fileToDelete : existingFiles) {
+                if (Config.LOGV)
+                    Log.v(TAG, "fileToDelete is " + fileToDelete);
+                try {
+                    (new File(fileToDelete)).delete();
+                } catch (SecurityException ex) {
+                }
+            }
+            
+            Log.v(TAG, "/pruneDeadThumbnailFiles... " + c);
+            if (c != null) {
+                c.close();
+            }
+        } catch (RemoteException e) {
+            // We will soon be killed...
+        }
+    }
+
+    private void postscan(String[] directories) throws RemoteException {
+        Iterator<FileCacheEntry> iterator = mFileCache.values().iterator();
+
+        while (iterator.hasNext()) {
+            FileCacheEntry entry = iterator.next();
+            String path = entry.mPath;
+            
+            // remove database entries for files that no longer exist.
+            boolean fileMissing = false;
+            
+            if (!entry.mSeenInFileSystem) {
+                if (inScanDirectory(path, directories)) {
+                    // we didn't see this file in the scan directory.
+                    fileMissing = true;
+                } else {
+                    // the file is outside of our scan directory,
+                    // so we need to check for file existence here.
+                    File testFile = new File(path);
+                    if (!testFile.exists()) {
+                        fileMissing = true;
+                    }
+                }
+            }
+            
+            if (fileMissing) {
+                // do not delete missing playlists, since they may have been modified by the user.
+                // the user can delete them in the media player instead.
+                // instead, clear the path and lastModified fields in the row
+                MediaFile.MediaFileType mediaFileType = MediaFile.getFileType(path);
+                int fileType = (mediaFileType == null ? 0 : mediaFileType.fileType);
+
+                if (MediaFile.isPlayListFileType(fileType)) {
+                    ContentValues values = new ContentValues();
+                    values.put(MediaStore.Audio.Playlists.DATA, "");
+                    values.put(MediaStore.Audio.Playlists.DATE_MODIFIED, 0);
+                    mMediaProvider.update(ContentUris.withAppendedId(mPlaylistsUri, entry.mRowId), values, null, null);
+                } else {
+                    mMediaProvider.delete(ContentUris.withAppendedId(entry.mTableUri, entry.mRowId), null, null);
+                    iterator.remove();
+                }
+            }
+        }
+        
+        // handle playlists last, after we know what media files are on the storage.
+        if (mProcessPlaylists) {
+            processPlayLists();
+        }
+        
+        if (mOriginalCount == 0 && mImagesUri.equals(Images.Media.getContentUri("external")))
+            pruneDeadThumbnailFiles();
+        
+        // allow GC to clean up
+        mGenreCache = null;
+        mPlayLists = null;
+        mFileCache = null;
+        mMediaProvider = null;
+    }
+    
+    private void initialize(String volumeName) {
+        mMediaProvider = mContext.getContentResolver().acquireProvider("media");
+        
+        mAudioUri = Audio.Media.getContentUri(volumeName);
+        mVideoUri = Video.Media.getContentUri(volumeName);
+        mImagesUri = Images.Media.getContentUri(volumeName);
+        mThumbsUri = Images.Thumbnails.getContentUri(volumeName);
+
+        if (!volumeName.equals("internal")) {
+            // we only support playlists on external media
+            mProcessPlaylists = true;
+            mProcessGenres = true;
+            mGenreCache = new HashMap<String, Uri>();
+            mGenresUri = Genres.getContentUri(volumeName);
+            mPlaylistsUri = Playlists.getContentUri(volumeName);
+            // assuming external storage is FAT (case insensitive), except on the simulator.
+            if ( Process.supportsProcesses()) {
+                mCaseInsensitivePaths = true;
+            }
+        }          
+    }
+
+    public void scanDirectories(String[] directories, String volumeName) {
+        try {
+            long start = System.currentTimeMillis();
+            initialize(volumeName);    
+            prescan(null);
+            long prescan = System.currentTimeMillis();
+            
+            for (int i = 0; i < directories.length; i++) {
+                processDirectory(directories[i], MediaFile.sFileExtensions, mClient);
+            }
+            long scan = System.currentTimeMillis();
+            postscan(directories);
+            long end = System.currentTimeMillis();
+            
+            if (Config.LOGD) {
+                Log.d(TAG, " prescan time: " + (prescan - start) + "ms\n");
+                Log.d(TAG, "    scan time: " + (scan - prescan) + "ms\n");
+                Log.d(TAG, "postscan time: " + (end - scan) + "ms\n");
+                Log.d(TAG, "   total time: " + (end - start) + "ms\n");
+            }
+        } catch (SQLException e) {
+            // this might happen if the SD card is removed while the media scanner is running
+            Log.e(TAG, "SQLException in MediaScanner.scan()", e);
+        } catch (UnsupportedOperationException e) {
+            // this might happen if the SD card is removed while the media scanner is running
+            Log.e(TAG, "UnsupportedOperationException in MediaScanner.scan()", e);
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException in MediaScanner.scan()", e);
+        }
+    }
+
+    // this function is used to scan a single file
+    public Uri scanSingleFile(String path, String volumeName, String mimeType) {
+        try {
+            initialize(volumeName);        
+            prescan(path);
+    
+            File file = new File(path);
+            // always scan the file, so we can return the content://media Uri for existing files
+            return mClient.doScanFile(path, mimeType, file.lastModified(), file.length(), true);
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException in MediaScanner.scanFile()", e);
+            return null;
+        }
+    }
+
+    // returns the number of matching file/directory names, starting from the right
+    private int matchPaths(String path1, String path2) {
+        int result = 0;
+        int end1 = path1.length();
+        int end2 = path2.length();
+        
+        while (end1 > 0 && end2 > 0) {
+            int slash1 = path1.lastIndexOf('/', end1 - 1);
+            int slash2 = path2.lastIndexOf('/', end2 - 1);
+            int backSlash1 = path1.lastIndexOf('\\', end1 - 1);
+            int backSlash2 = path2.lastIndexOf('\\', end2 - 1);
+            int start1 = (slash1 > backSlash1 ? slash1 : backSlash1);
+            int start2 = (slash2 > backSlash2 ? slash2 : backSlash2);
+            if (start1 < 0) start1 = 0; else start1++;
+            if (start2 < 0) start2 = 0; else start2++;
+            int length = end1 - start1;
+            if (end2 - start2 != length) break;
+            if (path1.regionMatches(true, start1, path2, start2, length)) {
+                result++;
+                end1 = start1 - 1;
+                end2 = start2 - 1;
+            } else break;
+        }
+               
+        return result;
+    }
+
+    private boolean addPlayListEntry(String entry, String playListDirectory, 
+            Uri uri, ContentValues values, int index) {
+        
+        // watch for trailing whitespace
+        int entryLength = entry.length();
+        while (entryLength > 0 && Character.isWhitespace(entry.charAt(entryLength - 1))) entryLength--;
+        // path should be longer than 3 characters.
+        // avoid index out of bounds errors below by returning here.
+        if (entryLength < 3) return false;
+        if (entryLength < entry.length()) entry = entry.substring(0, entryLength);
+
+        // does entry appear to be an absolute path?
+        // look for Unix or DOS absolute paths
+        char ch1 = entry.charAt(0);
+        boolean fullPath = (ch1 == '/' ||
+                (Character.isLetter(ch1) && entry.charAt(1) == ':' && entry.charAt(2) == '\\'));
+        // if we have a relative path, combine entry with playListDirectory
+        if (!fullPath)
+            entry = playListDirectory + entry;
+            
+        //FIXME - should we look for "../" within the path?
+        
+        // best matching MediaFile for the play list entry
+        FileCacheEntry bestMatch = null;
+        
+        // number of rightmost file/directory names for bestMatch
+        int bestMatchLength = 0;    
+                
+        Iterator<FileCacheEntry> iterator = mFileCache.values().iterator();
+        while (iterator.hasNext()) {
+            FileCacheEntry cacheEntry = iterator.next();
+            String path = cacheEntry.mPath;
+        
+            if (path.equalsIgnoreCase(entry)) {
+                bestMatch = cacheEntry;
+                break;    // don't bother continuing search
+            }
+            
+            int matchLength = matchPaths(path, entry);
+            if (matchLength > bestMatchLength) {
+                bestMatch = cacheEntry;
+                bestMatchLength = matchLength;
+            }
+        }
+        
+        if (bestMatch == null) {
+            return false;
+        }
+        
+        try {
+        // OK, now we need to add this to the database
+            values.clear();
+            values.put(MediaStore.Audio.Playlists.Members.PLAY_ORDER, Integer.valueOf(index));
+            values.put(MediaStore.Audio.Playlists.Members.AUDIO_ID, Long.valueOf(bestMatch.mRowId));
+            mMediaProvider.insert(uri, values);
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException in MediaScanner.addPlayListEntry()", e);
+            return false;
+        }
+
+        return true;
+    }
+    
+    private void processM3uPlayList(String path, String playListDirectory, Uri uri, ContentValues values) {
+        BufferedReader reader = null;
+        try {
+            File f = new File(path);
+            if (f.exists()) {
+                reader = new BufferedReader(
+                        new InputStreamReader(new FileInputStream(f)), 8192);
+                String line = reader.readLine();
+                int index = 0;
+                while (line != null) {
+                    // ignore comment lines, which begin with '#'
+                    if (line.length() > 0 && line.charAt(0) != '#') {
+                        values.clear();
+                        if (addPlayListEntry(line, playListDirectory, uri, values, index))
+                            index++;
+                    }
+                    line = reader.readLine();
+                }
+            }
+        } catch (IOException e) {
+            Log.e(TAG, "IOException in MediaScanner.processM3uPlayList()", e);
+        } finally {
+            try {
+                if (reader != null)
+                    reader.close();
+            } catch (IOException e) {
+                Log.e(TAG, "IOException in MediaScanner.processM3uPlayList()", e);
+            }
+        }
+    }
+
+    private void processPlsPlayList(String path, String playListDirectory, Uri uri, ContentValues values) {
+        BufferedReader reader = null;
+        try {
+            File f = new File(path);
+            if (f.exists()) {
+                reader = new BufferedReader(
+                        new InputStreamReader(new FileInputStream(f)), 8192);
+                String line = reader.readLine();
+                int index = 0;
+                while (line != null) {
+                    // ignore comment lines, which begin with '#'
+                    if (line.startsWith("File")) {
+                        int equals = line.indexOf('=');
+                        if (equals > 0) {
+                            values.clear();
+                            if (addPlayListEntry(line.substring(equals + 1), playListDirectory, uri, values, index))
+                                index++;
+                        }
+                    }
+                    line = reader.readLine();
+                }
+            }
+        } catch (IOException e) {
+            Log.e(TAG, "IOException in MediaScanner.processPlsPlayList()", e);
+        } finally {
+            try {
+                if (reader != null)
+                    reader.close();
+            } catch (IOException e) {
+                Log.e(TAG, "IOException in MediaScanner.processPlsPlayList()", e);
+            }
+        }
+    }
+
+    class WplHandler implements ElementListener {
+
+        final ContentHandler handler;
+        String playListDirectory;
+        Uri uri;
+        ContentValues values = new ContentValues();
+        int index = 0;
+
+        public WplHandler(String playListDirectory, Uri uri) {
+            this.playListDirectory = playListDirectory;
+            this.uri = uri;
+            
+            RootElement root = new RootElement("smil");
+            Element body = root.getChild("body");
+            Element seq = body.getChild("seq");
+            Element media = seq.getChild("media");
+            media.setElementListener(this);
+
+            this.handler = root.getContentHandler();
+        }
+
+        public void start(Attributes attributes) {
+            String path = attributes.getValue("", "src");
+            if (path != null) {
+                values.clear();
+                if (addPlayListEntry(path, playListDirectory, uri, values, index)) {
+                    index++;
+                }
+            }
+        }
+
+       public void end() {
+       }
+
+        ContentHandler getContentHandler() {
+            return handler;
+        }
+    }
+
+    private void processWplPlayList(String path, String playListDirectory, Uri uri) {
+        FileInputStream fis = null;
+        try {
+            File f = new File(path);
+            if (f.exists()) {
+                fis = new FileInputStream(f);
+
+                Xml.parse(fis, Xml.findEncodingByName("UTF-8"), new WplHandler(playListDirectory, uri).getContentHandler());
+            }
+        } catch (SAXException e) {
+            e.printStackTrace();
+        } catch (IOException e) {
+            e.printStackTrace();
+        } finally {
+            try {
+                if (fis != null)
+                    fis.close();
+            } catch (IOException e) {
+                Log.e(TAG, "IOException in MediaScanner.processWplPlayList()", e);
+            }
+        }
+    }
+    
+    private void processPlayLists() throws RemoteException {
+        Iterator<FileCacheEntry> iterator = mPlayLists.iterator();
+        while (iterator.hasNext()) {
+            FileCacheEntry entry = iterator.next();
+            String path = entry.mPath;  
+
+            // only process playlist files if they are new or have been modified since the last scan
+            if (entry.mLastModifiedChanged) {
+                ContentValues values = new ContentValues();
+                int lastSlash = path.lastIndexOf('/');
+                if (lastSlash < 0) throw new IllegalArgumentException("bad path " + path);
+                Uri uri, membersUri;
+                long rowId = entry.mRowId;
+                if (rowId == 0) {
+                    // Create a new playlist
+        
+                    int lastDot = path.lastIndexOf('.');
+                    String name = (lastDot < 0 ? path.substring(lastSlash + 1) : path.substring(lastSlash + 1, lastDot));
+                    values.put(MediaStore.Audio.Playlists.NAME, name);
+                    values.put(MediaStore.Audio.Playlists.DATA, path);
+                    values.put(MediaStore.Audio.Playlists.DATE_MODIFIED, entry.mLastModified);
+                    uri = mMediaProvider.insert(mPlaylistsUri, values);
+                    rowId = ContentUris.parseId(uri);
+                    membersUri = Uri.withAppendedPath(uri, Playlists.Members.CONTENT_DIRECTORY);
+                } else {
+                    uri = ContentUris.withAppendedId(mPlaylistsUri, rowId);
+                    
+                    // update lastModified value of existing playlist
+                    values.put(MediaStore.Audio.Playlists.DATE_MODIFIED, entry.mLastModified);
+                    mMediaProvider.update(uri, values, null, null);
+
+                    // delete members of existing playlist
+                    membersUri = Uri.withAppendedPath(uri, Playlists.Members.CONTENT_DIRECTORY);
+                    mMediaProvider.delete(membersUri, null, null);
+                }
+               
+                String playListDirectory = path.substring(0, lastSlash + 1);
+                MediaFile.MediaFileType mediaFileType = MediaFile.getFileType(path);
+                int fileType = (mediaFileType == null ? 0 : mediaFileType.fileType);
+
+                if (fileType == MediaFile.FILE_TYPE_M3U)
+                    processM3uPlayList(path, playListDirectory, membersUri, values);
+                else if (fileType == MediaFile.FILE_TYPE_PLS)
+                    processPlsPlayList(path, playListDirectory, membersUri, values);
+                else if (fileType == MediaFile.FILE_TYPE_WPL)
+                    processWplPlayList(path, playListDirectory, membersUri);
+                    
+                Cursor cursor = mMediaProvider.query(membersUri, PLAYLIST_MEMBERS_PROJECTION, null,
+                        null, null);
+                try {
+                    if (cursor == null || cursor.getCount() == 0) {
+                        Log.d(TAG, "playlist is empty - deleting");
+                        mMediaProvider.delete(uri, null, null);
+                    }
+                } finally {
+                    if (cursor != null) cursor.close();
+                }
+            }
+        }
+    }
+    
+    private native void processDirectory(String path, String extensions, MediaScannerClient client);
+    private native void processFile(String path, String mimeType, MediaScannerClient client);
+    public native void setLocale(String locale);
+    
+    public native byte[] extractAlbumArt(FileDescriptor fd);
+
+    private native final void native_setup();
+    private native final void native_finalize();
+    @Override
+    protected void finalize() { 
+        mContext.getContentResolver().releaseProvider(mMediaProvider);
+        native_finalize(); 
+    }
+}
diff --git a/media/java/android/media/MediaScannerClient.java b/media/java/android/media/MediaScannerClient.java
new file mode 100644
index 0000000..cf1a8da
--- /dev/null
+++ b/media/java/android/media/MediaScannerClient.java
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+package android.media;
+
+/**
+ * {@hide}
+ */
+public interface MediaScannerClient
+{    
+    public void scanFile(String path, long lastModified, long fileSize);
+    
+    public void scanFile(String path, String mimeType, long lastModified, long fileSize);
+
+    /**
+     * Called by native code to return metadata extracted from media files.
+     */
+    public void handleStringTag(String name, String value);
+    
+    /**
+     * Called by native code to return mime type extracted from DRM content.
+     */
+    public void setMimeType(String mimeType);
+}
diff --git a/media/java/android/media/MediaScannerConnection.java b/media/java/android/media/MediaScannerConnection.java
new file mode 100644
index 0000000..d2596b8
--- /dev/null
+++ b/media/java/android/media/MediaScannerConnection.java
@@ -0,0 +1,189 @@
+/*
+ * 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.
+ */
+
+package android.media;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.media.IMediaScannerListener;
+import android.media.IMediaScannerService;
+import android.net.Uri;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Config;
+import android.util.Log;
+
+
+/**
+ * MediaScannerConnection provides a way for applications to pass a 
+ * newly created or downloaded media file to the media scanner service.
+ * The media scanner service will read metadata from the file and add 
+ * the file to the media content provider.
+ * The MediaScannerConnectionClient provides an interface for the 
+ * media scanner service to return the Uri for a newly scanned file
+ * to the client of the MediaScannerConnection class.
+ */
+public class MediaScannerConnection implements ServiceConnection {
+
+    private static final String TAG = "MediaScannerConnection";
+
+    private Context mContext;
+    private MediaScannerConnectionClient mClient;
+    private IMediaScannerService mService;
+    private boolean mConnected; // true if connect() has been called since last disconnect()
+    
+    private IMediaScannerListener.Stub mListener = new IMediaScannerListener.Stub() {
+        public void scanCompleted(String path, Uri uri) {
+            MediaScannerConnectionClient client = mClient;
+            if (client != null) {
+                client.onScanCompleted(path, uri);
+            }
+        }
+    };
+
+    /**
+     * An interface for notifying clients of MediaScannerConnection
+     * when a connection to the MediaScanner service has been established
+     * and when the scanning of a file has completed.
+     */
+    public interface MediaScannerConnectionClient {
+        /**
+         * Called to notify the client when a connection to the 
+         * MediaScanner service has been established.
+         */    
+        public void onMediaScannerConnected();
+
+        /**
+         * Called to notify the client when the media scanner has finished
+         * scanning a file.
+         * @param path the path to the file that has been scanned.
+         * @param uri the Uri for the file if the scanning operation succeeded 
+         * and the file was added to the media database, or null if scanning failed. 
+         */    
+        public void onScanCompleted(String path, Uri uri);
+    }
+
+    /**
+     * Constructs a new MediaScannerConnection object.
+     * @param context the Context object, required for establishing a connection to
+     * the media scanner service.
+     * @param client an optional object implementing the MediaScannerConnectionClient
+     * interface, for receiving notifications from the media scanner.
+     */
+    public MediaScannerConnection(Context context, MediaScannerConnectionClient client) {
+        mContext = context;
+        mClient = client;
+    }
+
+    /**
+     * Initiates a connection to the media scanner service.
+     * {@link MediaScannerConnectionClient#onMediaScannerConnected()}
+     * will be called when the connection is established.
+     */
+    public void connect() {
+        synchronized (this) {
+            if (!mConnected) {
+                Intent intent = new Intent(IMediaScannerService.class.getName());
+                mContext.bindService(intent, this, Context.BIND_AUTO_CREATE);
+                mConnected = true;
+            }
+        }
+    }
+
+    /**
+     * Releases the connection to the media scanner service.
+     */
+    public void disconnect() {
+        synchronized (this) {
+            if (mConnected) {
+                if (Config.LOGV) {
+                    Log.v(TAG, "Disconnecting from Media Scanner");
+                }
+                try {
+                    mContext.unbindService(this);
+                } catch (IllegalArgumentException ex) {
+                    if (Config.LOGV) {
+                        Log.v(TAG, "disconnect failed: " + ex);
+                    }
+                }
+                mConnected = false;
+            }
+        }
+    }
+    
+    /**
+     * Returns whether we are connected to the media scanner service
+     * @return true if we are connected, false otherwise
+     */
+    public synchronized boolean isConnected() {
+        return (mService != null && mConnected);
+    }
+
+    /**
+     * Requests the media scanner to scan a file.
+     * @param path the path to the file to be scanned.
+     * @param mimeType  an optional mimeType for the file.
+     * If mimeType is null, then the mimeType will be inferred from the file extension.
+     * Success or failure of the scanning operation cannot be determined until 
+     * {@link MediaScannerConnectionClient#onScanCompleted(String, Uri)} is called.
+     */
+     public void scanFile(String path, String mimeType) {
+        synchronized (this) {
+            if (mService == null || !mConnected) {
+                throw new IllegalStateException("not connected to MediaScannerService");
+            }
+            try {
+                if (Config.LOGV) {
+                    Log.v(TAG, "Scanning file " + path);
+                }
+                mService.requestScanFile(path, mimeType, mListener);
+            } catch (RemoteException e) {
+                if (Config.LOGD) {
+                    Log.d(TAG, "Failed to scan file " + path);
+                }
+            }
+        }
+    }
+
+    /**
+     * Part of the ServiceConnection interface.  Do not call.
+     */
+    public void onServiceConnected(ComponentName className, IBinder service) {
+        if (Config.LOGV) {
+            Log.v(TAG, "Connected to Media Scanner");
+        }
+        synchronized (this) {
+            mService = IMediaScannerService.Stub.asInterface(service);
+            if (mService != null && mClient != null) {
+                mClient.onMediaScannerConnected();
+            }
+        }
+    }
+
+    /**
+     * Part of the ServiceConnection interface.  Do not call.
+     */
+    public void onServiceDisconnected(ComponentName className) {
+        if (Config.LOGV) {
+            Log.v(TAG, "Disconnected from Media Scanner");
+        }
+        synchronized (this) {
+            mService = null;
+        }
+    }
+}
diff --git a/media/java/android/media/ResampleInputStream.java b/media/java/android/media/ResampleInputStream.java
new file mode 100644
index 0000000..e26eae5
--- /dev/null
+++ b/media/java/android/media/ResampleInputStream.java
@@ -0,0 +1,153 @@
+/*
+ * 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.
+ */
+
+package android.media;
+
+import android.util.Config;
+import android.util.Log;
+
+import java.io.InputStream;
+import java.io.IOException;
+
+
+/**
+ * ResampleInputStream
+ * @hide
+ */
+public final class ResampleInputStream extends InputStream
+{    
+    static {
+        System.loadLibrary("media_jni");
+    }
+    
+    private final static String TAG = "ResampleInputStream";
+    
+    // pcm input stream
+    private InputStream mInputStream;
+
+    // sample rates, assumed to be normalized
+    private final int mRateIn;
+    private final int mRateOut;
+    
+    // input pcm data
+    private byte[] mBuf;
+    private int mBufCount;
+    
+    // length of 2:1 fir
+    private static final int mFirLength = 29;
+    
+    // helper for bytewise read()
+    private final byte[] mOneByte = new byte[1];
+    
+    /**
+     * Create a new ResampleInputStream, which converts the sample rate
+     * @param inputStream InputStream containing 16 bit PCM.
+     * @param rateIn the input sample rate.
+     * @param rateOut the output sample rate.
+     * This only handles rateIn == rateOut / 2 for the moment.
+     */
+    public ResampleInputStream(InputStream inputStream, int rateIn, int rateOut) {
+        // only support 2:1 at the moment
+        if (rateIn != 2 * rateOut) throw new IllegalArgumentException("only support 2:1 at the moment");
+        rateIn = 2;
+        rateOut = 1;
+
+        mInputStream = inputStream;
+        mRateIn = rateIn;
+        mRateOut = rateOut;
+    }
+
+    @Override
+    public int read() throws IOException {
+        int rtn = read(mOneByte, 0, 1);
+        return rtn == 1 ? (0xff & mOneByte[0]) : -1;
+    }
+    
+    @Override
+    public int read(byte[] b) throws IOException {
+        return read(b, 0, b.length);
+    }
+
+    @Override
+    public int read(byte[] b, int offset, int length) throws IOException {
+        if (mInputStream == null) throw new IllegalStateException("not open");
+
+        // ensure that mBuf is big enough to cover requested 'length'
+        int nIn = ((length / 2) * mRateIn / mRateOut + mFirLength) * 2;
+        if (mBuf == null) {
+            mBuf = new byte[nIn];
+        } else if (nIn > mBuf.length) {
+            byte[] bf = new byte[nIn];
+            System.arraycopy(mBuf, 0, bf, 0, mBufCount);
+            mBuf = bf;
+        }
+        
+        // read until we have enough data for at least one output sample
+        while (true) {
+            int len = ((mBufCount / 2 - mFirLength) * mRateOut / mRateIn) * 2;
+            if (len > 0) {
+                length = len < length ? len : (length / 2) * 2;
+                break;
+            }
+            // TODO: should mBuf.length below be nIn instead?
+            int n = mInputStream.read(mBuf, mBufCount, mBuf.length - mBufCount);
+            if (n == -1) return -1;
+            mBufCount += n;
+        }
+
+        // resample input data
+        fir21(mBuf, 0, b, offset, length / 2);
+        
+        // move any unused bytes to front of mBuf
+        int nFwd = length * mRateIn / mRateOut;
+        mBufCount -= nFwd;
+        if (mBufCount > 0) System.arraycopy(mBuf, nFwd, mBuf, 0, mBufCount);
+        
+        return length;
+    }
+
+/*
+    @Override
+    public int available() throws IOException {
+        int nsamples = (mIn - mOut + mInputStream.available()) / 2;
+        return ((nsamples - mFirLength) * mRateOut / mRateIn) * 2;
+    }
+*/
+
+    @Override
+    public void close() throws IOException {
+        try {
+            if (mInputStream != null) mInputStream.close();
+        } finally {
+            mInputStream = null;
+        }
+    }
+
+    @Override
+    protected void finalize() throws Throwable {
+        if (mInputStream != null) {
+            close();
+            throw new IllegalStateException("someone forgot to close ResampleInputStream");
+        }
+    }
+
+    //
+    // fir filter code JNI interface
+    //
+    private static native void fir21(byte[] in, int inOffset,
+            byte[] out, int outOffset, int npoints);
+
+}
diff --git a/media/java/android/media/Ringtone.java b/media/java/android/media/Ringtone.java
new file mode 100644
index 0000000..e80d8aa
--- /dev/null
+++ b/media/java/android/media/Ringtone.java
@@ -0,0 +1,239 @@
+/*
+ * 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.
+ */
+
+package android.media;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.res.AssetFileDescriptor;
+import android.database.Cursor;
+import android.media.AudioManager;
+import android.media.MediaPlayer;
+import android.net.Uri;
+import android.provider.DrmStore;
+import android.provider.MediaStore;
+import android.provider.Settings;
+import android.util.Log;
+
+import java.io.FileDescriptor;
+import java.io.IOException;
+
+/**
+ * Ringtone provides a quick method for playing a ringtone, notification, or
+ * other similar types of sounds.
+ * <p>
+ * For ways of retrieving {@link Ringtone} objects or to show a ringtone
+ * picker, see {@link RingtoneManager}.
+ * 
+ * @see RingtoneManager
+ */
+public class Ringtone {
+    private static String TAG = "Ringtone";
+
+    private static final String[] MEDIA_COLUMNS = new String[] {
+        MediaStore.Audio.Media._ID,
+        MediaStore.Audio.Media.DATA,
+        MediaStore.Audio.Media.TITLE
+    };
+
+    private static final String[] DRM_COLUMNS = new String[] {
+        DrmStore.Audio._ID,
+        DrmStore.Audio.DATA,
+        DrmStore.Audio.TITLE
+    };
+
+    private MediaPlayer mAudio;
+
+    private Uri mUri;
+    private String mTitle;
+    private FileDescriptor mFileDescriptor;
+    private AssetFileDescriptor mAssetFileDescriptor;
+
+    private int mStreamType = AudioManager.STREAM_RING;
+
+    private Context mContext;
+
+    Ringtone(Context context) {
+        mContext = context;
+    }
+
+    /**
+     * Sets the stream type where this ringtone will be played.
+     * 
+     * @param streamType The stream, see {@link AudioManager}.
+     */
+    public void setStreamType(int streamType) {
+        mStreamType = streamType;
+        
+        if (mAudio != null) {
+            /*
+             * The stream type has to be set before the media player is
+             * prepared. Re-initialize it.
+             */
+            try {
+                openMediaPlayer();
+            } catch (IOException e) {
+                Log.w(TAG, "Couldn't set the stream type", e);
+            }
+        }
+    }
+
+    /**
+     * Gets the stream type where this ringtone will be played.
+     * 
+     * @return The stream type, see {@link AudioManager}.
+     */
+    public int getStreamType() {
+        return mStreamType;
+    }
+
+    /**
+     * Returns a human-presentable title for ringtone. Looks in media and DRM
+     * content providers. If not in either, uses the filename
+     * 
+     * @param context A context used for querying. 
+     */
+    public String getTitle(Context context) {
+        if (mTitle != null) return mTitle;
+        return mTitle = getTitle(context, mUri, true);
+    }
+
+    private static String getTitle(Context context, Uri uri, boolean followSettingsUri) {
+        Cursor cursor = null;
+        ContentResolver res = context.getContentResolver();
+        
+        String title = null;
+
+        if (uri != null) {
+            String authority = uri.getAuthority();
+
+            if (Settings.AUTHORITY.equals(authority)) {
+                if (followSettingsUri) {
+                    Uri actualUri = RingtoneManager.getActualDefaultRingtoneUri(context,
+                            RingtoneManager.getDefaultType(uri));
+                    String actualTitle = getTitle(context, actualUri, false);
+                    title = context
+                            .getString(com.android.internal.R.string.ringtone_default_with_actual,
+                                    actualTitle);
+                }
+            } else {
+                
+                if (DrmStore.AUTHORITY.equals(authority)) {
+                    cursor = res.query(uri, DRM_COLUMNS, null, null, null);
+                } else if (MediaStore.AUTHORITY.equals(authority)) {
+                    cursor = res.query(uri, MEDIA_COLUMNS, null, null, null);
+                }
+                
+                if (cursor != null && cursor.getCount() == 1) {
+                    cursor.moveToFirst();
+                    return cursor.getString(2);
+                } else {
+                    title = uri.getLastPathSegment();
+                }
+            }
+        }
+
+        if (title == null) {
+            title = context.getString(com.android.internal.R.string.ringtone_unknown);
+            
+            if (title == null) {
+                title = "";
+            }
+        }
+        
+        return title;
+    }
+    
+    private void openMediaPlayer() throws IOException {
+        mAudio = new MediaPlayer();
+        if (mUri != null) {
+            mAudio.setDataSource(mContext, mUri);
+        } else if (mFileDescriptor != null) {
+            mAudio.setDataSource(mFileDescriptor);
+        } else if (mAssetFileDescriptor != null) {
+            // Note: using getDeclaredLength so that our behavior is the same
+            // as previous versions when the content provider is returning
+            // a full file.
+            if (mAssetFileDescriptor.getDeclaredLength() < 0) {
+                mAudio.setDataSource(mAssetFileDescriptor.getFileDescriptor());
+            } else {
+                mAudio.setDataSource(mAssetFileDescriptor.getFileDescriptor(),
+                        mAssetFileDescriptor.getStartOffset(),
+                        mAssetFileDescriptor.getDeclaredLength());
+            }
+        } else {
+            throw new IOException("No data source set.");
+        }
+        mAudio.setAudioStreamType(mStreamType);
+        mAudio.prepare();
+    }
+
+    void open(FileDescriptor fd) throws IOException {
+        mFileDescriptor = fd;
+        openMediaPlayer();
+    }
+
+    void open(AssetFileDescriptor fd) throws IOException {
+        mAssetFileDescriptor = fd;
+        openMediaPlayer();
+    }
+
+    void open(Uri uri) throws IOException {
+        mUri = uri;
+        openMediaPlayer();
+    }
+    
+    /**
+     * Plays the ringtone.
+     */
+    public void play() {
+        if (mAudio == null) {
+            try {
+                openMediaPlayer();
+            } catch (Exception ex) {
+                Log.e(TAG, "play() caught ", ex);
+                mAudio = null;
+            }
+        }
+        if (mAudio != null) {
+            mAudio.start();
+        }
+    }
+
+    /**
+     * Stops a playing ringtone.
+     */
+    public void stop() {
+        if (mAudio != null) {
+            mAudio.reset();
+            mAudio.release();
+            mAudio = null;
+        }
+    }
+
+    /**
+     * Whether this ringtone is currently playing.
+     * 
+     * @return True if playing, false otherwise.
+     */
+    public boolean isPlaying() {
+        return mAudio != null && mAudio.isPlaying();
+    }
+
+    void setTitle(String title) {
+        mTitle = title;
+    }
+}
diff --git a/media/java/android/media/RingtoneManager.java b/media/java/android/media/RingtoneManager.java
new file mode 100644
index 0000000..2f0007f
--- /dev/null
+++ b/media/java/android/media/RingtoneManager.java
@@ -0,0 +1,713 @@
+/*
+ * 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.
+ */
+
+package android.media;
+
+import com.android.internal.database.SortCursor;
+
+import android.annotation.SdkConstant;
+import android.annotation.SdkConstant.SdkConstantType;
+import android.app.Activity;
+import android.content.ContentUris;
+import android.content.Context;
+import android.content.res.AssetFileDescriptor;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Environment;
+import android.provider.DrmStore;
+import android.provider.MediaStore;
+import android.provider.Settings;
+import android.provider.Settings.System;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * RingtoneManager provides access to ringtones, notification, and other types
+ * of sounds. It manages querying the different media providers and combines the
+ * results into a single cursor. It also provides a {@link Ringtone} for each
+ * ringtone. We generically call these sounds ringtones, however the
+ * {@link #TYPE_RINGTONE} refers to the type of sounds that are suitable for the
+ * phone ringer.
+ * <p>
+ * To show a ringtone picker to the user, use the
+ * {@link #ACTION_RINGTONE_PICKER} intent to launch the picker as a subactivity.
+ * 
+ * @see Ringtone
+ */
+public class RingtoneManager {
+
+    private static final String TAG = "RingtoneManager";
+
+    // Make sure these are in sync with attrs.xml:
+    // <attr name="ringtoneType">
+    
+    /**
+     * Type that refers to sounds that are used for the phone ringer.
+     */
+    public static final int TYPE_RINGTONE = 1;
+    
+    /**
+     * Type that refers to sounds that are used for notifications.
+     */
+    public static final int TYPE_NOTIFICATION = 2;
+    
+    /**
+     * Type that refers to sounds that are used for the alarm.
+     */
+    public static final int TYPE_ALARM = 4;
+    
+    /**
+     * All types of sounds.
+     */
+    public static final int TYPE_ALL = TYPE_RINGTONE | TYPE_NOTIFICATION | TYPE_ALARM;
+    
+    // </attr>
+    
+    /**
+     * Activity Action: Shows a ringtone picker.
+     * <p>
+     * Input: {@link #EXTRA_RINGTONE_EXISTING_URI},
+     * {@link #EXTRA_RINGTONE_SHOW_DEFAULT},
+     * {@link #EXTRA_RINGTONE_SHOW_SILENT}, {@link #EXTRA_RINGTONE_TYPE},
+     * {@link #EXTRA_RINGTONE_DEFAULT_URI}, {@link #EXTRA_RINGTONE_TITLE},
+     * {@link #EXTRA_RINGTONE_INCLUDE_DRM}.
+     * <p>
+     * Output: {@link #EXTRA_RINGTONE_PICKED_URI}.
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_RINGTONE_PICKER = "android.intent.action.RINGTONE_PICKER";
+
+    /**
+     * Given to the ringtone picker as a boolean. Whether to show an item for
+     * "Default".
+     * 
+     * @see #ACTION_RINGTONE_PICKER
+     */
+    public static final String EXTRA_RINGTONE_SHOW_DEFAULT =
+            "android.intent.extra.ringtone.SHOW_DEFAULT";
+    
+    /**
+     * Given to the ringtone picker as a boolean. Whether to show an item for
+     * "Silent". If the "Silent" item is picked,
+     * {@link #EXTRA_RINGTONE_PICKED_URI} will be null.
+     * 
+     * @see #ACTION_RINGTONE_PICKER
+     */
+    public static final String EXTRA_RINGTONE_SHOW_SILENT =
+            "android.intent.extra.ringtone.SHOW_SILENT";
+
+    /**
+     * Given to the ringtone picker as a boolean. Whether to include DRM ringtones.
+     */
+    public static final String EXTRA_RINGTONE_INCLUDE_DRM =
+            "android.intent.extra.ringtone.INCLUDE_DRM";
+    
+    /**
+     * Given to the ringtone picker as a {@link Uri}. The {@link Uri} of the
+     * current ringtone, which will be used to show a checkmark next to the item
+     * for this {@link Uri}. If showing an item for "Default" (@see
+     * {@link #EXTRA_RINGTONE_SHOW_DEFAULT}), this can also be one of
+     * {@link System#DEFAULT_RINGTONE_URI} or
+     * {@link System#DEFAULT_NOTIFICATION_URI} to have the "Default" item
+     * checked.
+     * 
+     * @see #ACTION_RINGTONE_PICKER
+     */
+    public static final String EXTRA_RINGTONE_EXISTING_URI =
+            "android.intent.extra.ringtone.EXISTING_URI";
+    
+    /**
+     * Given to the ringtone picker as a {@link Uri}. The {@link Uri} of the
+     * ringtone to play when the user attempts to preview the "Default"
+     * ringtone. This can be one of {@link System#DEFAULT_RINGTONE_URI} or
+     * {@link System#DEFAULT_NOTIFICATION_URI} to have the "Default" point to
+     * the current sound for the given default sound type. If you are showing a
+     * ringtone picker for some other type of sound, you are free to provide any
+     * {@link Uri} here.
+     */
+    public static final String EXTRA_RINGTONE_DEFAULT_URI =
+            "android.intent.extra.ringtone.DEFAULT_URI";
+    
+    /**
+     * Given to the ringtone picker as an int. Specifies which ringtone type(s) should be
+     * shown in the picker. One or more of {@link #TYPE_RINGTONE},
+     * {@link #TYPE_NOTIFICATION}, {@link #TYPE_ALARM}, or {@link #TYPE_ALL}
+     * (bitwise-ored together).
+     */
+    public static final String EXTRA_RINGTONE_TYPE = "android.intent.extra.ringtone.TYPE";
+
+    /**
+     * Given to the ringtone picker as a {@link CharSequence}. The title to
+     * show for the ringtone picker. This has a default value that is suitable
+     * in most cases.
+     */
+    public static final String EXTRA_RINGTONE_TITLE = "android.intent.extra.ringtone.TITLE";
+    
+    /**
+     * Returned from the ringtone picker as a {@link Uri}.
+     * <p>
+     * It will be one of:
+     * <li> the picked ringtone,
+     * <li> a {@link Uri} that equals {@link System#DEFAULT_RINGTONE_URI} or
+     * {@link System#DEFAULT_NOTIFICATION_URI} if the default was chosen,
+     * <li> null if the "Silent" item was picked.
+     * 
+     * @see #ACTION_RINGTONE_PICKER
+     */
+    public static final String EXTRA_RINGTONE_PICKED_URI =
+            "android.intent.extra.ringtone.PICKED_URI";
+    
+    // Make sure the column ordering and then ..._COLUMN_INDEX are in sync
+    
+    private static final String[] INTERNAL_COLUMNS = new String[] {
+        MediaStore.Audio.Media._ID, MediaStore.Audio.Media.TITLE,
+        "\"" + MediaStore.Audio.Media.INTERNAL_CONTENT_URI + "\""
+    };
+
+    private static final String[] DRM_COLUMNS = new String[] {
+        DrmStore.Audio._ID, DrmStore.Audio.TITLE,
+        "\"" + DrmStore.Audio.CONTENT_URI + "\""
+    };
+
+    private static final String[] MEDIA_COLUMNS = new String[] {
+        MediaStore.Audio.Media._ID, MediaStore.Audio.Media.TITLE,
+        "\"" + MediaStore.Audio.Media.EXTERNAL_CONTENT_URI + "\""
+    };
+    
+    /**
+     * The column index (in the cursor returned by {@link #getCursor()} for the
+     * row ID.
+     */
+    public static final int ID_COLUMN_INDEX = 0;
+
+    /**
+     * The column index (in the cursor returned by {@link #getCursor()} for the
+     * title.
+     */
+    public static final int TITLE_COLUMN_INDEX = 1;
+
+    /**
+     * The column index (in the cursor returned by {@link #getCursor()} for the
+     * media provider's URI.
+     */
+    public static final int URI_COLUMN_INDEX = 2;
+
+    private Activity mActivity;
+    private Context mContext;
+    
+    private Cursor mCursor;
+
+    private int mType = TYPE_RINGTONE;
+    
+    /**
+     * If a column (item from this list) exists in the Cursor, its value must
+     * be true (value of 1) for the row to be returned.
+     */
+    private List<String> mFilterColumns = new ArrayList<String>();
+    
+    private boolean mStopPreviousRingtone = true;
+    private Ringtone mPreviousRingtone;
+
+    private boolean mIncludeDrm;
+    
+    /**
+     * Constructs a RingtoneManager. This constructor is recommended as its
+     * constructed instance manages cursor(s).
+     * 
+     * @param activity The activity used to get a managed cursor.
+     */
+    public RingtoneManager(Activity activity) {
+        mContext = mActivity = activity;
+        setType(mType);
+    }
+
+    /**
+     * Constructs a RingtoneManager. The instance constructed by this
+     * constructor will not manage the cursor(s), so the client should handle
+     * this itself.
+     * 
+     * @param context The context to used to get a cursor.
+     */
+    public RingtoneManager(Context context) {
+        mContext = context;
+        setType(mType);
+    }
+
+    /**
+     * Sets which type(s) of ringtones will be listed by this.
+     * 
+     * @param type The type(s), one or more of {@link #TYPE_RINGTONE},
+     *            {@link #TYPE_NOTIFICATION}, {@link #TYPE_ALARM},
+     *            {@link #TYPE_ALL}.
+     * @see #EXTRA_RINGTONE_TYPE           
+     */
+    public void setType(int type) {
+
+        if (mCursor != null) {
+            throw new IllegalStateException(
+                    "Setting filter columns should be done before querying for ringtones.");
+        }
+        
+        mType = type;
+        setFilterColumnsList(type);
+    }
+
+    /**
+     * Infers the playback stream type based on what type of ringtones this
+     * manager is returning.
+     * 
+     * @return The stream type.
+     * @hide Pending API Council approval
+     */
+    public int inferStreamType() {
+        switch (mType) {
+            
+            case TYPE_ALARM:
+                return AudioManager.STREAM_ALARM;
+                
+            case TYPE_NOTIFICATION:
+                return AudioManager.STREAM_NOTIFICATION;
+                
+            default:
+                return AudioManager.STREAM_RING;
+        }
+    }
+    
+    /**
+     * Whether retrieving another {@link Ringtone} will stop playing the
+     * previously retrieved {@link Ringtone}.
+     * <p>
+     * If this is false, make sure to {@link Ringtone#stop()} any previous
+     * ringtones to free resources.
+     * 
+     * @param stopPreviousRingtone If true, the previously retrieved
+     *            {@link Ringtone} will be stopped.
+     */
+    public void setStopPreviousRingtone(boolean stopPreviousRingtone) {
+        mStopPreviousRingtone = stopPreviousRingtone;
+    }
+
+    /**
+     * @see #setStopPreviousRingtone(boolean)
+     */
+    public boolean getStopPreviousRingtone() {
+        return mStopPreviousRingtone;
+    }
+
+    /**
+     * Stops playing the last {@link Ringtone} retrieved from this.
+     */
+    public void stopPreviousRingtone() {
+        if (mPreviousRingtone != null) {
+            mPreviousRingtone.stop();
+        }
+    }
+    
+    /**
+     * Returns whether DRM ringtones will be included.
+     * 
+     * @return Whether DRM ringtones will be included.
+     * @see #setIncludeDrm(boolean)
+     */
+    public boolean getIncludeDrm() {
+        return mIncludeDrm;
+    }
+
+    /**
+     * Sets whether to include DRM ringtones.
+     * 
+     * @param includeDrm Whether to include DRM ringtones.
+     */
+    public void setIncludeDrm(boolean includeDrm) {
+        mIncludeDrm = includeDrm;
+    }
+
+    /**
+     * Returns a {@link Cursor} of all the ringtones available. The returned
+     * cursor will be the same cursor returned each time this method is called,
+     * so do not {@link Cursor#close()} the cursor. The cursor can be
+     * {@link Cursor#deactivate()} safely.
+     * <p>
+     * If {@link RingtoneManager#RingtoneManager(Activity)} was not used, the
+     * caller should manage the returned cursor through its activity's life
+     * cycle to prevent leaking the cursor.
+     * 
+     * @return A {@link Cursor} of all the ringtones available.
+     * @see #ID_COLUMN_INDEX
+     * @see #TITLE_COLUMN_INDEX
+     * @see #URI_COLUMN_INDEX
+     */
+    public Cursor getCursor() {
+        if (mCursor != null && mCursor.requery()) {
+            return mCursor;
+        }
+        
+        final Cursor internalCursor = getInternalRingtones();
+        final Cursor drmCursor = mIncludeDrm ? getDrmRingtones() : null;
+        final Cursor mediaCursor = getMediaRingtones();
+             
+        return mCursor = new SortCursor(new Cursor[] { internalCursor, drmCursor, mediaCursor },
+                MediaStore.MediaColumns.TITLE);
+    }
+
+    /**
+     * Gets a {@link Ringtone} for the ringtone at the given position in the
+     * {@link Cursor}.
+     * 
+     * @param position The position (in the {@link Cursor}) of the ringtone.
+     * @return A {@link Ringtone} pointing to the ringtone.
+     */
+    public Ringtone getRingtone(int position) {
+        if (mStopPreviousRingtone && mPreviousRingtone != null) {
+            mPreviousRingtone.stop();
+        }
+        
+        mPreviousRingtone = getRingtone(mContext, getRingtoneUri(position), inferStreamType());
+        return mPreviousRingtone;
+    }
+
+    /**
+     * Gets a {@link Uri} for the ringtone at the given position in the {@link Cursor}.
+     * 
+     * @param position The position (in the {@link Cursor}) of the ringtone.
+     * @return A {@link Uri} pointing to the ringtone.
+     */
+    public Uri getRingtoneUri(int position) {
+        final Cursor cursor = getCursor();
+        
+        if (!cursor.moveToPosition(position)) {
+            return null;
+        }
+        
+        return getUriFromCursor(cursor);
+    }
+    
+    private static Uri getUriFromCursor(Cursor cursor) {
+        return ContentUris.withAppendedId(Uri.parse(cursor.getString(URI_COLUMN_INDEX)), cursor
+                .getLong(ID_COLUMN_INDEX));
+    }
+    
+    /**
+     * Gets the position of a {@link Uri} within this {@link RingtoneManager}.
+     * 
+     * @param ringtoneUri The {@link Uri} to retreive the position of.
+     * @return The position of the {@link Uri}, or -1 if it cannot be found.
+     */
+    public int getRingtonePosition(Uri ringtoneUri) {
+        
+        if (ringtoneUri == null) return -1;
+        
+        final Cursor cursor = getCursor();
+        final int cursorCount = cursor.getCount();
+        
+        if (!cursor.moveToFirst()) {
+            return -1;
+        }
+        
+        // Only create Uri objects when the actual URI changes
+        Uri currentUri = null;
+        String previousUriString = null;
+        for (int i = 0; i < cursorCount; i++) {
+            String uriString = cursor.getString(URI_COLUMN_INDEX);
+            if (currentUri == null || !uriString.equals(previousUriString)) {
+                currentUri = Uri.parse(uriString);
+            }
+            
+            if (ringtoneUri.equals(ContentUris.withAppendedId(currentUri, cursor
+                    .getLong(ID_COLUMN_INDEX)))) {
+                return i;
+            }
+            
+            cursor.move(1);
+            
+            previousUriString = uriString;
+        }
+        
+        return -1;
+    }
+
+    /**
+     * Returns a valid ringtone URI. No guarantees on which it returns. If it
+     * cannot find one, returns null.
+     * 
+     * @param context The context to use for querying.
+     * @return A ringtone URI, or null if one cannot be found.
+     */
+    public static Uri getValidRingtoneUri(Context context) {
+        final RingtoneManager rm = new RingtoneManager(context);
+        
+        Uri uri = getValidRingtoneUriFromCursorAndClose(context, rm.getInternalRingtones());
+
+        if (uri == null) {
+            uri = getValidRingtoneUriFromCursorAndClose(context, rm.getMediaRingtones());
+        }
+        
+        if (uri == null) {
+            uri = getValidRingtoneUriFromCursorAndClose(context, rm.getDrmRingtones());
+        }
+        
+        return uri;
+    }
+    
+    private static Uri getValidRingtoneUriFromCursorAndClose(Context context, Cursor cursor) {
+        if (cursor != null) {
+            Uri uri = null;
+            
+            if (cursor.moveToFirst()) {
+                uri = getUriFromCursor(cursor);
+            }
+            cursor.close();
+            
+            return uri;
+        } else {
+            return null;
+        }
+    }
+
+    private Cursor getInternalRingtones() {
+        return query(
+                MediaStore.Audio.Media.INTERNAL_CONTENT_URI, INTERNAL_COLUMNS,
+                constructBooleanTrueWhereClause(mFilterColumns),
+                null, MediaStore.Audio.Media.DEFAULT_SORT_ORDER);
+    }
+    
+    private Cursor getDrmRingtones() {
+        // DRM store does not have any columns to use for filtering 
+        return query(
+                DrmStore.Audio.CONTENT_URI, DRM_COLUMNS,
+                null, null, DrmStore.Audio.TITLE);
+    }
+
+    private Cursor getMediaRingtones() {
+         // Get the external media cursor. First check to see if it is mounted.
+        final String status = Environment.getExternalStorageState();
+        
+        return (status.equals(Environment.MEDIA_MOUNTED) ||
+                    status.equals(Environment.MEDIA_MOUNTED_READ_ONLY))
+                ? query(
+                    MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, MEDIA_COLUMNS,
+                    constructBooleanTrueWhereClause(mFilterColumns), null,
+                    MediaStore.Audio.Media.DEFAULT_SORT_ORDER)
+                : null;
+    }
+    
+    private void setFilterColumnsList(int type) {
+        List<String> columns = mFilterColumns;
+        columns.clear();
+        
+        if ((type & TYPE_RINGTONE) != 0) {
+            columns.add(MediaStore.Audio.AudioColumns.IS_RINGTONE);
+        }
+        
+        if ((type & TYPE_NOTIFICATION) != 0) {
+            columns.add(MediaStore.Audio.AudioColumns.IS_NOTIFICATION);
+        }
+        
+        if ((type & TYPE_ALARM) != 0) {
+            columns.add(MediaStore.Audio.AudioColumns.IS_ALARM);
+        }
+    }
+    
+    /**
+     * Constructs a where clause that consists of at least one column being 1
+     * (true). This is used to find all matching sounds for the given sound
+     * types (ringtone, notifications, etc.)
+     * 
+     * @param columns The columns that must be true.
+     * @return The where clause.
+     */
+    private static String constructBooleanTrueWhereClause(List<String> columns) {
+        
+        if (columns == null) return null;
+        
+        StringBuilder sb = new StringBuilder();
+        for (int i = columns.size() - 1; i >= 0; i--) {
+            sb.append(columns.get(i)).append("=1 or ");
+        }
+        
+        if (columns.size() > 0) {
+            // Remove last ' or '
+            sb.setLength(sb.length() - 4);
+        }
+        
+        return sb.toString();
+    }
+    
+    private Cursor query(Uri uri,
+            String[] projection,
+            String selection,
+            String[] selectionArgs,
+            String sortOrder) {
+        if (mActivity != null) {
+            return mActivity.managedQuery(uri, projection, selection, selectionArgs, sortOrder);
+        } else {
+            return mContext.getContentResolver().query(uri, projection, selection, selectionArgs,
+                    sortOrder);
+        }
+    }
+    
+    /**
+     * Returns a {@link Ringtone} for a given sound URI.
+     * <p>
+     * If the given URI cannot be opened for any reason, this method will
+     * attempt to fallback on another sound. If it cannot find any, it will
+     * return null.
+     * 
+     * @param context A context used to query.
+     * @param ringtoneUri The {@link Uri} of a sound or ringtone.
+     * @return A {@link Ringtone} for the given URI, or null.
+     */
+    public static Ringtone getRingtone(final Context context, Uri ringtoneUri) {
+        // Don't set the stream type
+        return getRingtone(context, ringtoneUri, -1);
+    }
+
+    /**
+     * Returns a {@link Ringtone} for a given sound URI on the given stream
+     * type. Normally, if you change the stream type on the returned
+     * {@link Ringtone}, it will re-create the {@link MediaPlayer}. This is just
+     * an optimized route to avoid that.
+     * 
+     * @param streamType The stream type for the ringtone, or -1 if it should
+     *            not be set (and the default used instead).
+     * @see #getRingtone(Context, Uri)
+     */
+    private static Ringtone getRingtone(final Context context, Uri ringtoneUri, int streamType) {
+
+        try {
+            Ringtone r = new Ringtone(context);
+            if (streamType >= 0) {
+                r.setStreamType(streamType);
+            }
+            r.open(ringtoneUri);
+            return r;
+        } catch (Exception ex) {
+            Log.e(TAG, "Failed to open ringtone " + ringtoneUri);
+        }
+
+        // Ringtone doesn't exist, use the fallback ringtone.
+        try {
+            AssetFileDescriptor afd = context.getResources().openRawResourceFd(
+                    com.android.internal.R.raw.fallbackring);
+            if (afd != null) {
+                Ringtone r = new Ringtone(context);
+                r.open(afd);
+                afd.close();
+                return r;
+            }
+        } catch (Exception ex) {
+        }
+        
+        // we should never get here
+        Log.e(TAG, "unable to find a usable ringtone");
+        return null;
+    }
+    
+    /**
+     * Gets the current default sound's {@link Uri}. This will give the actual
+     * sound {@link Uri}, instead of using this, most clients can use
+     * {@link System#DEFAULT_RINGTONE_URI}.
+     * 
+     * @param context A context used for querying.
+     * @param type The type whose default sound should be returned. One of
+     *            {@link #TYPE_RINGTONE} or {@link #TYPE_NOTIFICATION}.
+     * @return A {@link Uri} pointing to the default sound for the sound type.
+     * @see #setActualDefaultRingtoneUri(Context, int, Uri)
+     */
+    public static Uri getActualDefaultRingtoneUri(Context context, int type) {
+        String setting = getSettingForType(type);
+        if (setting == null) return null;
+        final String uriString = Settings.System.getString(context.getContentResolver(), setting); 
+        return uriString != null ? Uri.parse(uriString) : getValidRingtoneUri(context);
+    }
+    
+    /**
+     * Sets the {@link Uri} of the default sound for a given sound type.
+     * 
+     * @param context A context used for querying.
+     * @param type The type whose default sound should be set. One of
+     *            {@link #TYPE_RINGTONE} or {@link #TYPE_NOTIFICATION}.
+     * @param ringtoneUri A {@link Uri} pointing to the default sound to set.
+     * @see #getActualDefaultRingtoneUri(Context, int)
+     */
+    public static void setActualDefaultRingtoneUri(Context context, int type, Uri ringtoneUri) {
+        String setting = getSettingForType(type);
+        if (setting == null) return;
+        Settings.System.putString(context.getContentResolver(), setting, ringtoneUri.toString());
+    }
+    
+    private static String getSettingForType(int type) {
+        if ((type & TYPE_RINGTONE) != 0) {
+            return Settings.System.RINGTONE;
+        } else if ((type & TYPE_NOTIFICATION) != 0) {
+            return Settings.System.NOTIFICATION_SOUND;
+        } else {
+            return null;
+        }
+    }
+    
+    /**
+     * Returns whether the given {@link Uri} is one of the default ringtones.
+     * 
+     * @param ringtoneUri The ringtone {@link Uri} to be checked.
+     * @return Whether the {@link Uri} is a default.
+     */
+    public static boolean isDefault(Uri ringtoneUri) {
+        return getDefaultType(ringtoneUri) != -1;
+    }
+    
+    /**
+     * Returns the type of a default {@link Uri}.
+     * 
+     * @param defaultRingtoneUri The default {@link Uri}. For example,
+     *            {@link System#DEFAULT_RINGTONE_URI} or
+     *            {@link System#DEFAULT_NOTIFICATION_URI}.
+     * @return The type of the defaultRingtoneUri, or -1.
+     */
+    public static int getDefaultType(Uri defaultRingtoneUri) {
+        if (defaultRingtoneUri == null) {
+            return -1;
+        } else if (defaultRingtoneUri.equals(Settings.System.DEFAULT_RINGTONE_URI)) {
+            return TYPE_RINGTONE;
+        } else if (defaultRingtoneUri.equals(Settings.System.DEFAULT_NOTIFICATION_URI)) {
+            return TYPE_NOTIFICATION;
+        } else {
+            return -1;
+        }
+    }
+ 
+    /**
+     * Returns the {@link Uri} for the default ringtone of a particular type.
+     * Rather than returning the actual ringtone's sound {@link Uri}, this will
+     * return the symbolic {@link Uri} which will resolved to the actual sound
+     * when played.
+     * 
+     * @param type The ringtone type whose default should be returned.
+     * @return The {@link Uri} of the default ringtone for the given type.
+     */
+    public static Uri getDefaultUri(int type) {
+        if ((type & TYPE_RINGTONE) != 0) {
+            return Settings.System.DEFAULT_RINGTONE_URI;
+        } else if ((type & TYPE_NOTIFICATION) != 0) {
+            return Settings.System.DEFAULT_NOTIFICATION_URI;
+        } else {
+            return null;
+        }
+    }
+    
+}
diff --git a/media/java/android/media/SoundPool.java b/media/java/android/media/SoundPool.java
new file mode 100644
index 0000000..000430f
--- /dev/null
+++ b/media/java/android/media/SoundPool.java
@@ -0,0 +1,127 @@
+/*
+ * 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.
+ */
+
+package android.media;
+
+import android.util.AndroidRuntimeException;
+import android.util.Log;
+import java.io.File;
+import java.io.FileDescriptor;
+import android.os.ParcelFileDescriptor;
+import java.lang.ref.WeakReference;
+import android.content.Context;
+import android.content.res.AssetFileDescriptor;
+import java.io.IOException;
+
+/*
+ * The SoundPool class manages and plays audio resources for applications.
+ */
+public class SoundPool
+{
+    static { System.loadLibrary("soundpool"); }
+
+    private final static String TAG = "SoundPool";
+
+    private int mNativeContext; // accessed by native methods
+
+    public SoundPool(int maxStreams, int streamType, int srcQuality) {
+        native_setup(new WeakReference<SoundPool>(this), maxStreams, streamType, srcQuality);
+    }
+
+    public int load(String path, int priority)
+    {
+        // pass network streams to player
+        if (path.startsWith("http:"))
+            return _load(path, priority);
+
+        // try local path
+        int id = 0;
+        try {
+            File f = new File(path);
+            if (f != null) {
+                ParcelFileDescriptor fd = ParcelFileDescriptor.open(f, ParcelFileDescriptor.MODE_READ_ONLY);
+                if (fd != null) {
+                    id = _load(fd.getFileDescriptor(), 0, f.length(), priority);
+                    //Log.v(TAG, "close fd");
+                    fd.close();
+                }
+            }
+        } catch (java.io.IOException e) {}
+        return id;
+    }
+
+    public int load(Context context, int resId, int priority) {
+        AssetFileDescriptor afd = context.getResources().openRawResourceFd(resId);
+        int id = 0;
+        if (afd != null) {
+            id = _load(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength(), priority);
+            try {
+                //Log.v(TAG, "close fd");
+                afd.close();
+            } catch (java.io.IOException ex) {
+                //Log.d(TAG, "close failed:", ex);
+            }
+        }
+        return id;
+    }
+
+    public int load(AssetFileDescriptor afd, int priority) {
+        if (afd != null) {
+            long len = afd.getLength();
+            if (len < 0) {
+                throw new AndroidRuntimeException("no length for fd");
+            }
+            return _load(afd.getFileDescriptor(), afd.getStartOffset(), len, priority);
+        } else {
+            return 0;
+        }
+    }
+
+    public int load(FileDescriptor fd, long offset, long length, int priority) {
+        return _load(fd, offset, length, priority);
+    }
+
+    private native final int _load(String uri, int priority);
+
+    private native final int _load(FileDescriptor fd, long offset, long length, int priority);
+
+    public native final boolean unload(int soundID);
+
+    public native final int play(int soundID, float leftVolume, float rightVolume,
+            int priority, int loop, float rate);
+
+    public native final void pause(int streamID);
+
+    public native final void resume(int streamID);
+
+    public native final void stop(int streamID);
+
+    public native final void setVolume(int streamID,
+            float leftVolume, float rightVolume);
+
+    public native final void setPriority(int streamID, int priority);
+
+    public native final void setLoop(int streamID, int loop);
+
+    public native final void setRate(int streamID, float rate);
+
+    public native final void release();
+
+    private native final void native_setup(Object mediaplayer_this,
+            int maxStreams, int streamType, int srcQuality);
+
+    protected void finalize() { release(); }
+}
diff --git a/media/java/android/media/ToneGenerator.java b/media/java/android/media/ToneGenerator.java
new file mode 100644
index 0000000..0901fbf
--- /dev/null
+++ b/media/java/android/media/ToneGenerator.java
@@ -0,0 +1,286 @@
+/*
+ * 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.
+ */
+
+package android.media;
+
+
+
+/**
+ * This class provides methods to play DTMF tones (ITU-T Recommendation Q.23), 
+ * call supervisory tones (3GPP TS 22.001, CEPT) and proprietary tones (3GPP TS 31.111). 
+ * Depending on call state and routing options, tones are mixed to the downlink audio
+ * or output to the speaker phone or headset. 
+ * This API is not for generating tones over the uplink audio path.   
+ */
+public class ToneGenerator
+{
+
+    /* Values for toneType parameter of ToneGenerator() constructor */
+    /*
+     * List of all available tones: These constants must be kept consistant with
+     * the enum in ToneGenerator C++ class.     */
+
+	/**
+     * DTMF tone for key 0: 1336Hz, 941Hz, continuous</p>
+     * 
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_DTMF_0 = 0;
+    /**
+     * DTMF tone for key 1: 1209Hz, 697Hz, continuous
+     * 
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_DTMF_1 = 1;
+    /**
+     * DTMF tone for key 2: 1336Hz, 697Hz, continuous
+     * 
+     * @see #ToneGenerator(int, int)
+     */
+   public static final int TONE_DTMF_2 = 2;
+   /**
+    * DTMF tone for key 3: 1477Hz, 697Hz, continuous
+    * 
+    * @see #ToneGenerator(int, int)
+    */
+    public static final int TONE_DTMF_3 = 3;
+    /**
+     * DTMF tone for key 4: 1209Hz, 770Hz, continuous
+     * 
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_DTMF_4 = 4;
+    /**
+     * DTMF tone for key 5: 1336Hz, 770Hz, continuous
+     * 
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_DTMF_5 = 5;
+    /**
+     * DTMF tone for key 6: 1477Hz, 770Hz, continuous
+     * 
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_DTMF_6 = 6;
+    /**
+     * DTMF tone for key 7: 1209Hz, 852Hz, continuous
+     * 
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_DTMF_7 = 7;
+    /**
+     * DTMF tone for key 8: 1336Hz, 852Hz, continuous
+     * 
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_DTMF_8 = 8;
+    /**
+     * DTMF tone for key 9: 1477Hz, 852Hz, continuous
+     * 
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_DTMF_9 = 9;
+    /**
+     * DTMF tone for key *: 1209Hz, 941Hz, continuous
+     * 
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_DTMF_S = 10;
+    /**
+     * DTMF tone for key #: 1477Hz, 941Hz, continuous
+     * 
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_DTMF_P = 11;
+    /**
+     * DTMF tone for key A: 1633Hz, 697Hz, continuous
+     * 
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_DTMF_A = 12;
+    /**
+     * DTMF tone for key B: 1633Hz, 770Hz, continuous
+     * 
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_DTMF_B = 13;
+    /**
+     * DTMF tone for key C: 1633Hz, 852Hz, continuous
+     * 
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_DTMF_C = 14;
+    /**
+     * DTMF tone for key D: 1633Hz, 941Hz, continuous
+     * 
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_DTMF_D = 15;
+    /**
+     * Call supervisory tone, Dial tone: 425Hz, continuous
+     * 
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_SUP_DIAL = 16;
+    /**
+     * Call supervisory tone, Busy: 425Hz, 500ms ON, 500ms OFF...
+     * 
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_SUP_BUSY = 17;
+    /**
+     * Call supervisory tone, Congestion: 425Hz, 200ms ON, 200ms OFF...
+     * 
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_SUP_CONGESTION = 18;
+    /**
+     * Call supervisory tone, Radio path acknowlegment : 425Hz, 200ms ON
+     * 
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_SUP_RADIO_ACK = 19;
+    /**
+     * Call supervisory tone, Radio path not available: 425Hz, 200ms ON, 200 OFF 3 bursts
+     * 
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_SUP_RADIO_NOTAVAIL = 20;
+    /**
+     * Call supervisory tone, Error/Special info: 950Hz+1400Hz+1800Hz, 330ms ON, 1s OFF...
+     * 
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_SUP_ERROR = 21;
+    /**
+     * Call supervisory tone, Call Waiting: 425Hz, 200ms ON, 600ms OFF, 200ms ON, 3s OFF...
+     * 
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_SUP_CALL_WAITING = 22;
+    /**
+     * Call supervisory tone, Ring Tone: 425Hz, 1s ON, 4s OFF...
+     * 
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_SUP_RINGTONE = 23;
+    /**
+     * Proprietary tone, general beep: 400Hz+1200Hz, 35ms ON
+     * 
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_PROP_BEEP = 24;
+    /**
+     * Proprietary tone, positive acknowlegement: 1200Hz, 100ms ON, 100ms OFF 2 bursts
+     * 
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_PROP_ACK = 25;
+    /**
+     * Proprietary tone, negative acknowlegement: 300Hz+400Hz+500Hz, 400ms ON
+     * 
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_PROP_NACK = 26;
+    /**
+     * Proprietary tone, prompt tone: 400Hz+1200Hz, 200ms ON
+     * 
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int  TONE_PROP_PROMPT = 27;
+    /**
+     * Proprietary tone, general double beep: twice 400Hz+1200Hz, 35ms ON, 200ms OFF, 35ms ON
+     * 
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_PROP_BEEP2 = 28;
+
+    /** Maximum volume, for use with {@link #ToneGenerator(int,int)} */
+    public static final int MAX_VOLUME = AudioSystem.MAX_VOLUME;
+    /** Minimum volume setting, for use with {@link #ToneGenerator(int,int)} */
+    public static final int MIN_VOLUME = AudioSystem.MIN_VOLUME;
+
+
+    /**
+     * ToneGenerator class contructor specifying output stream type and volume.
+     * 
+     * @param streamType The streame type used for tone playback (e.g. STREAM_MUSIC).
+     * @param volume     The volume of the tone, given in percentage of maximum volume (from 0-100).
+     * 
+     */
+    public ToneGenerator(int streamType, int volume) {
+        native_setup(streamType, volume);
+    }
+
+    /**
+     * This method starts the playback of a tone of the specified type.
+     * only one tone can play at a time: if a tone is playing while this method is called, 
+     * this tone is stopped and replaced by the one requested.
+     * @param toneType   The type of tone generate chosen from the following list:
+     * <ul>
+     * <li>{@link #TONE_DTMF_0}
+     * <li>{@link #TONE_DTMF_1}
+     * <li>{@link #TONE_DTMF_2}
+     * <li>{@link #TONE_DTMF_3}
+     * <li>{@link #TONE_DTMF_4}
+     * <li>{@link #TONE_DTMF_5}
+     * <li>{@link #TONE_DTMF_6}
+     * <li>{@link #TONE_DTMF_7}
+     * <li>{@link #TONE_DTMF_8}
+     * <li>{@link #TONE_DTMF_9}
+     * <li>{@link #TONE_DTMF_A}
+     * <li>{@link #TONE_DTMF_B}
+     * <li>{@link #TONE_DTMF_C}
+     * <li>{@link #TONE_DTMF_D}
+     * <li>{@link #TONE_SUP_DIAL}
+     * <li>{@link #TONE_SUP_BUSY}
+     * <li>{@link #TONE_SUP_CONGESTION}
+     * <li>{@link #TONE_SUP_RADIO_ACK}
+     * <li>{@link #TONE_SUP_RADIO_NOTAVAIL}
+     * <li>{@link #TONE_SUP_ERROR}
+     * <li>{@link #TONE_SUP_CALL_WAITING}
+     * <li>{@link #TONE_SUP_RINGTONE}
+     * <li>{@link #TONE_PROP_BEEP}
+     * <li>{@link #TONE_PROP_ACK}
+     * <li>{@link #TONE_PROP_NACK}
+     * <li>{@link #TONE_PROP_PROMPT}
+     * <li>{@link #TONE_PROP_BEEP2}
+     * </ul>
+     * @see #ToneGenerator(int, int)
+    */
+    public native boolean startTone(int toneType);
+
+    /**
+     * This method stops the tone currently playing playback.
+     * @see #ToneGenerator(int, int)
+     */
+    public native void stopTone();
+
+    /**
+     * Releases resources associated with this ToneGenerator object. It is good
+     * practice to call this method when you're done using the ToneGenerator.
+     */
+    public native void release();
+
+    private native final void native_setup(int streamType, int volume);
+
+    private native final void native_finalize();
+    protected void finalize() { native_finalize(); }
+
+    private int mNativeContext; // accessed by native methods
+
+
+}
diff --git a/media/java/android/media/package.html b/media/java/android/media/package.html
new file mode 100644
index 0000000..3de7167
--- /dev/null
+++ b/media/java/android/media/package.html
@@ -0,0 +1,13 @@
+<HTML>
+<BODY>
+Provides classes that manage various media interfaces in audio and video.
+<p>The Media APIs are used to play and, in some cases, record media files. This includes
+audio (e.g., play MP3s or other music files, ringtones, game sound effects, or DTMF tones)
+and video (e.g., play a video streamed over the web or from local storage).
+</p>
+<p>Other special classes in the package offer the ability to detect the faces of people 
+in Bitmaps ({@link android.media.FaceDetector}), control audio routing (to the device or a headset)
+and control alerts such as ringtones and phone vibrations ({@link android.media.AudioManager}).
+</p>
+</BODY>
+</HTML>
diff --git a/media/jni/Android.mk b/media/jni/Android.mk
new file mode 100644
index 0000000..3620494
--- /dev/null
+++ b/media/jni/Android.mk
@@ -0,0 +1,42 @@
+ifneq ($(BUILD_WITHOUT_PV),true)
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+	android_media_MediaPlayer.cpp \
+	android_media_MediaRecorder.cpp \
+	android_media_MediaScanner.cpp \
+	android_media_MediaMetadataRetriever.cpp \
+	android_media_AmrInputStream.cpp \
+	android_media_ResampleInputStream.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+	libopencoreplayer \
+	libopencoreauthor \
+	libandroid_runtime \
+	libnativehelper \
+	libcutils \
+	libutils \
+	libmedia \
+	libsgl \
+	libui
+
+LOCAL_STATIC_LIBRARIES :=
+
+LOCAL_C_INCLUDES += \
+	external/tremor/Tremor \
+	$(PV_INCLUDES) \
+	$(JNI_H_INCLUDE) \
+	$(call include-path-for, corecg graphics)
+
+LOCAL_CFLAGS +=
+
+LOCAL_LDLIBS := -lpthread
+
+LOCAL_MODULE:= libmedia_jni
+
+include $(BUILD_SHARED_LIBRARY)
+
+# build libsoundpool.so
+include $(LOCAL_PATH)/soundpool/Android.mk
+endif
diff --git a/media/jni/MODULE_LICENSE_APACHE2 b/media/jni/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/media/jni/MODULE_LICENSE_APACHE2
diff --git a/media/jni/NOTICE b/media/jni/NOTICE
new file mode 100644
index 0000000..c5b1efa
--- /dev/null
+++ b/media/jni/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/jni/android_media_AmrInputStream.cpp b/media/jni/android_media_AmrInputStream.cpp
new file mode 100644
index 0000000..978c110
--- /dev/null
+++ b/media/jni/android_media_AmrInputStream.cpp
@@ -0,0 +1,184 @@
+/*
+**
+** 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 "AmrInputStream"
+#include "utils/Log.h"
+
+#include <media/mediarecorder.h>
+#include <stdio.h>
+#include <assert.h>
+#include <limits.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <utils/threads.h>
+
+#include "jni.h"
+#include "JNIHelp.h"
+#include "android_runtime/AndroidRuntime.h"
+#include "gsmamr_encoder_wrapper.h"
+
+
+// ----------------------------------------------------------------------------
+
+using namespace android;
+
+// Corresponds to max bit rate of 12.2 kbps.
+static const int aMaxOutputBufferSize = 32;
+
+static const int SAMPLES_PER_FRAME = 8000 * 20 / 1000;
+
+
+//
+// helper function to throw an exception
+//
+static void throwException(JNIEnv *env, const char* ex, const char* fmt, int data) {
+    if (jclass cls = env->FindClass(ex)) {
+        char msg[1000];
+        sprintf(msg, fmt, data);
+        env->ThrowNew(cls, msg);
+        env->DeleteLocalRef(cls);
+    }
+}
+
+static jint android_media_AmrInputStream_GsmAmrEncoderNew
+        (JNIEnv *env, jclass clazz) {
+    CPvGsmAmrEncoder* gae = new CPvGsmAmrEncoder();
+    if (gae == NULL) {
+        throwException(env, "java/lang/IllegalStateException",
+                "new CPvGsmAmrEncoder() failed", 0);
+    }
+    return (jint)gae;
+}
+
+static void android_media_AmrInputStream_GsmAmrEncoderInitialize
+        (JNIEnv *env, jclass clazz, jint gae) {
+    // set input parameters
+    TEncodeProperties encodeProps;
+    encodeProps.iInBitsPerSample = 16;
+    encodeProps.iInSamplingRate = 8000;
+    encodeProps.iInClockRate = 1000;
+    encodeProps.iInNumChannels = 1;
+    encodeProps.iInInterleaveMode = TEncodeProperties::EINTERLEAVE_LR;
+    encodeProps.iMode = CPvGsmAmrEncoder::GSM_AMR_12_2;
+    encodeProps.iBitStreamFormatIf2 = false;
+    encodeProps.iAudioObjectType = 0;
+    encodeProps.iOutSamplingRate = encodeProps.iInSamplingRate;
+    encodeProps.iOutNumChannels = encodeProps.iInNumChannels;
+    encodeProps.iOutClockRate = encodeProps.iInClockRate;
+
+    if (int rtn = ((CPvGsmAmrEncoder*)gae)->
+            InitializeEncoder(aMaxOutputBufferSize, &encodeProps)) {
+        throwException(env, "java/lang/IllegalArgumentException",
+                "CPvGsmAmrEncoder::InitializeEncoder failed %d", rtn);
+    }
+}
+
+static jint android_media_AmrInputStream_GsmAmrEncoderEncode
+        (JNIEnv *env, jclass clazz,
+         jint gae, jbyteArray pcm, jint pcmOffset, jbyteArray amr, jint amrOffset) {
+
+    // set up input stream
+    jbyte inBuf[SAMPLES_PER_FRAME*2];
+    TInputAudioStream in;
+    in.iSampleBuffer = (uint8*)inBuf;
+    env->GetByteArrayRegion(pcm, pcmOffset, sizeof(inBuf), inBuf);
+    in.iSampleLength = sizeof(inBuf);
+    in.iMode = CPvGsmAmrEncoder::GSM_AMR_12_2;
+    in.iStartTime = 0;
+    in.iStopTime = 0;
+
+    // set up output stream
+    jbyte outBuf[aMaxOutputBufferSize];
+    int32 sampleFrameSize[1] = { 0 };
+    TOutputAudioStream out;
+    out.iBitStreamBuffer = (uint8*)outBuf;
+    out.iNumSampleFrames = 0;
+    out.iSampleFrameSize = sampleFrameSize;
+    out.iStartTime = 0;
+    out.iStopTime = 0;
+
+    // encode
+    if (int rtn = ((CPvGsmAmrEncoder*)gae)->Encode(in, out)) {
+        throwException(env, "java/io/IOException", "CPvGsmAmrEncoder::Encode failed %d", rtn);
+        return -1;
+    }
+
+    // validate one-frame assumption
+    if (out.iNumSampleFrames != 1) {
+        throwException(env, "java/io/IOException",
+                "CPvGsmAmrEncoder::Encode more than one frame returned %d", out.iNumSampleFrames);
+        return 0;
+    }
+
+    // copy result
+    int length = out.iSampleFrameSize[0];
+
+    // The 1st byte of PV AMR frames are WMF (Wireless Multimedia Forum)
+    // bitpacked, i.e.;
+    //    [P(4) + FT(4)]. Q=1 for good frame, P=padding bit, 0
+    // Here we are converting the header to be as specified in Section 5.3 of
+    // RFC 3267 (AMR storage format) i.e.
+    //    [P(1) + FT(4) + Q(1) + P(2)].
+    if (length > 0) {
+      outBuf[0] = (outBuf[0] << 3) | 0x4;
+    }
+
+    env->SetByteArrayRegion(amr, amrOffset, length, outBuf);
+
+    return length;
+}
+
+static void android_media_AmrInputStream_GsmAmrEncoderCleanup
+        (JNIEnv *env, jclass clazz, jint gae) {
+    if (int rtn = ((CPvGsmAmrEncoder*)gae)->CleanupEncoder()) {
+        throwException(env, "java/lang/IllegalStateException",
+                "CPvGsmAmrEncoder::CleanupEncoder failed %d", rtn);
+    }
+}
+
+static void android_media_AmrInputStream_GsmAmrEncoderDelete
+        (JNIEnv *env, jclass clazz, jint gae) {
+    delete (CPvGsmAmrEncoder*)gae;
+}
+
+// ----------------------------------------------------------------------------
+
+static JNINativeMethod gMethods[] = {
+    {"GsmAmrEncoderNew",        "()I",        (void*)android_media_AmrInputStream_GsmAmrEncoderNew},
+    {"GsmAmrEncoderInitialize", "(I)V",       (void*)android_media_AmrInputStream_GsmAmrEncoderInitialize},
+    {"GsmAmrEncoderEncode",     "(I[BI[BI)I", (void*)android_media_AmrInputStream_GsmAmrEncoderEncode},
+    {"GsmAmrEncoderCleanup",    "(I)V",       (void*)android_media_AmrInputStream_GsmAmrEncoderCleanup},
+    {"GsmAmrEncoderDelete",     "(I)V",       (void*)android_media_AmrInputStream_GsmAmrEncoderDelete},
+};
+
+
+int register_android_media_AmrInputStream(JNIEnv *env)
+{
+    const char* const kClassPathName = "android/media/AmrInputStream";
+    jclass clazz;
+
+    clazz = env->FindClass(kClassPathName);
+    if (clazz == NULL) {
+        LOGE("Can't find %s", kClassPathName);
+        return -1;
+    }
+
+    return AndroidRuntime::registerNativeMethods(env,
+            kClassPathName, gMethods, NELEM(gMethods));
+}
+
+
diff --git a/media/jni/android_media_MediaMetadataRetriever.cpp b/media/jni/android_media_MediaMetadataRetriever.cpp
new file mode 100644
index 0000000..4624a18
--- /dev/null
+++ b/media/jni/android_media_MediaMetadataRetriever.cpp
@@ -0,0 +1,327 @@
+/*
+**
+** 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_NDEBUG 0
+#define LOG_TAG "MediaMetadataRetrieverJNI"
+
+#include <assert.h>
+#include <utils/Log.h>
+#include <utils/threads.h>
+#include <core/SkBitmap.h>
+#include <media/mediametadataretriever.h>
+#include <private/media/VideoFrame.h>
+
+#include "jni.h"
+#include "JNIHelp.h"
+#include "android_runtime/AndroidRuntime.h"
+
+
+using namespace android;
+
+struct fields_t {
+    jfieldID context;
+    jclass bitmapClazz;
+    jmethodID bitmapConstructor;
+};
+
+static fields_t fields;
+static Mutex sLock;
+
+static void process_media_retriever_call(JNIEnv *env, status_t opStatus, const char* exception, const char *message)
+{
+    if (opStatus == (status_t) INVALID_OPERATION) {
+        jniThrowException(env, "java/lang/IllegalStateException", NULL);
+    } else if (opStatus != (status_t) OK) {
+        if (strlen(message) > 230) {
+            // If the message is too long, don't bother displaying the status code.
+            jniThrowException( env, exception, message);
+        } else {
+            char msg[256];
+            // Append the status code to the message.
+            sprintf(msg, "%s: status = 0x%X", message, opStatus);
+            jniThrowException( env, exception, msg);
+        }
+    }
+}
+
+static MediaMetadataRetriever* getRetriever(JNIEnv* env, jobject thiz)
+{
+    // No lock is needed, since it is called internally by other methods that are protected
+    MediaMetadataRetriever* retriever = (MediaMetadataRetriever*) env->GetIntField(thiz, fields.context);
+    return retriever;
+}
+
+static void setRetriever(JNIEnv* env, jobject thiz, int retriever)
+{
+    // No lock is needed, since it is called internally by other methods that are protected
+    MediaMetadataRetriever *old = (MediaMetadataRetriever*) env->GetIntField(thiz, fields.context);
+    env->SetIntField(thiz, fields.context, retriever);
+}
+
+static void android_media_MediaMetadataRetriever_setDataSource(JNIEnv *env, jobject thiz, jstring path)
+{
+    LOGV("setDataSource");
+    Mutex::Autolock lock(sLock);
+    MediaMetadataRetriever* retriever = getRetriever(env, thiz);
+    if (retriever == 0) {
+        jniThrowException(env, "java/lang/IllegalStateException", "No retriever available");
+        return;
+    }
+    if (!path) {
+        jniThrowException(env, "java/lang/IllegalArgumentException", "Null pointer");
+        return;
+    }
+
+    const char *pathStr = env->GetStringUTFChars(path, NULL);
+    if (!pathStr) {  // OutOfMemoryError exception already thrown
+        return;
+    }
+
+    // Don't let somebody trick us in to reading some random block of memory
+    if (strncmp("mem://", pathStr, 6) == 0) {
+        jniThrowException(env, "java/lang/IllegalArgumentException", "Invalid pathname");
+        return;
+    }
+
+    process_media_retriever_call(env, retriever->setDataSource(pathStr), "java/lang/RuntimeException", "setDataSource failed");
+    env->ReleaseStringUTFChars(path, pathStr);
+}
+
+static void android_media_MediaMetadataRetriever_setDataSourceFD(JNIEnv *env, jobject thiz, jobject fileDescriptor, jlong offset, jlong length)
+{
+    LOGV("setDataSource");
+    Mutex::Autolock lock(sLock);
+    MediaMetadataRetriever* retriever = getRetriever(env, thiz);
+    if (retriever == 0) {
+        jniThrowException(env, "java/lang/IllegalStateException", "No retriever available");
+        return;
+    }
+    if (!fileDescriptor) {
+        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
+        return;
+    }
+    int fd = getParcelFileDescriptorFD(env, fileDescriptor);
+    if (offset < 0 || length < 0 || fd < 0) {
+        if (offset < 0) {
+            LOGE("negative offset (%lld)", offset);
+        }
+        if (length < 0) {
+            LOGE("negative length (%lld)", length);
+        }
+        if (fd < 0) {
+            LOGE("invalid file descriptor");
+        }
+        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
+        return;
+    }
+    process_media_retriever_call(env, retriever->setDataSource(fd, offset, length), "java/lang/RuntimeException", "setDataSource failed");
+}
+
+static void android_media_MediaMetadataRetriever_setMode(JNIEnv *env, jobject thiz, jint mode)
+{
+    LOGV("setMode");
+    Mutex::Autolock lock(sLock);
+    MediaMetadataRetriever* retriever = getRetriever(env, thiz);
+    if (retriever == 0) {
+        jniThrowException(env, "java/lang/IllegalStateException", "No retriever available");
+        return;
+    }
+    process_media_retriever_call(env, retriever->setMode(mode), "java/lang/RuntimeException", "setMode failed");
+}
+
+static int android_media_MediaMetadataRetriever_getMode(JNIEnv *env, jobject thiz)
+{
+    LOGV("getMode");
+    Mutex::Autolock lock(sLock);
+    MediaMetadataRetriever* retriever = getRetriever(env, thiz);
+    if (retriever == 0) {
+        jniThrowException(env, "java/lang/IllegalStateException", "No retriever available");
+        return -1;  // Error
+    }
+    int mode = -1;
+    retriever->getMode(&mode);
+    return mode;
+}
+
+static jobject android_media_MediaMetadataRetriever_captureFrame(JNIEnv *env, jobject thiz)
+{
+    LOGV("captureFrame");
+    Mutex::Autolock lock(sLock);
+    MediaMetadataRetriever* retriever = getRetriever(env, thiz);
+    if (retriever == 0) {
+        jniThrowException(env, "java/lang/IllegalStateException", "No retriever available");
+        return NULL;
+    }
+
+    // Call native method to retrieve a video frame
+    VideoFrame *videoFrame = NULL;
+    sp<IMemory> frameMemory = retriever->captureFrame();
+    if (frameMemory != 0) {  // cast the shared structure to a VideoFrame object
+        videoFrame = static_cast<VideoFrame *>(frameMemory->pointer());
+    }
+    if (videoFrame == NULL) {
+        LOGE("captureFrame: videoFrame is a NULL pointer");
+        return NULL;
+    }
+
+    // Create a SkBitmap to hold the pixels
+    SkBitmap *bitmap = new SkBitmap();
+    if (bitmap == NULL) {
+        LOGE("captureFrame: cannot instantiate a SkBitmap object.");
+        return NULL;
+    }
+    bitmap->setConfig(SkBitmap::kRGB_565_Config, videoFrame->mDisplayWidth, videoFrame->mDisplayHeight);
+    if (!bitmap->allocPixels()) {
+        delete bitmap;
+        LOGE("failed to allocate pixel buffer");
+        return NULL;
+    }
+    memcpy((uint8_t*)bitmap->getPixels(), (uint8_t*)videoFrame + sizeof(VideoFrame), videoFrame->mSize);
+
+    // Since internally SkBitmap uses reference count to manage the reference to
+    // its pixels, it is important that the pixels (along with SkBitmap) be
+    // available after creating the Bitmap is returned to Java app.
+    return env->NewObject(fields.bitmapClazz, fields.bitmapConstructor, (int) bitmap, true, NULL);
+}
+
+static jbyteArray android_media_MediaMetadataRetriever_extractAlbumArt(JNIEnv *env, jobject thiz)
+{
+    LOGV("extractAlbumArt");
+    Mutex::Autolock lock(sLock);
+    MediaMetadataRetriever* retriever = getRetriever(env, thiz);
+    if (retriever == 0) {
+        jniThrowException(env, "java/lang/IllegalStateException", "No retriever available");
+        return NULL;
+    }
+    MediaAlbumArt* mediaAlbumArt = NULL;
+    sp<IMemory> albumArtMemory = retriever->extractAlbumArt();
+    if (albumArtMemory != 0) {  // cast the shared structure to a MediaAlbumArt object
+        mediaAlbumArt = static_cast<MediaAlbumArt *>(albumArtMemory->pointer());
+    }
+    if (mediaAlbumArt == NULL) {
+        LOGE("extractAlbumArt: Call to extractAlbumArt failed.");
+        return NULL;
+    }
+
+    unsigned int len = mediaAlbumArt->mSize;
+    char* data = (char*) mediaAlbumArt + sizeof(MediaAlbumArt);
+    jbyteArray array = env->NewByteArray(len);
+    if (!array) {  // OutOfMemoryError exception has already been thrown.
+        LOGE("extractAlbumArt: OutOfMemoryError is thrown.");
+    } else {
+        jbyte* bytes = env->GetByteArrayElements(array, NULL);
+        if (bytes != NULL) {
+            memcpy(bytes, data, len);
+            env->ReleaseByteArrayElements(array, bytes, 0);
+        }
+    }
+
+    // No need to delete mediaAlbumArt here
+    return array;
+}
+
+static jobject android_media_MediaMetadataRetriever_extractMetadata(JNIEnv *env, jobject thiz, jint keyCode)
+{
+    LOGV("extractMetadata");
+    Mutex::Autolock lock(sLock);
+    MediaMetadataRetriever* retriever = getRetriever(env, thiz);
+    if (retriever == 0) {
+        jniThrowException(env, "java/lang/IllegalStateException", "No retriever available");
+        return NULL;
+    }
+    const char* value = retriever->extractMetadata(keyCode);
+    if (!value) {
+        LOGV("extractMetadata: Metadata is not found");
+        return NULL;
+    }
+    LOGV("extractMetadata: value (%s) for keyCode(%d)", value, keyCode);
+    return env->NewStringUTF(value);
+}
+
+static void android_media_MediaMetadataRetriever_release(JNIEnv *env, jobject thiz)
+{
+    LOGV("release");
+    Mutex::Autolock lock(sLock);
+    MediaMetadataRetriever* retriever = getRetriever(env, thiz);
+    delete retriever;
+    setRetriever(env, thiz, 0);
+}
+
+static void android_media_MediaMetadataRetriever_native_finalize(JNIEnv *env, jobject thiz)
+{
+    LOGV("native_finalize");
+    
+    // No lock is needed, since android_media_MediaMetadataRetriever_release() is protected
+    android_media_MediaMetadataRetriever_release(env, thiz);
+}
+
+static void android_media_MediaMetadataRetriever_native_setup(JNIEnv *env, jobject thiz)
+{
+    LOGV("native_setup");
+    MediaMetadataRetriever* retriever = new MediaMetadataRetriever();
+    if (retriever == 0) {
+        jniThrowException(env, "java/lang/RuntimeException", "Out of memory");
+        return;
+    }
+    setRetriever(env, thiz, (int)retriever);
+}
+
+// JNI mapping between Java methods and native methods
+static JNINativeMethod nativeMethods[] = {
+        {"setDataSource",   "(Ljava/lang/String;)V", (void *)android_media_MediaMetadataRetriever_setDataSource},
+        {"setDataSource",   "(Ljava/io/FileDescriptor;JJ)V", (void *)android_media_MediaMetadataRetriever_setDataSourceFD},
+        {"setMode",         "(I)V", (void *)android_media_MediaMetadataRetriever_setMode},
+        {"getMode",         "()I",  (void *)android_media_MediaMetadataRetriever_getMode},
+        {"captureFrame",    "()Landroid/graphics/Bitmap;", (void *)android_media_MediaMetadataRetriever_captureFrame},
+        {"extractMetadata", "(I)Ljava/lang/String;", (void *)android_media_MediaMetadataRetriever_extractMetadata},
+        {"extractAlbumArt", "()[B", (void *)android_media_MediaMetadataRetriever_extractAlbumArt},
+        {"release",         "()V", (void *)android_media_MediaMetadataRetriever_release},
+        {"native_finalize", "()V", (void *)android_media_MediaMetadataRetriever_native_finalize},
+        {"native_setup",    "()V", (void *)android_media_MediaMetadataRetriever_native_setup},
+};
+
+// Register native mehtods with Android runtime environment
+int register_android_media_MediaMetadataRetriever(JNIEnv *env)
+{
+    static const char* const kClassPathName = "android/media/MediaMetadataRetriever";
+    jclass clazz = env->FindClass(kClassPathName);
+    if (clazz == NULL) {
+        LOGE("Can't find class: %s", kClassPathName);
+        return -1;
+    }
+
+    fields.context = env->GetFieldID(clazz, "mNativeContext", "I");
+    if (fields.context == NULL) {
+        LOGE("Can't find MediaMetadataRetriever.mNativeContext");
+        return -1;
+    }
+
+    fields.bitmapClazz = env->FindClass("android/graphics/Bitmap");
+    if (fields.bitmapClazz == NULL) {
+        LOGE("Bitmap class is not found");
+        return -1;
+    }
+
+    fields.bitmapConstructor = env->GetMethodID(fields.bitmapClazz, "<init>", "(IZ[B)V");
+    if (fields.bitmapConstructor == NULL) {
+        LOGE("Bitmap constructor is not found");
+        return -1;
+    }
+
+    return AndroidRuntime::registerNativeMethods
+    (env, kClassPathName, nativeMethods, NELEM(nativeMethods));
+}
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
new file mode 100644
index 0000000..5562254
--- /dev/null
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -0,0 +1,573 @@
+/* //device/libs/android_runtime/android_media_MediaPlayer.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 "MediaPlayer-JNI"
+#include "utils/Log.h"
+
+#include <media/mediaplayer.h>
+#include <stdio.h>
+#include <assert.h>
+#include <limits.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <utils/threads.h>
+#include "jni.h"
+#include "JNIHelp.h"
+#include "android_runtime/AndroidRuntime.h"
+
+
+// ----------------------------------------------------------------------------
+
+using namespace android;
+
+// ----------------------------------------------------------------------------
+
+struct fields_t {
+    jfieldID    context;
+    jfieldID    surface;
+    /* actually in android.view.Surface XXX */
+    jfieldID    surface_native;
+
+    jmethodID   post_event;
+};
+static fields_t fields;
+
+static Mutex sLock;
+
+// ----------------------------------------------------------------------------
+// ref-counted object for callbacks
+class JNIMediaPlayerListener: public MediaPlayerListener
+{
+public:
+    JNIMediaPlayerListener(JNIEnv* env, jobject thiz, jobject weak_thiz);
+    ~JNIMediaPlayerListener();
+    void notify(int msg, int ext1, int ext2);
+private:
+    JNIMediaPlayerListener();
+    jclass      mClass;     // Reference to MediaPlayer class
+    jobject     mObject;    // Weak ref to MediaPlayer Java object to call on
+};
+
+JNIMediaPlayerListener::JNIMediaPlayerListener(JNIEnv* env, jobject thiz, jobject weak_thiz)
+{
+
+    // Hold onto the MediaPlayer class for use in calling the static method
+    // that posts events to the application thread.
+    jclass clazz = env->GetObjectClass(thiz);
+    if (clazz == NULL) {
+        LOGE("Can't find android/media/MediaPlayer");
+        jniThrowException(env, "java/lang/Exception", NULL);
+        return;
+    }
+    mClass = (jclass)env->NewGlobalRef(clazz);
+
+    // We use a weak reference so the MediaPlayer object can be garbage collected.
+    // The reference is only used as a proxy for callbacks.
+    mObject  = env->NewGlobalRef(weak_thiz);
+}
+
+JNIMediaPlayerListener::~JNIMediaPlayerListener()
+{
+    // remove global references
+    JNIEnv *env = AndroidRuntime::getJNIEnv();
+    env->DeleteGlobalRef(mObject);
+    env->DeleteGlobalRef(mClass);
+}
+
+void JNIMediaPlayerListener::notify(int msg, int ext1, int ext2)
+{
+    JNIEnv *env = AndroidRuntime::getJNIEnv();
+    env->CallStaticVoidMethod(mClass, fields.post_event, mObject, msg, ext1, ext2, 0);
+}
+
+// ----------------------------------------------------------------------------
+
+static sp<Surface> get_surface(JNIEnv* env, jobject clazz)
+{
+    Surface* const p = (Surface*)env->GetIntField(clazz, fields.surface_native);
+    return sp<Surface>(p);
+}
+
+static sp<MediaPlayer> getMediaPlayer(JNIEnv* env, jobject thiz)
+{
+    Mutex::Autolock l(sLock);
+    MediaPlayer* const p = (MediaPlayer*)env->GetIntField(thiz, fields.context);
+    return sp<MediaPlayer>(p);
+}
+
+static sp<MediaPlayer> setMediaPlayer(JNIEnv* env, jobject thiz, const sp<MediaPlayer>& player)
+{
+    Mutex::Autolock l(sLock);
+    sp<MediaPlayer> old = (MediaPlayer*)env->GetIntField(thiz, fields.context);
+    if (player.get()) {
+        player->incStrong(thiz);
+    }
+    if (old != 0) {
+        old->decStrong(thiz);
+    }
+    env->SetIntField(thiz, fields.context, (int)player.get());
+    return old;
+}
+
+// If exception is NULL and opStatus is not OK, this method sends an error 
+// event to the client application; otherwise, if exception is not NULL and 
+// opStatus is not OK, this method throws the given exception to the client
+// application.
+static void process_media_player_call(JNIEnv *env, jobject thiz, status_t opStatus, const char* exception, const char *message)
+{
+    if (exception == NULL) {  // Don't throw exception. Instead, send an event.
+        if (opStatus != (status_t) OK) {
+            sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
+            if (mp != 0) mp->notify(MEDIA_ERROR, opStatus, 0);
+        }
+    } else {  // Throw exception!
+        if ( opStatus == (status_t) INVALID_OPERATION ) {
+            jniThrowException(env, "java/lang/IllegalStateException", NULL);
+        } else if ( opStatus != (status_t) OK ) {
+            if (strlen(message) > 230) {
+               // if the message is too long, don't bother displaying the status code
+               jniThrowException( env, exception, message);
+            } else {
+               char msg[256];
+                // append the status code to the message
+               sprintf(msg, "%s: status=0x%X", message, opStatus);
+               jniThrowException( env, exception, msg);
+            }
+        }
+    }
+}
+
+static void
+android_media_MediaPlayer_setDataSource(JNIEnv *env, jobject thiz, jstring path)
+{
+    sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
+    if (mp == NULL ) {
+        jniThrowException(env, "java/lang/IllegalStateException", NULL);
+        return;
+    }
+
+    if (path == NULL) {
+        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
+        return;
+    }
+
+    const char *pathStr = env->GetStringUTFChars(path, NULL);
+    if (pathStr == NULL) {  // Out of memory
+        jniThrowException(env, "java/lang/RuntimeException", "Out of memory");
+        return;
+    }
+    status_t opStatus = mp->setDataSource(pathStr);
+
+    // Make sure that local ref is released before a potential exception
+    env->ReleaseStringUTFChars(path, pathStr);
+    process_media_player_call( env, thiz, opStatus, "java/io/IOException", "setDataSource failed." );
+}
+
+static void
+android_media_MediaPlayer_setDataSourceFD(JNIEnv *env, jobject thiz, jobject fileDescriptor, jlong offset, jlong length)
+{
+    sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
+    if (mp == NULL ) {
+        jniThrowException(env, "java/lang/IllegalStateException", NULL);
+        return;
+    }
+
+    if (fileDescriptor == NULL) {
+        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
+        return;
+    }
+    int fd = getParcelFileDescriptorFD(env, fileDescriptor);
+    process_media_player_call( env, thiz, mp->setDataSource(fd, offset, length), "java/io/IOException", "setDataSourceFD failed." );
+}
+
+
+static void
+android_media_MediaPlayer_prepare(JNIEnv *env, jobject thiz)
+{
+    sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
+    if (mp == NULL ) {
+        jniThrowException(env, "java/lang/IllegalStateException", NULL);
+        return;
+    }
+    jobject surface = env->GetObjectField(thiz, fields.surface);
+    if (surface != NULL) {
+        const sp<Surface>& native_surface = get_surface(env, surface);
+        //LOGI("prepare: surface=%p (id=%d)", 
+        //        native_surface.get(), native_surface->ID());
+        mp->setVideoSurface(native_surface);
+    }
+    process_media_player_call( env, thiz, mp->prepare(), "java/io/IOException", "Prepare failed." );
+}
+
+static void
+android_media_MediaPlayer_prepareAsync(JNIEnv *env, jobject thiz)
+{
+    sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
+    if (mp == NULL ) {
+        jniThrowException(env, "java/lang/IllegalStateException", NULL);
+        return;
+    }
+    jobject surface = env->GetObjectField(thiz, fields.surface);
+    if (surface != NULL) {
+        const sp<Surface>& native_surface = get_surface(env, surface);
+        LOGI("prepareAsync: surface=%p (id=%d)", 
+                native_surface.get(), native_surface->ID());
+        mp->setVideoSurface(native_surface);
+    }
+    process_media_player_call( env, thiz, mp->prepareAsync(), "java/io/IOException", "Prepare Async failed." );
+}
+
+static void
+android_media_MediaPlayer_start(JNIEnv *env, jobject thiz)
+{
+    sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
+    if (mp == NULL ) {
+        jniThrowException(env, "java/lang/IllegalStateException", NULL);
+        return;
+    }
+    process_media_player_call( env, thiz, mp->start(), NULL, NULL );
+}
+
+static void
+android_media_MediaPlayer_stop(JNIEnv *env, jobject thiz)
+{
+    sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
+    if (mp == NULL ) {
+        jniThrowException(env, "java/lang/IllegalStateException", NULL);
+        return;
+    }
+    process_media_player_call( env, thiz, mp->stop(), NULL, NULL );    
+}
+
+static void
+android_media_MediaPlayer_pause(JNIEnv *env, jobject thiz)
+{
+    sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
+    if (mp == NULL ) {
+        jniThrowException(env, "java/lang/IllegalStateException", NULL);
+        return;
+    }
+    process_media_player_call( env, thiz, mp->pause(), NULL, NULL );
+}
+
+static jboolean
+android_media_MediaPlayer_isPlaying(JNIEnv *env, jobject thiz)
+{
+    sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
+    if (mp == NULL ) {
+        jniThrowException(env, "java/lang/IllegalStateException", NULL);
+        return false;
+    }
+    return mp->isPlaying();
+}
+
+static void
+android_media_MediaPlayer_seekTo(JNIEnv *env, jobject thiz, int msec)
+{
+    sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
+    if (mp == NULL ) {
+        jniThrowException(env, "java/lang/IllegalStateException", NULL);
+        return;
+    }
+    process_media_player_call( env, thiz, mp->seekTo(msec), NULL, NULL );
+}
+
+static int
+android_media_MediaPlayer_getVideoWidth(JNIEnv *env, jobject thiz)
+{
+    sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
+    if (mp == NULL ) {
+        jniThrowException(env, "java/lang/IllegalStateException", NULL);
+        return 0;
+    }
+    int w;
+    if (0 == mp->getVideoWidth(&w))
+        return w;
+    return 0;
+}
+
+static int
+android_media_MediaPlayer_getVideoHeight(JNIEnv *env, jobject thiz)
+{
+    sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
+    if (mp == NULL ) {
+        jniThrowException(env, "java/lang/IllegalStateException", NULL);
+        return 0;
+    }
+    int h;
+    if (0 == mp->getVideoHeight(&h))
+        return h;
+    return 0;
+}
+
+
+static int
+android_media_MediaPlayer_getCurrentPosition(JNIEnv *env, jobject thiz)
+{
+    sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
+    if (mp == NULL ) {
+        jniThrowException(env, "java/lang/IllegalStateException", NULL);
+        return 0;
+    }
+    int msec;
+    process_media_player_call( env, thiz, mp->getCurrentPosition(&msec), NULL, NULL );
+    return msec;
+}
+
+static int
+android_media_MediaPlayer_getDuration(JNIEnv *env, jobject thiz)
+{
+    sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
+    if (mp == NULL ) {
+        jniThrowException(env, "java/lang/IllegalStateException", NULL);
+        return 0;
+    }
+    int msec;
+    process_media_player_call( env, thiz, mp->getDuration(&msec), NULL, NULL );
+    return msec;
+}
+
+static void
+android_media_MediaPlayer_reset(JNIEnv *env, jobject thiz)
+{
+    sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
+    if (mp == NULL ) {
+        jniThrowException(env, "java/lang/IllegalStateException", NULL);
+        return;
+    }
+    process_media_player_call( env, thiz, mp->reset(), NULL, NULL );
+}
+
+static void
+android_media_MediaPlayer_setAudioStreamType(JNIEnv *env, jobject thiz, int streamtype)
+{
+    sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
+    if (mp == NULL ) {
+        jniThrowException(env, "java/lang/IllegalStateException", NULL);
+        return;
+    }
+    process_media_player_call( env, thiz, mp->setAudioStreamType(streamtype) , NULL, NULL );
+}
+
+static void
+android_media_MediaPlayer_setLooping(JNIEnv *env, jobject thiz, jboolean looping)
+{
+    sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
+    if (mp == NULL ) {
+        jniThrowException(env, "java/lang/IllegalStateException", NULL);
+        return;
+    }
+    process_media_player_call( env, thiz, mp->setLooping(looping), NULL, NULL );
+}
+
+static jboolean
+android_media_MediaPlayer_isLooping(JNIEnv *env, jobject thiz)
+{
+    sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
+    if (mp == NULL ) {
+        jniThrowException(env, "java/lang/IllegalStateException", NULL);
+        return false;
+    }
+    return mp->isLooping();
+}
+
+static void
+android_media_MediaPlayer_setVolume(JNIEnv *env, jobject thiz, float leftVolume, float rightVolume)
+{
+    sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
+    if (mp == NULL ) {
+        jniThrowException(env, "java/lang/IllegalStateException", NULL);
+        return;
+    }
+    process_media_player_call( env, thiz, mp->setVolume(leftVolume, rightVolume), NULL, NULL );
+}
+
+// FIXME: deprecated
+static jobject
+android_media_MediaPlayer_getFrameAt(JNIEnv *env, jobject thiz, jint msec)
+{
+    return NULL;
+}
+
+static void
+android_media_MediaPlayer_native_setup(JNIEnv *env, jobject thiz, jobject weak_this)
+{
+    LOGV("native_setup");
+    sp<MediaPlayer> mp = new MediaPlayer();
+    if (mp == NULL) {
+        jniThrowException(env, "java/lang/RuntimeException", "Out of memory");
+        return;
+    }
+
+    // create new listener and give it to MediaPlayer
+    sp<JNIMediaPlayerListener> listener = new JNIMediaPlayerListener(env, thiz, weak_this);
+    mp->setListener(listener);
+
+    // Stow our new C++ MediaPlayer in an opaque field in the Java object.
+    setMediaPlayer(env, thiz, mp);
+}
+
+static void
+android_media_MediaPlayer_release(JNIEnv *env, jobject thiz)
+{
+    LOGV("release");
+    sp<MediaPlayer> mp = setMediaPlayer(env, thiz, 0);
+    if (mp != NULL) {
+        // this prevents native callbacks after the object is released
+        mp->setListener(0);
+        mp->disconnect();
+    }
+}
+
+static void
+android_media_MediaPlayer_native_finalize(JNIEnv *env, jobject thiz)
+{
+    LOGV("native_finalize");
+    android_media_MediaPlayer_release(env, thiz);
+}
+
+// ----------------------------------------------------------------------------
+
+static JNINativeMethod gMethods[] = {
+    {"setDataSource",       "(Ljava/lang/String;)V",            (void *)android_media_MediaPlayer_setDataSource},
+    {"setDataSource",       "(Ljava/io/FileDescriptor;JJ)V",    (void *)android_media_MediaPlayer_setDataSourceFD},
+    {"prepare",             "()V",                              (void *)android_media_MediaPlayer_prepare},
+    {"prepareAsync",        "()V",                              (void *)android_media_MediaPlayer_prepareAsync},
+    {"_start",              "()V",                              (void *)android_media_MediaPlayer_start},
+    {"_stop",               "()V",                              (void *)android_media_MediaPlayer_stop},
+    {"getVideoWidth",       "()I",                              (void *)android_media_MediaPlayer_getVideoWidth},
+    {"getVideoHeight",      "()I",                              (void *)android_media_MediaPlayer_getVideoHeight},
+    {"seekTo",              "(I)V",                             (void *)android_media_MediaPlayer_seekTo},
+    {"_pause",              "()V",                              (void *)android_media_MediaPlayer_pause},
+    {"isPlaying",           "()Z",                              (void *)android_media_MediaPlayer_isPlaying},
+    {"getCurrentPosition",  "()I",                              (void *)android_media_MediaPlayer_getCurrentPosition},
+    {"getDuration",         "()I",                              (void *)android_media_MediaPlayer_getDuration},
+    {"_release",            "()V",                              (void *)android_media_MediaPlayer_release},
+    {"_reset",              "()V",                              (void *)android_media_MediaPlayer_reset},
+    {"setAudioStreamType",  "(I)V",                             (void *)android_media_MediaPlayer_setAudioStreamType},
+    {"setLooping",          "(Z)V",                             (void *)android_media_MediaPlayer_setLooping},
+    {"isLooping",           "()Z",                              (void *)android_media_MediaPlayer_isLooping},
+    {"setVolume",           "(FF)V",                            (void *)android_media_MediaPlayer_setVolume},
+    {"getFrameAt",          "(I)Landroid/graphics/Bitmap;",     (void *)android_media_MediaPlayer_getFrameAt},
+    {"native_setup",        "(Ljava/lang/Object;)V",            (void *)android_media_MediaPlayer_native_setup},
+    {"native_finalize",     "()V",                              (void *)android_media_MediaPlayer_native_finalize},
+};
+
+static const char* const kClassPathName = "android/media/MediaPlayer";
+
+static int register_android_media_MediaPlayer(JNIEnv *env)
+{
+    jclass clazz;
+
+    clazz = env->FindClass("android/media/MediaPlayer");
+    if (clazz == NULL) {
+        LOGE("Can't find android/media/MediaPlayer");
+        return -1;
+    }
+
+    fields.context = env->GetFieldID(clazz, "mNativeContext", "I");
+    if (fields.context == NULL) {
+        LOGE("Can't find MediaPlayer.mNativeContext");
+        return -1;
+    }
+
+    fields.post_event = env->GetStaticMethodID(clazz, "postEventFromNative",
+                                               "(Ljava/lang/Object;IIILjava/lang/Object;)V");
+    if (fields.post_event == NULL) {
+        LOGE("Can't find MediaPlayer.postEventFromNative");
+        return -1;
+    }
+
+    fields.surface = env->GetFieldID(clazz, "mSurface", "Landroid/view/Surface;");
+    if (fields.surface == NULL) {
+        LOGE("Can't find MediaPlayer.mSurface");
+        return -1;
+    }
+
+    jclass surface = env->FindClass("android/view/Surface");
+    if (surface == NULL) {
+        LOGE("Can't find android/view/Surface");
+        return -1;
+    }
+
+    fields.surface_native = env->GetFieldID(surface, "mSurface", "I");
+    if (fields.surface_native == NULL) {
+        LOGE("Can't find Surface fields");
+        return -1;
+    }
+
+    return AndroidRuntime::registerNativeMethods(env,
+                "android/media/MediaPlayer", gMethods, NELEM(gMethods));
+}
+
+extern int register_android_media_MediaRecorder(JNIEnv *env);
+extern int register_android_media_MediaScanner(JNIEnv *env);
+extern int register_android_media_MediaMetadataRetriever(JNIEnv *env);
+extern int register_android_media_AmrInputStream(JNIEnv *env);
+extern int register_android_media_ResampleInputStream(JNIEnv *env);
+
+jint JNI_OnLoad(JavaVM* vm, void* reserved)
+{
+    JNIEnv* env = NULL;
+    jint result = -1;
+
+    if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
+        LOGE("ERROR: GetEnv failed\n");
+        goto bail;
+    }
+    assert(env != NULL);
+
+    if (register_android_media_MediaPlayer(env) < 0) {
+        LOGE("ERROR: MediaPlayer native registration failed\n");
+        goto bail;
+    }
+
+    if (register_android_media_MediaRecorder(env) < 0) {
+        LOGE("ERROR: MediaRecorder native registration failed\n");
+        goto bail;
+    }
+
+    if (register_android_media_MediaScanner(env) < 0) {
+        LOGE("ERROR: MediaScanner native registration failed\n");
+        goto bail;
+    }
+
+    if (register_android_media_MediaMetadataRetriever(env) < 0) {
+        LOGE("ERROR: MediaMetadataRetriever native registration failed\n");
+        goto bail;
+    }
+
+    if (register_android_media_AmrInputStream(env) < 0) {
+        LOGE("ERROR: AmrInputStream native registration failed\n");
+        goto bail;
+    }
+
+    if (register_android_media_ResampleInputStream(env) < 0) {
+        LOGE("ERROR: ResampleInputStream native registration failed\n");
+        goto bail;
+    }
+
+    /* success -- return valid version number */
+    result = JNI_VERSION_1_4;
+
+bail:
+    return result;
+}
+
+// KTHXBYE
+
diff --git a/media/jni/android_media_MediaRecorder.cpp b/media/jni/android_media_MediaRecorder.cpp
new file mode 100644
index 0000000..44f875c
--- /dev/null
+++ b/media/jni/android_media_MediaRecorder.cpp
@@ -0,0 +1,416 @@
+/*
+ * 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 "MediaRecorderJNI"
+#include <utils/Log.h>
+
+#include <ui/SurfaceComposerClient.h>
+#include <ui/ICameraService.h>
+#include <ui/Camera.h>
+#include <media/mediarecorder.h>
+#include <stdio.h>
+#include <assert.h>
+#include <limits.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <utils/threads.h>
+
+#include "jni.h"
+#include "JNIHelp.h"
+#include "android_runtime/AndroidRuntime.h"
+
+
+// ----------------------------------------------------------------------------
+
+using namespace android;
+
+// ----------------------------------------------------------------------------
+
+// helper function to extract a native Camera object from a Camera Java object
+extern sp<Camera> get_native_camera(JNIEnv *env, jobject thiz, struct camera_context_t** context);
+
+struct fields_t {
+    jfieldID    context;
+    jfieldID    surface;
+    /* actually in android.view.Surface XXX */
+    jfieldID    surface_native;
+
+    jmethodID   post_event;
+};
+static fields_t fields;
+
+static Mutex sLock;
+
+// ----------------------------------------------------------------------------
+// ref-counted object for callbacks
+class JNIMediaRecorderListener: public MediaRecorderListener
+{
+public:
+    JNIMediaRecorderListener(JNIEnv* env, jobject thiz, jobject weak_thiz);
+    ~JNIMediaRecorderListener();
+    void notify(int msg, int ext1, int ext2);
+private:
+    JNIMediaRecorderListener();
+    jclass      mClass;     // Reference to MediaRecorder class
+    jobject     mObject;    // Weak ref to MediaRecorder Java object to call on
+};
+
+JNIMediaRecorderListener::JNIMediaRecorderListener(JNIEnv* env, jobject thiz, jobject weak_thiz)
+{
+
+    // Hold onto the MediaRecorder class for use in calling the static method
+    // that posts events to the application thread.
+    jclass clazz = env->GetObjectClass(thiz);
+    if (clazz == NULL) {
+        LOGE("Can't find android/media/MediaRecorder");
+        jniThrowException(env, "java/lang/Exception", NULL);
+        return;
+    }
+    mClass = (jclass)env->NewGlobalRef(clazz);
+
+    // We use a weak reference so the MediaRecorder object can be garbage collected.
+    // The reference is only used as a proxy for callbacks.
+    mObject  = env->NewGlobalRef(weak_thiz);
+}
+
+JNIMediaRecorderListener::~JNIMediaRecorderListener()
+{
+    // remove global references
+    JNIEnv *env = AndroidRuntime::getJNIEnv();
+    env->DeleteGlobalRef(mObject);
+    env->DeleteGlobalRef(mClass);
+}
+
+void JNIMediaRecorderListener::notify(int msg, int ext1, int ext2)
+{
+    LOGV("JNIMediaRecorderListener::notify");
+
+    JNIEnv *env = AndroidRuntime::getJNIEnv();
+    env->CallStaticVoidMethod(mClass, fields.post_event, mObject, msg, ext1, ext2, 0);
+}
+
+// ----------------------------------------------------------------------------
+
+static sp<Surface> get_surface(JNIEnv* env, jobject clazz)
+{
+    LOGV("get_surface");
+    Surface* const p = (Surface*)env->GetIntField(clazz, fields.surface_native);
+    return sp<Surface>(p);
+}
+
+// Returns true if it throws an exception.
+static bool process_media_recorder_call(JNIEnv *env, status_t opStatus, const char* exception, const char* message)
+{
+    LOGV("process_media_recorder_call");
+    if (opStatus == (status_t)INVALID_OPERATION) {
+        jniThrowException(env, "java/lang/IllegalStateException", NULL);
+        return true;
+    } else if (opStatus != (status_t)OK) {
+        jniThrowException(env, exception, message);
+        return true;
+    }
+    return false;
+}
+
+static sp<MediaRecorder> getMediaRecorder(JNIEnv* env, jobject thiz)
+{
+    Mutex::Autolock l(sLock);
+    MediaRecorder* const p = (MediaRecorder*)env->GetIntField(thiz, fields.context);
+    return sp<MediaRecorder>(p);
+}
+
+static sp<MediaRecorder> setMediaRecorder(JNIEnv* env, jobject thiz, const sp<MediaRecorder>& recorder)
+{
+    Mutex::Autolock l(sLock);
+    sp<MediaRecorder> old = (MediaRecorder*)env->GetIntField(thiz, fields.context);
+    if (recorder.get()) {
+        recorder->incStrong(thiz);
+    }
+    if (old != 0) {
+        old->decStrong(thiz);
+    }
+    env->SetIntField(thiz, fields.context, (int)recorder.get());
+    return old;
+}
+
+
+static void android_media_MediaRecorder_setCamera(JNIEnv* env, jobject thiz, jobject camera)
+{
+    sp<Camera> c = get_native_camera(env, camera, NULL);
+    sp<MediaRecorder> mr = getMediaRecorder(env, thiz);
+    process_media_recorder_call(env, mr->setCamera(c->remote()),
+            "java/lang/RuntimeException", "setCamera failed.");
+}
+
+static void
+android_media_MediaRecorder_setVideoSource(JNIEnv *env, jobject thiz, jint vs)
+{
+    LOGV("setVideoSource(%d)", vs);
+    if (vs < VIDEO_SOURCE_DEFAULT || vs > VIDEO_SOURCE_CAMERA) {
+        jniThrowException(env, "java/lang/IllegalArgumentException", "Invalid video source");
+        return;
+    }
+    sp<MediaRecorder> mr = getMediaRecorder(env, thiz);
+    process_media_recorder_call(env, mr->setVideoSource(vs), "java/lang/RuntimeException", "setVideoSource failed.");
+}
+
+static void
+android_media_MediaRecorder_setAudioSource(JNIEnv *env, jobject thiz, jint as)
+{
+    LOGV("setAudioSource(%d)", as);
+    if (as < AUDIO_SOURCE_DEFAULT || as > AUDIO_SOURCE_MIC) {
+        jniThrowException(env, "java/lang/IllegalArgumentException", "Invalid audio source");
+        return;
+    }
+    sp<MediaRecorder> mr = getMediaRecorder(env, thiz);
+    process_media_recorder_call(env, mr->setAudioSource(as), "java/lang/RuntimeException", "setAudioSource failed.");
+}
+
+static void
+android_media_MediaRecorder_setOutputFormat(JNIEnv *env, jobject thiz, jint of)
+{
+    LOGV("setOutputFormat(%d)", of);
+    if (of < OUTPUT_FORMAT_DEFAULT || of >= OUTPUT_FORMAT_LIST_END) {
+        jniThrowException(env, "java/lang/IllegalArgumentException", "Invalid output format");
+        return;
+    }
+    sp<MediaRecorder> mr = getMediaRecorder(env, thiz);
+    process_media_recorder_call(env, mr->setOutputFormat(of), "java/lang/RuntimeException", "setOutputFormat failed.");
+}
+
+static void
+android_media_MediaRecorder_setVideoEncoder(JNIEnv *env, jobject thiz, jint ve)
+{
+    LOGV("setVideoEncoder(%d)", ve);
+    if (ve < VIDEO_ENCODER_DEFAULT || ve > VIDEO_ENCODER_MPEG_4_SP) {
+        jniThrowException(env, "java/lang/IllegalArgumentException", "Invalid video encoder");
+        return;
+    }
+    sp<MediaRecorder> mr = getMediaRecorder(env, thiz);
+    process_media_recorder_call(env, mr->setVideoEncoder(ve), "java/lang/RuntimeException", "setVideoEncoder failed.");
+}
+
+static void
+android_media_MediaRecorder_setAudioEncoder(JNIEnv *env, jobject thiz, jint ae)
+{
+    LOGV("setAudioEncoder(%d)", ae);
+    if (ae < AUDIO_ENCODER_DEFAULT || ae > AUDIO_ENCODER_AMR_NB) {
+        jniThrowException(env, "java/lang/IllegalArgumentException", "Invalid audio encoder");
+        return;
+    }
+    sp<MediaRecorder> mr = getMediaRecorder(env, thiz);
+    process_media_recorder_call(env, mr->setAudioEncoder(ae), "java/lang/RuntimeException", "setAudioEncoder failed.");
+}
+
+static void
+android_media_MediaRecorder_setOutputFileFD(JNIEnv *env, jobject thiz, jobject fileDescriptor, jlong offset, jlong length)
+{
+    LOGV("setOutputFile");
+    if (fileDescriptor == NULL) {
+        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
+        return;
+    }
+    int fd = getParcelFileDescriptorFD(env, fileDescriptor);
+    sp<MediaRecorder> mr = getMediaRecorder(env, thiz);
+    status_t opStatus = mr->setOutputFile(fd, offset, length);
+    process_media_recorder_call(env, opStatus, "java/io/IOException", "setOutputFile failed.");
+}
+
+static void
+android_media_MediaRecorder_setVideoSize(JNIEnv *env, jobject thiz, jint width, jint height)
+{
+    LOGV("setVideoSize(%d, %d)", width, height);
+    sp<MediaRecorder> mr = getMediaRecorder(env, thiz);
+
+    if (width <= 0 || height <= 0) {
+        jniThrowException(env, "java/lang/IllegalArgumentException", "invalid video size");
+        return;
+    }
+    process_media_recorder_call(env, mr->setVideoSize(width, height), "java/lang/RuntimeException", "setVideoSize failed.");
+}
+
+static void
+android_media_MediaRecorder_setVideoFrameRate(JNIEnv *env, jobject thiz, jint rate)
+{
+    LOGV("setVideoFrameRate(%d)", rate);
+    if (rate <= 0 || rate > MEDIA_RECORDER_MAX_FRAME_RATE) {
+        jniThrowException(env, "java/lang/IllegalArgumentException", "invalid frame rate");
+        return;
+    }
+    sp<MediaRecorder> mr = getMediaRecorder(env, thiz);
+    process_media_recorder_call(env, mr->setVideoFrameRate(rate), "java/lang/RuntimeException", "setVideoFrameRate failed.");
+}
+
+static void
+android_media_MediaRecorder_prepare(JNIEnv *env, jobject thiz)
+{
+    LOGV("prepare");
+    sp<MediaRecorder> mr = getMediaRecorder(env, thiz);
+
+    jobject surface = env->GetObjectField(thiz, fields.surface);
+    if (surface != NULL) {
+        const sp<Surface>& native_surface = get_surface(env, surface);
+        LOGI("prepare: surface=%p (id=%d)", native_surface.get(), native_surface->ID());
+        if (process_media_recorder_call(env, mr->setPreviewSurface(native_surface), "java/lang/RuntimeException", "setPreviewSurface failed.")) {
+            return;
+        }
+    }
+    process_media_recorder_call(env, mr->prepare(), "java/io/IOException", "prepare failed.");
+}
+
+static int
+android_media_MediaRecorder_native_getMaxAmplitude(JNIEnv *env, jobject thiz)
+{
+    LOGV("getMaxAmplitude");
+    sp<MediaRecorder> mr = getMediaRecorder(env, thiz);
+    int result = 0;
+    process_media_recorder_call(env, mr->getMaxAmplitude(&result), "java/lang/RuntimeException", "getMaxAmplitude failed.");
+    return result;
+}
+
+static void
+android_media_MediaRecorder_start(JNIEnv *env, jobject thiz)
+{
+    LOGV("start");
+    sp<MediaRecorder> mr = getMediaRecorder(env, thiz);
+    process_media_recorder_call(env, mr->start(), "java/lang/RuntimeException", "start failed.");
+}
+
+static void
+android_media_MediaRecorder_stop(JNIEnv *env, jobject thiz)
+{
+    LOGV("stop");
+    sp<MediaRecorder> mr = getMediaRecorder(env, thiz);
+    process_media_recorder_call(env, mr->stop(), "java/lang/RuntimeException", "stop failed.");
+}
+
+static void
+android_media_MediaRecorder_native_reset(JNIEnv *env, jobject thiz)
+{
+    LOGV("native_reset");
+    sp<MediaRecorder> mr = getMediaRecorder(env, thiz);
+    process_media_recorder_call(env, mr->reset(), "java/lang/RuntimeException", "native_reset failed.");
+}
+
+static void
+android_media_MediaRecorder_release(JNIEnv *env, jobject thiz)
+{
+    LOGV("release");
+    sp<MediaRecorder> mr = setMediaRecorder(env, thiz, 0);
+    if (mr != NULL) {
+        mr->setListener(NULL);
+    }
+}
+
+static void
+android_media_MediaRecorder_native_setup(JNIEnv *env, jobject thiz, jobject weak_this)
+{
+    LOGV("setup");
+    sp<MediaRecorder> mr = new MediaRecorder();
+    if (mr == NULL) {
+        jniThrowException(env, "java/lang/RuntimeException", "Out of memory");
+        return;
+    }
+    if (mr->initCheck() != NO_ERROR) {
+        jniThrowException(env, "java/lang/IOException", "Unable to initialize camera");
+        return;
+    }
+
+    // create new listener and give it to MediaRecorder
+    sp<JNIMediaRecorderListener> listener = new JNIMediaRecorderListener(env, thiz, weak_this);
+    mr->setListener(listener);
+
+    setMediaRecorder(env, thiz, mr);
+}
+
+static void
+android_media_MediaRecorder_native_finalize(JNIEnv *env, jobject thiz)
+{
+    LOGV("finalize");
+    android_media_MediaRecorder_release(env, thiz);
+}
+
+// ----------------------------------------------------------------------------
+
+static JNINativeMethod gMethods[] = {
+    {"setCamera",            "(Landroid/hardware/Camera;)V",    (void *)android_media_MediaRecorder_setCamera},
+    {"setVideoSource",       "(I)V",                            (void *)android_media_MediaRecorder_setVideoSource},
+    {"setAudioSource",       "(I)V",                            (void *)android_media_MediaRecorder_setAudioSource},
+    {"setOutputFormat",      "(I)V",                            (void *)android_media_MediaRecorder_setOutputFormat},
+    {"setVideoEncoder",      "(I)V",                            (void *)android_media_MediaRecorder_setVideoEncoder},
+    {"setAudioEncoder",      "(I)V",                            (void *)android_media_MediaRecorder_setAudioEncoder},
+    {"_setOutputFile",       "(Ljava/io/FileDescriptor;JJ)V",   (void *)android_media_MediaRecorder_setOutputFileFD},
+    {"setVideoSize",         "(II)V",                           (void *)android_media_MediaRecorder_setVideoSize},
+    {"setVideoFrameRate",    "(I)V",                            (void *)android_media_MediaRecorder_setVideoFrameRate},
+    {"_prepare",             "()V",                             (void *)android_media_MediaRecorder_prepare},
+    {"getMaxAmplitude",      "()I",                             (void *)android_media_MediaRecorder_native_getMaxAmplitude},
+    {"start",                "()V",                             (void *)android_media_MediaRecorder_start},
+    {"stop",                 "()V",                             (void *)android_media_MediaRecorder_stop},
+    {"native_reset",                "()V",                             (void *)android_media_MediaRecorder_native_reset},
+    {"release",              "()V",                             (void *)android_media_MediaRecorder_release},
+    {"native_setup",         "(Ljava/lang/Object;)V",           (void *)android_media_MediaRecorder_native_setup},
+    {"native_finalize",      "()V",                             (void *)android_media_MediaRecorder_native_finalize},
+};
+
+static const char* const kClassPathName = "android/media/MediaRecorder";
+
+int register_android_media_MediaRecorder(JNIEnv *env)
+{
+    jclass clazz;
+
+    clazz = env->FindClass("android/media/MediaRecorder");
+    if (clazz == NULL) {
+        LOGE("Can't find android/media/MediaRecorder");
+        return -1;
+    }
+
+    fields.context = env->GetFieldID(clazz, "mNativeContext", "I");
+    if (fields.context == NULL) {
+        LOGE("Can't find MediaRecorder.mNativeContext");
+        return -1;
+    }
+
+    fields.surface = env->GetFieldID(clazz, "mSurface", "Landroid/view/Surface;");
+    if (fields.surface == NULL) {
+        LOGE("Can't find MediaRecorder.mSurface");
+        return -1;
+    }
+
+    jclass surface = env->FindClass("android/view/Surface");
+    if (surface == NULL) {
+        LOGE("Can't find android/view/Surface");
+        return -1;
+    }
+
+    fields.surface_native = env->GetFieldID(surface, "mSurface", "I");
+    if (fields.surface_native == NULL) {
+        LOGE("Can't find Surface fields");
+        return -1;
+    }
+
+    fields.post_event = env->GetStaticMethodID(clazz, "postEventFromNative",
+                                               "(Ljava/lang/Object;IIILjava/lang/Object;)V");
+    if (fields.post_event == NULL) {
+        LOGE("Can't find MediaRecorder.postEventFromNative");
+        return -1;
+    }
+
+    return AndroidRuntime::registerNativeMethods(env,
+                "android/media/MediaRecorder", gMethods, NELEM(gMethods));
+}
+
+
diff --git a/media/jni/android_media_MediaScanner.cpp b/media/jni/android_media_MediaScanner.cpp
new file mode 100644
index 0000000..8764a70
--- /dev/null
+++ b/media/jni/android_media_MediaScanner.cpp
@@ -0,0 +1,304 @@
+/* //device/libs/media_jni/MediaScanner.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 "MediaScanner"
+#include "utils/Log.h"
+
+#include <media/mediascanner.h>
+#include <stdio.h>
+#include <assert.h>
+#include <limits.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <utils/threads.h>
+
+#include "jni.h"
+#include "JNIHelp.h"
+#include "android_runtime/AndroidRuntime.h"
+
+
+// ----------------------------------------------------------------------------
+
+using namespace android;
+
+// ----------------------------------------------------------------------------
+
+struct fields_t {
+    jfieldID    context;
+};
+static fields_t fields;
+
+// ----------------------------------------------------------------------------
+
+class MyMediaScannerClient : public MediaScannerClient
+{
+public:
+    MyMediaScannerClient(JNIEnv *env, jobject client)
+        :   mEnv(env),
+            mClient(env->NewGlobalRef(client)),
+            mScanFileMethodID(0),
+            mHandleStringTagMethodID(0),
+            mSetMimeTypeMethodID(0)
+    {
+        jclass mediaScannerClientInterface = env->FindClass("android/media/MediaScannerClient");
+        if (mediaScannerClientInterface == NULL) {
+            fprintf(stderr, "android/media/MediaScannerClient not found\n");
+        }
+        else {
+            mScanFileMethodID = env->GetMethodID(mediaScannerClientInterface, "scanFile",
+                                                     "(Ljava/lang/String;JJ)V");
+            mHandleStringTagMethodID = env->GetMethodID(mediaScannerClientInterface, "handleStringTag",
+                                                     "(Ljava/lang/String;Ljava/lang/String;)V");
+            mSetMimeTypeMethodID = env->GetMethodID(mediaScannerClientInterface, "setMimeType",
+                                                     "(Ljava/lang/String;)V");
+        }
+    }
+    
+    virtual ~MyMediaScannerClient()
+    {
+        mEnv->DeleteGlobalRef(mClient);
+    }
+    
+    // returns true if it succeeded, false if an exception occured in the Java code
+    virtual bool scanFile(const char* path, long long lastModified, long long fileSize)
+    {
+        jstring pathStr;
+        if ((pathStr = mEnv->NewStringUTF(path)) == NULL) return false;
+
+        mEnv->CallVoidMethod(mClient, mScanFileMethodID, pathStr, lastModified, fileSize);
+
+        mEnv->DeleteLocalRef(pathStr);
+        return (!mEnv->ExceptionCheck());
+    }
+
+    // returns true if it succeeded, false if an exception occured in the Java code
+    virtual bool handleStringTag(const char* name, const char* value)
+    {
+        jstring nameStr, valueStr;
+        if ((nameStr = mEnv->NewStringUTF(name)) == NULL) return false;
+        if ((valueStr = mEnv->NewStringUTF(value)) == NULL) return false;
+
+        mEnv->CallVoidMethod(mClient, mHandleStringTagMethodID, nameStr, valueStr);
+
+        mEnv->DeleteLocalRef(nameStr);
+        mEnv->DeleteLocalRef(valueStr);
+        return (!mEnv->ExceptionCheck());
+    }
+
+    // returns true if it succeeded, false if an exception occured in the Java code
+    virtual bool setMimeType(const char* mimeType)
+    {
+        jstring mimeTypeStr;
+        if ((mimeTypeStr = mEnv->NewStringUTF(mimeType)) == NULL) return false;
+
+        mEnv->CallVoidMethod(mClient, mSetMimeTypeMethodID, mimeTypeStr);
+
+        mEnv->DeleteLocalRef(mimeTypeStr);
+        return (!mEnv->ExceptionCheck());
+    }
+
+private:
+    JNIEnv *mEnv;
+    jobject mClient;
+    jmethodID mScanFileMethodID; 
+    jmethodID mHandleStringTagMethodID; 
+    jmethodID mSetMimeTypeMethodID;
+};
+
+
+// ----------------------------------------------------------------------------
+
+static bool ExceptionCheck(void* env)
+{
+    return ((JNIEnv *)env)->ExceptionCheck();
+}
+
+static void
+android_media_MediaScanner_processDirectory(JNIEnv *env, jobject thiz, jstring path, jstring extensions, jobject client)
+{
+    MediaScanner *mp = (MediaScanner *)env->GetIntField(thiz, fields.context);
+
+    if (path == NULL) {
+        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
+        return;
+    }
+    if (extensions == NULL) {
+        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
+        return;
+    }
+    
+    const char *pathStr = env->GetStringUTFChars(path, NULL);
+    if (pathStr == NULL) {  // Out of memory
+        jniThrowException(env, "java/lang/RuntimeException", "Out of memory");
+        return;
+    }
+    const char *extensionsStr = env->GetStringUTFChars(extensions, NULL);
+    if (extensionsStr == NULL) {  // Out of memory
+        env->ReleaseStringUTFChars(path, pathStr);
+        jniThrowException(env, "java/lang/RuntimeException", "Out of memory");
+        return;
+    }
+
+    MyMediaScannerClient myClient(env, client);
+    mp->processDirectory(pathStr, extensionsStr, myClient, ExceptionCheck, env);
+    env->ReleaseStringUTFChars(path, pathStr);
+    env->ReleaseStringUTFChars(extensions, extensionsStr);
+}
+
+static void
+android_media_MediaScanner_processFile(JNIEnv *env, jobject thiz, jstring path, jstring mimeType, jobject client)
+{
+    MediaScanner *mp = (MediaScanner *)env->GetIntField(thiz, fields.context);
+
+    if (path == NULL) {
+        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
+        return;
+    }
+    
+    const char *pathStr = env->GetStringUTFChars(path, NULL);
+    if (pathStr == NULL) {  // Out of memory
+        jniThrowException(env, "java/lang/RuntimeException", "Out of memory");
+        return;
+    }
+    const char *mimeTypeStr = (mimeType ? env->GetStringUTFChars(mimeType, NULL) : NULL);
+    if (mimeType && mimeTypeStr == NULL) {  // Out of memory
+        env->ReleaseStringUTFChars(path, pathStr);
+        jniThrowException(env, "java/lang/RuntimeException", "Out of memory");
+        return;
+    }
+
+    MyMediaScannerClient myClient(env, client);
+    mp->processFile(pathStr, mimeTypeStr, myClient);
+    env->ReleaseStringUTFChars(path, pathStr);
+    if (mimeType) {
+        env->ReleaseStringUTFChars(mimeType, mimeTypeStr);
+    }
+}
+
+static void
+android_media_MediaScanner_setLocale(JNIEnv *env, jobject thiz, jstring locale)
+{
+    MediaScanner *mp = (MediaScanner *)env->GetIntField(thiz, fields.context);
+
+    if (locale == NULL) {
+        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
+        return;
+    }
+    const char *localeStr = env->GetStringUTFChars(locale, NULL);
+    if (localeStr == NULL) {  // Out of memory
+        jniThrowException(env, "java/lang/RuntimeException", "Out of memory");
+        return;
+    }
+    mp->setLocale(localeStr);
+
+    env->ReleaseStringUTFChars(locale, localeStr);
+}
+
+static jbyteArray
+android_media_MediaScanner_extractAlbumArt(JNIEnv *env, jobject thiz, jobject fileDescriptor)
+{
+    MediaScanner *mp = (MediaScanner *)env->GetIntField(thiz, fields.context);
+
+    if (fileDescriptor == NULL) {
+        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
+        return NULL;
+    }
+
+    int fd = getParcelFileDescriptorFD(env, fileDescriptor);
+    char* data = mp->extractAlbumArt(fd);
+    if (!data) {
+        return NULL;
+    }
+    long len = *((long*)data);
+    
+    jbyteArray array = env->NewByteArray(len);
+    if (array != NULL) {
+        jbyte* bytes = env->GetByteArrayElements(array, NULL);
+        memcpy(bytes, data + 4, len);
+        env->ReleaseByteArrayElements(array, bytes, 0);
+    }
+    
+done:
+    free(data);
+    // if NewByteArray() returned NULL, an out-of-memory
+    // exception will have been raised. I just want to
+    // return null in that case.
+    env->ExceptionClear();
+    return array;
+}
+
+static void
+android_media_MediaScanner_native_setup(JNIEnv *env, jobject thiz)
+{
+    MediaScanner *mp = new MediaScanner();
+    if (mp == NULL) {
+        jniThrowException(env, "java/lang/RuntimeException", "Out of memory");
+        return;
+    }
+
+    env->SetIntField(thiz, fields.context, (int)mp);
+}
+
+static void
+android_media_MediaScanner_native_finalize(JNIEnv *env, jobject thiz)
+{
+    MediaScanner *mp = (MediaScanner *)env->GetIntField(thiz, fields.context);
+
+    //printf("##### android_media_MediaScanner_native_finalize: ctx=0x%p\n", ctx);
+
+    if (mp == 0)
+        return;
+
+    delete mp;
+}
+
+// ----------------------------------------------------------------------------
+
+static JNINativeMethod gMethods[] = {
+    {"processDirectory",  "(Ljava/lang/String;Ljava/lang/String;Landroid/media/MediaScannerClient;)V",    
+                                                        (void *)android_media_MediaScanner_processDirectory},
+    {"processFile",       "(Ljava/lang/String;Ljava/lang/String;Landroid/media/MediaScannerClient;)V",    
+                                                        (void *)android_media_MediaScanner_processFile},
+    {"setLocale",         "(Ljava/lang/String;)V",      (void *)android_media_MediaScanner_setLocale},
+    {"extractAlbumArt",   "(Ljava/io/FileDescriptor;)[B",     (void *)android_media_MediaScanner_extractAlbumArt},
+    {"native_setup",        "()V",                      (void *)android_media_MediaScanner_native_setup},
+    {"native_finalize",     "()V",                      (void *)android_media_MediaScanner_native_finalize},
+};
+
+static const char* const kClassPathName = "android/media/MediaScanner";
+
+int register_android_media_MediaScanner(JNIEnv *env)
+{
+    jclass clazz;
+
+    clazz = env->FindClass("android/media/MediaScanner");
+    if (clazz == NULL) {
+        LOGE("Can't find android/media/MediaScanner");
+        return -1;
+    }
+
+    fields.context = env->GetFieldID(clazz, "mNativeContext", "I");
+    if (fields.context == NULL) {
+        LOGE("Can't find MediaScanner.mNativeContext");
+        return -1;
+    }
+
+    return AndroidRuntime::registerNativeMethods(env,
+                "android/media/MediaScanner", gMethods, NELEM(gMethods));
+}
+
+
diff --git a/media/jni/android_media_ResampleInputStream.cpp b/media/jni/android_media_ResampleInputStream.cpp
new file mode 100644
index 0000000..0247cdb
--- /dev/null
+++ b/media/jni/android_media_ResampleInputStream.cpp
@@ -0,0 +1,143 @@
+/*
+**
+** 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 "ResampleInputStream"
+#include "utils/Log.h"
+
+#include <media/mediarecorder.h>
+#include <stdio.h>
+#include <assert.h>
+#include <limits.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <utils/threads.h>
+
+#include "jni.h"
+#include "JNIHelp.h"
+#include "android_runtime/AndroidRuntime.h"
+
+
+// ----------------------------------------------------------------------------
+
+using namespace android;
+
+
+//
+// helper function to throw an exception
+//
+static void throwException(JNIEnv *env, const char* ex, const char* fmt, int data) {
+    if (jclass cls = env->FindClass(ex)) {
+        char msg[1000];
+        sprintf(msg, fmt, data);
+        env->ThrowNew(cls, msg);
+        env->DeleteLocalRef(cls);
+    }
+}
+
+
+#define FIR_COEF(coef) (short)(0x10000 * coef)
+static const short fir21[] = {
+    FIR_COEF(-0.006965742326),
+    FIR_COEF(-0.008428945737),
+    FIR_COEF( 0.004241280174),
+    FIR_COEF( 0.022141096893),
+    FIR_COEF( 0.018765669437),
+    FIR_COEF(-0.009871891152),
+    FIR_COEF(-0.024842433247),
+    FIR_COEF( 0.006121772058),
+    FIR_COEF( 0.045890841611),
+    FIR_COEF( 0.021573503509),
+    FIR_COEF(-0.059681984668),
+    FIR_COEF(-0.076036275138),
+    FIR_COEF( 0.072405390275),
+    FIR_COEF( 0.308255674582),
+    FIR_COEF( 0.424321210495),
+    FIR_COEF( 0.308255674582),
+    FIR_COEF( 0.072405390275),
+    FIR_COEF(-0.076036275138),
+    FIR_COEF(-0.059681984668),
+    FIR_COEF( 0.021573503509),
+    FIR_COEF( 0.045890841611),
+    FIR_COEF( 0.006121772058),
+    FIR_COEF(-0.024842433247),
+    FIR_COEF(-0.009871891152),
+    FIR_COEF( 0.018765669437),
+    FIR_COEF( 0.022141096893),
+    FIR_COEF( 0.004241280174),
+    FIR_COEF(-0.008428945737),
+    FIR_COEF(-0.006965742326)
+};
+static const int nFir21 = sizeof(fir21) / sizeof(fir21[0]);
+
+static const int BUF_SIZE = 2048;
+
+
+static void android_media_ResampleInputStream_fir21(JNIEnv *env, jclass clazz,
+         jbyteArray jIn,  jint jInOffset,
+         jbyteArray jOut, jint jOutOffset,
+         jint jNpoints) {
+    
+    // safety first!
+    if (nFir21 + jNpoints > BUF_SIZE) {
+        throwException(env, "java/lang/IllegalArgumentException",
+                "FIR+data too long %d", nFir21 + jNpoints);
+        return;
+    }
+    
+    // get input data
+    short in[BUF_SIZE];
+    env->GetByteArrayRegion(jIn, jInOffset, (jNpoints * 2 + nFir21 - 1) * 2, (jbyte*)in);
+    
+    // compute filter
+    short out[BUF_SIZE];
+    for (int i = 0; i < jNpoints; i++) {
+        long sum = 0;
+        const short* firp = &fir21[0];
+        const short* inp = &in[i * 2];
+        for (int n = nFir21; --n >= 0; ) {
+            sum += ((long)*firp++) * ((long)*inp++);
+        }
+        out[i] = (short)(sum >> 16);
+    }
+
+    // save new values
+    env->SetByteArrayRegion(jOut, jOutOffset, jNpoints * 2, (jbyte*)out);
+}
+
+// ----------------------------------------------------------------------------
+
+static JNINativeMethod gMethods[] = {
+    {"fir21", "([BI[BII)V", (void*)android_media_ResampleInputStream_fir21},
+};
+
+
+int register_android_media_ResampleInputStream(JNIEnv *env)
+{
+    const char* const kClassPathName = "android/media/ResampleInputStream";
+    jclass clazz;
+
+    clazz = env->FindClass(kClassPathName);
+    if (clazz == NULL) {
+        LOGE("Can't find %s", kClassPathName);
+        return -1;
+    }
+
+    return AndroidRuntime::registerNativeMethods(env,
+            kClassPathName, gMethods, NELEM(gMethods));
+}
+
+
diff --git a/media/jni/soundpool/Android.mk b/media/jni/soundpool/Android.mk
new file mode 100644
index 0000000..374ddeb
--- /dev/null
+++ b/media/jni/soundpool/Android.mk
@@ -0,0 +1,18 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+	android_media_SoundPool.cpp \
+	SoundPool.cpp \
+	SoundPoolThread.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+	libcutils \
+	libutils \
+	libandroid_runtime \
+	libnativehelper \
+	libmedia
+
+LOCAL_MODULE:= libsoundpool
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/media/jni/soundpool/SoundPool.cpp b/media/jni/soundpool/SoundPool.cpp
new file mode 100644
index 0000000..02731825
--- /dev/null
+++ b/media/jni/soundpool/SoundPool.cpp
@@ -0,0 +1,764 @@
+/*
+ * 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "SoundPool"
+#include <utils/Log.h>
+
+//#define USE_SHARED_MEM_BUFFER
+
+// XXX needed for timing latency
+#include <utils/Timers.h>
+
+#include <sys/resource.h>
+#include <media/AudioTrack.h>
+#include <media/mediaplayer.h>
+
+#include "SoundPool.h"
+#include "SoundPoolThread.h"
+
+namespace android
+{
+
+int kDefaultBufferCount = 4;
+uint32_t kMaxSampleRate = 48000;
+uint32_t kDefaultSampleRate = 44100;
+uint32_t kDefaultFrameCount = 1200;
+
+SoundPool::SoundPool(jobject soundPoolRef, int maxChannels, int streamType, int srcQuality)
+{
+    LOGV("SoundPool constructor: maxChannels=%d, streamType=%d, srcQuality=%d",
+            maxChannels, streamType, srcQuality);
+
+    if (maxChannels > 32) {
+        LOGW("App requested %d channels, capped at 32", maxChannels);
+        maxChannels = 32;
+    }
+
+    mQuit = false;
+    mSoundPoolRef = soundPoolRef;
+    mDecodeThread = 0;
+    mMaxChannels = maxChannels;
+    mStreamType = streamType;
+    mSrcQuality = srcQuality;
+    mAllocated = 0;
+    mNextSampleID = 0;
+    mNextChannelID = 0;
+
+    mChannelPool = new SoundChannel[maxChannels];
+    for (int i = 0; i < maxChannels; ++i) {
+        mChannelPool[i].init(this);
+        mChannels.push_back(&mChannelPool[i]);
+    }
+
+    // start decode thread
+    startThreads();
+}
+
+SoundPool::~SoundPool()
+{
+    LOGV("SoundPool destructor");
+    mDecodeThread->quit();
+    quit();
+
+    Mutex::Autolock lock(&mLock);
+    mChannels.clear();
+    if (mChannelPool)
+        delete [] mChannelPool;
+
+    // clean up samples
+    LOGV("clear samples");
+    mSamples.clear();
+
+    if (mDecodeThread)
+        delete mDecodeThread;
+}
+
+void SoundPool::addToRestartList(SoundChannel* channel)
+{
+    Mutex::Autolock lock(&mLock);
+    mRestart.push_back(channel);
+    mCondition.signal();
+}
+
+int SoundPool::beginThread(void* arg)
+{
+    SoundPool* p = (SoundPool*)arg;
+    return p->run();
+}
+
+int SoundPool::run()
+{
+    mLock.lock();
+    while (!mQuit) {
+        mCondition.wait(mLock);
+        LOGV("awake");
+        if (mQuit) break;
+
+        while (!mRestart.empty()) {
+            SoundChannel* channel;
+            LOGV("Getting channel from list");
+            List<SoundChannel*>::iterator iter = mRestart.begin();
+            channel = *iter;
+            mRestart.erase(iter);
+            if (channel) channel->nextEvent();
+            if (mQuit) break;
+        }
+    }
+
+    mRestart.clear();
+    mCondition.signal();
+    mLock.unlock();
+    LOGV("goodbye");
+    return 0;
+}
+
+void SoundPool::quit()
+{
+    mLock.lock();
+    mQuit = true;
+    mCondition.signal();
+    mCondition.wait(mLock);
+    LOGV("return from quit");
+    mLock.unlock();
+}
+
+bool SoundPool::startThreads()
+{
+    createThread(beginThread, this);
+    if (mDecodeThread == NULL)
+        mDecodeThread = new SoundPoolThread(this);
+    return mDecodeThread != NULL;
+}
+
+SoundChannel* SoundPool::findChannel(int channelID)
+{
+    for (int i = 0; i < mMaxChannels; ++i) {
+        if (mChannelPool[i].channelID() == channelID) {
+            return &mChannelPool[i];
+        }
+    }
+    return NULL;
+}
+
+SoundChannel* SoundPool::findNextChannel(int channelID)
+{
+    for (int i = 0; i < mMaxChannels; ++i) {
+        if (mChannelPool[i].nextChannelID() == channelID) {
+            return &mChannelPool[i];
+        }
+    }
+    return NULL;
+}
+
+int SoundPool::load(const char* path, int priority)
+{
+    LOGV("load: path=%s, priority=%d", path, priority);
+    Mutex::Autolock lock(&mLock);
+    sp<Sample> sample = new Sample(++mNextSampleID, path);
+    mSamples.add(sample->sampleID(), sample);
+    doLoad(sample);
+    return sample->sampleID();
+}
+
+int SoundPool::load(int fd, int64_t offset, int64_t length, int priority)
+{
+    LOGV("load: fd=%d, offset=%lld, length=%lld, priority=%d",
+            fd, offset, length, priority);
+    Mutex::Autolock lock(&mLock);
+    sp<Sample> sample = new Sample(++mNextSampleID, fd, offset, length);
+    mSamples.add(sample->sampleID(), sample);
+    doLoad(sample);
+    return sample->sampleID();
+}
+
+void SoundPool::doLoad(sp<Sample>& sample)
+{
+    LOGV("doLoad: loading sample sampleID=%d", sample->sampleID());
+    sample->startLoad();
+    mDecodeThread->loadSample(sample->sampleID());
+}
+
+bool SoundPool::unload(int sampleID)
+{
+    LOGV("unload: sampleID=%d", sampleID);
+    Mutex::Autolock lock(&mLock);
+    return mSamples.removeItem(sampleID);
+}
+
+int SoundPool::play(int sampleID, float leftVolume, float rightVolume,
+        int priority, int loop, float rate)
+{
+    LOGV("sampleID=%d, leftVolume=%f, rightVolume=%f, priority=%d, loop=%d, rate=%f",
+            sampleID, leftVolume, rightVolume, priority, loop, rate);
+    sp<Sample> sample;
+    SoundChannel* channel;
+    int channelID;
+
+    // scope for lock
+    {
+        Mutex::Autolock lock(&mLock);
+
+        // is sample ready?
+        sample = findSample(sampleID);
+        if ((sample == 0) || (sample->state() != Sample::READY)) {
+            LOGW("  sample %d not READY", sampleID);
+            return 0;
+        }
+
+        dump();
+
+        // allocate a channel
+        channel = allocateChannel(priority);
+
+        // no channel allocated - return 0
+        if (!channel) {
+            LOGV("No channel allocated");
+            return 0;
+        }
+
+        channelID = ++mNextChannelID;
+    }
+
+    LOGV("channel state = %d", channel->state());
+    channel->play(sample, channelID, leftVolume, rightVolume, priority, loop, rate);
+    return channelID;
+}
+
+SoundChannel* SoundPool::allocateChannel(int priority)
+{
+    List<SoundChannel*>::iterator iter;
+    SoundChannel* channel = NULL;
+
+    // allocate a channel
+    if (!mChannels.empty()) {
+        iter = mChannels.begin();
+        if (priority >= (*iter)->priority()) {
+            channel = *iter;
+            mChannels.erase(iter);
+            LOGV("Allocated active channel");
+        }
+    }
+
+    // update priority and put it back in the list
+    if (channel) {
+        channel->setPriority(priority);
+        for (iter = mChannels.begin(); iter != mChannels.end(); ++iter) {
+            if (priority < (*iter)->priority()) {
+                break;
+            }
+        }
+        mChannels.insert(iter, channel);
+    }
+    return channel;
+}
+
+// move a channel from its current position to the front of the list
+void SoundPool::moveToFront(SoundChannel* channel)
+{
+    for (List<SoundChannel*>::iterator iter = mChannels.begin(); iter != mChannels.end(); ++iter) {
+        if (*iter == channel) {
+            mChannels.erase(iter);
+            mChannels.push_front(channel);
+            break;
+        }
+    }
+}
+
+void SoundPool::pause(int channelID)
+{
+    LOGV("pause(%d)", channelID);
+    Mutex::Autolock lock(&mLock);
+    SoundChannel* channel = findChannel(channelID);
+    if (channel) {
+        channel->pause();
+    }
+}
+
+void SoundPool::resume(int channelID)
+{
+    LOGV("resume(%d)", channelID);
+    Mutex::Autolock lock(&mLock);
+    SoundChannel* channel = findChannel(channelID);
+    if (channel) {
+        channel->resume();
+    }
+}
+
+void SoundPool::stop(int channelID)
+{
+    LOGV("stop(%d)", channelID);
+    Mutex::Autolock lock(&mLock);
+    SoundChannel* channel = findChannel(channelID);
+    if (channel) {
+        channel->stop();
+    } else {
+        channel = findNextChannel(channelID);
+        if (channel)
+            channel->clearNextEvent();
+    }
+}
+
+void SoundPool::setVolume(int channelID, float leftVolume, float rightVolume)
+{
+    Mutex::Autolock lock(&mLock);
+    SoundChannel* channel = findChannel(channelID);
+    if (channel) {
+        channel->setVolume(leftVolume, rightVolume);
+    }
+}
+
+void SoundPool::setPriority(int channelID, int priority)
+{
+    LOGV("setPriority(%d, %d)", channelID, priority);
+    Mutex::Autolock lock(&mLock);
+    SoundChannel* channel = findChannel(channelID);
+    if (channel) {
+        channel->setPriority(priority);
+    }
+}
+
+void SoundPool::setLoop(int channelID, int loop)
+{
+    LOGV("setLoop(%d, %d)", channelID, loop);
+    Mutex::Autolock lock(&mLock);
+    SoundChannel* channel = findChannel(channelID);
+    if (channel) {
+        channel->setLoop(loop);
+    }
+}
+
+void SoundPool::setRate(int channelID, float rate)
+{
+    LOGV("setRate(%d, %f)", channelID, rate);
+    Mutex::Autolock lock(&mLock);
+    SoundChannel* channel = findChannel(channelID);
+    if (channel) {
+        channel->setRate(rate);
+    }
+}
+
+// call with lock held
+void SoundPool::done(SoundChannel* channel)
+{
+    LOGV("done(%d)", channel->channelID());
+
+    // if "stolen", play next event
+    if (channel->nextChannelID() != 0) {
+        LOGV("add to restart list");
+        addToRestartList(channel);
+    }
+
+    // return to idle state
+    else {
+        LOGV("move to front");
+        moveToFront(channel);
+    }
+}
+
+void SoundPool::dump()
+{
+    for (int i = 0; i < mMaxChannels; ++i) {
+        mChannelPool[i].dump();
+    }
+}
+
+
+Sample::Sample(int sampleID, const char* url)
+{
+    init();
+    mSampleID = sampleID;
+    mUrl = strdup(url);
+    LOGV("create sampleID=%d, url=%s", mSampleID, mUrl);
+}
+
+Sample::Sample(int sampleID, int fd, int64_t offset, int64_t length)
+{
+    init();
+    mSampleID = sampleID;
+    mFd = dup(fd);
+    mOffset = offset;
+    mLength = length;
+    LOGV("create sampleID=%d, fd=%d, offset=%lld, length=%lld", mSampleID, mFd, mLength, mOffset);
+}
+
+void Sample::init()
+{
+    mData = 0;
+    mSize = 0;
+    mRefCount = 0;
+    mSampleID = 0;
+    mState = UNLOADED;
+    mFd = -1;
+    mOffset = 0;
+    mLength = 0;
+    mUrl = 0;
+}
+
+Sample::~Sample()
+{
+    LOGV("Sample::destructor sampleID=%d, fd=%d", mSampleID, mFd);
+    if (mFd > 0) {
+        LOGV("close(%d)", mFd);
+        ::close(mFd);
+    }
+    mData.clear();
+    delete mUrl;
+}
+
+void Sample::doLoad()
+{
+    uint32_t sampleRate;
+    int numChannels;
+    int format;
+    sp<IMemory> p;
+    LOGV("Start decode");
+    if (mUrl) {
+        p = MediaPlayer::decode(mUrl, &sampleRate, &numChannels, &format);
+    } else {
+        p = MediaPlayer::decode(mFd, mOffset, mLength, &sampleRate, &numChannels, &format);
+        LOGV("close(%d)", mFd);
+        ::close(mFd);
+        mFd = -1;
+    }
+    if (p == 0) {
+        LOGE("Unable to load sample: %s", mUrl);
+        return;
+    }
+    LOGV("pointer = %p, size = %u, sampleRate = %u, numChannels = %d",
+            p->pointer(), p->size(), sampleRate, numChannels);
+
+    if (sampleRate > kMaxSampleRate) {
+       LOGE("Sample rate (%u) out of range", sampleRate);
+       return;
+    }
+
+    if ((numChannels < 1) || (numChannels > 2)) {
+        LOGE("Sample channel count (%d) out of range", numChannels);
+        return;
+    }
+
+    //_dumpBuffer(p->pointer(), p->size());
+    uint8_t* q = static_cast<uint8_t*>(p->pointer()) + p->size() - 10;
+    //_dumpBuffer(q, 10, 10, false);
+
+    mData = p;
+    mSize = p->size();
+    mSampleRate = sampleRate;
+    mNumChannels = numChannels;
+    mFormat = format;
+    mState = READY;
+}
+
+
+void SoundChannel::init(SoundPool* soundPool)
+{
+    mSoundPool = soundPool;
+}
+
+void SoundChannel::play(const sp<Sample>& sample, int nextChannelID, float leftVolume,
+        float rightVolume, int priority, int loop, float rate)
+{
+    AudioTrack* oldTrack;
+
+    LOGV("play %p: sampleID=%d, channelID=%d, leftVolume=%f, rightVolume=%f, priority=%d, loop=%d, rate=%f",
+            this, sample->sampleID(), nextChannelID, leftVolume, rightVolume, priority, loop, rate);
+
+    // if not idle, this voice is being stolen
+    if (mState != IDLE) {
+        LOGV("channel %d stolen - event queued for channel %d", channelID(), nextChannelID);
+        stop_l();
+        mNextEvent.set(sample, nextChannelID, leftVolume, rightVolume, priority, loop, rate);
+#ifdef USE_SHARED_MEM_BUFFER
+        mSoundPool->done(this);
+#endif
+        return;
+    }
+
+    // initialize track
+    int afFrameCount;
+    int afSampleRate;
+    int streamType = mSoundPool->streamType();
+    if (AudioSystem::getOutputFrameCount(&afFrameCount, streamType) != NO_ERROR) {
+        afFrameCount = kDefaultFrameCount;
+    }
+    if (AudioSystem::getOutputSamplingRate(&afSampleRate, streamType) != NO_ERROR) {
+        afSampleRate = kDefaultSampleRate;
+    }
+    int numChannels = sample->numChannels();
+    uint32_t sampleRate = uint32_t(float(sample->sampleRate()) * rate + 0.5);
+    uint32_t bufferFrames = (afFrameCount * sampleRate) / afSampleRate;
+    uint32_t frameCount = 0;
+
+    if (loop) {
+        frameCount = sample->size()/numChannels/((sample->format() == AudioSystem::PCM_16_BIT) ? sizeof(int16_t) : sizeof(uint8_t));
+    }
+
+    // Ensure minimum audio buffer size in case of short looped sample
+    if(frameCount < kDefaultBufferCount * bufferFrames) {
+        frameCount = kDefaultBufferCount * bufferFrames;
+    }
+
+    AudioTrack* newTrack;
+    
+    // mToggle toggles each time a track is started on a given channel.
+    // The toggle is concatenated with the SoundChannel address and passed to AudioTrack
+    // as callback user data. This enables the detection of callbacks received from the old
+    // audio track while the new one is being started and avoids processing them with 
+    // wrong audio audio buffer size  (mAudioBufferSize)
+    unsigned long toggle = mToggle ^ 1;
+    void *userData = (void *)((unsigned long)this | toggle);
+    
+#ifdef USE_SHARED_MEM_BUFFER
+    newTrack = new AudioTrack(streamType, sampleRate, sample->format(),
+            numChannels, sample->getIMemory(), 0, callback, userData);
+#else
+    newTrack = new AudioTrack(streamType, sampleRate, sample->format(),
+            numChannels, frameCount, 0, callback, userData, bufferFrames);
+#endif
+    if (newTrack->initCheck() != NO_ERROR) {
+        LOGE("Error creating AudioTrack");
+        delete newTrack;
+        return;
+    }
+    LOGV("setVolume %p", newTrack);
+    newTrack->setVolume(leftVolume, rightVolume);
+    newTrack->setLoop(0, frameCount, loop);
+
+    {
+        Mutex::Autolock lock(&mLock);
+        // From now on, AudioTrack callbacks recevieved with previous toggle value will be ignored.
+        mToggle = toggle;
+        oldTrack = mAudioTrack;
+        mAudioTrack = newTrack;
+        mPos = 0;
+        mSample = sample;
+        mChannelID = nextChannelID;
+        mPriority = priority;
+        mLoop = loop;
+        mLeftVolume = leftVolume;
+        mRightVolume = rightVolume;
+        mNumChannels = numChannels;
+        mRate = rate;
+        clearNextEvent();
+        mState = PLAYING;
+        mAudioTrack->start();
+        mAudioBufferSize = newTrack->frameCount()*newTrack->frameSize();
+    }
+
+    LOGV("delete oldTrack %p", oldTrack);
+    delete oldTrack;
+}
+
+void SoundChannel::nextEvent()
+{
+    sp<Sample> sample;
+    int nextChannelID;
+    float leftVolume;
+    float rightVolume;
+    int priority;
+    int loop;
+    float rate;
+
+    // check for valid event
+    {
+        Mutex::Autolock lock(&mLock);
+        nextChannelID = mNextEvent.channelID();
+        if (nextChannelID  == 0) {
+            LOGV("stolen channel has no event");
+            return;
+        }
+
+        sample = mNextEvent.sample();
+        leftVolume = mNextEvent.leftVolume();
+        rightVolume = mNextEvent.rightVolume();
+        priority = mNextEvent.priority();
+        loop = mNextEvent.loop();
+        rate = mNextEvent.rate();
+    }
+
+    LOGV("Starting stolen channel %d -> %d", channelID(), nextChannelID);
+    play(sample, nextChannelID, leftVolume, rightVolume, priority, loop, rate);
+}
+
+void SoundChannel::callback(int event, void* user, void *info)
+{
+    unsigned long toggle = (unsigned long)user & 1;
+    SoundChannel* channel = static_cast<SoundChannel*>((void *)((unsigned long)user & ~1));
+    
+    if (channel->mToggle != toggle) {
+        LOGV("callback with wrong toggle");
+        return;
+    }
+    channel->process(event, info);
+}
+
+void SoundChannel::process(int event, void *info)
+{
+    //LOGV("process(%d)", mChannelID);
+    sp<Sample> sample = mSample;
+
+//    LOGV("SoundChannel::process event %d", event);
+
+    if (event == AudioTrack::EVENT_MORE_DATA) {
+       AudioTrack::Buffer* b = static_cast<AudioTrack::Buffer *>(info);
+
+        // check for stop state
+        if (b->size == 0) return;
+
+        if (sample != 0) {
+            // fill buffer
+            uint8_t* q = (uint8_t*) b->i8;
+            size_t count = 0;
+
+            if (mPos < (int)sample->size()) {
+                uint8_t* p = sample->data() + mPos;
+                count = sample->size() - mPos;
+                if (count > b->size) {
+                    count = b->size;
+                }
+                memcpy(q, p, count);
+                LOGV("fill: q=%p, p=%p, mPos=%u, b->size=%u, count=%d", q, p, mPos, b->size, count);
+            } else if (mPos < mAudioBufferSize) {
+                count = mAudioBufferSize - mPos;
+                if (count > b->size) {
+                    count = b->size;
+                }
+                memset(q, 0, count);
+                LOGV("fill extra: q=%p, mPos=%u, b->size=%u, count=%d", q, mPos, b->size, count);
+            }
+
+            mPos += count;
+            b->size = count;
+            //LOGV("buffer=%p, [0]=%d", b->i16, b->i16[0]);
+        }
+    } else if (event == AudioTrack::EVENT_UNDERRUN) {
+        LOGV("stopping track");
+        stop();
+    } else if (event == AudioTrack::EVENT_LOOP_END) {
+        LOGV("End loop: %d", *(int *)info);
+    }
+}
+
+
+// call with lock held
+void SoundChannel::stop_l()
+{
+    if (mState != IDLE) {
+        setVolume_l(0, 0);
+        LOGV("stop");
+        mAudioTrack->stop();
+        mSample.clear();
+        mState = IDLE;
+        mPriority = IDLE_PRIORITY;
+    }
+}
+
+void SoundChannel::stop()
+{
+    {
+        Mutex::Autolock lock(&mLock);
+        stop_l();
+    }
+    mSoundPool->done(this);
+}
+
+//FIXME: Pause is a little broken right now
+void SoundChannel::pause()
+{
+    Mutex::Autolock lock(&mLock);
+    if (mState == PLAYING) {
+        LOGV("pause track");
+        mState = PAUSED;
+        mAudioTrack->pause();
+    }
+}
+
+void SoundChannel::resume()
+{
+    Mutex::Autolock lock(&mLock);
+    if (mState == PAUSED) {
+        LOGV("resume track");
+        mState = PLAYING;
+        mAudioTrack->start();
+    }
+}
+
+void SoundChannel::setRate(float rate)
+{
+    Mutex::Autolock lock(&mLock);
+    if (mAudioTrack != 0 && mSample.get() != 0) {
+        uint32_t sampleRate = uint32_t(float(mSample->sampleRate()) * rate + 0.5);
+        mAudioTrack->setSampleRate(sampleRate);
+        mRate = rate;
+    }
+}
+
+// call with lock held
+void SoundChannel::setVolume_l(float leftVolume, float rightVolume)
+{
+    mLeftVolume = leftVolume;
+    mRightVolume = rightVolume;
+    if (mAudioTrack != 0) mAudioTrack->setVolume(leftVolume, rightVolume);
+}
+
+void SoundChannel::setVolume(float leftVolume, float rightVolume)
+{
+    Mutex::Autolock lock(&mLock);
+    setVolume_l(leftVolume, rightVolume);
+}
+
+void SoundChannel::setLoop(int loop)
+{
+    Mutex::Autolock lock(&mLock);
+    if (mAudioTrack != 0 && mSample.get() != 0) {
+        mAudioTrack->setLoop(0, mSample->size()/mNumChannels/((mSample->format() == AudioSystem::PCM_16_BIT) ? sizeof(int16_t) : sizeof(uint8_t)), loop);
+        mLoop = loop;
+    }
+}
+
+SoundChannel::~SoundChannel()
+{
+    LOGV("SoundChannel destructor");
+    if (mAudioTrack) {
+        LOGV("stop track");
+        mAudioTrack->stop();
+        delete mAudioTrack;
+    }
+    clearNextEvent();
+    mSample.clear();
+}
+
+void SoundChannel::dump()
+{
+    LOGV("mState = %d mChannelID=%d, mNumChannels=%d, mPos = %d, mPriority=%d, mLoop=%d",
+            mState, mChannelID, mNumChannels, mPos, mPriority, mLoop);
+}
+
+void SoundEvent::set(const sp<Sample>& sample, int channelID, float leftVolume,
+            float rightVolume, int priority, int loop, float rate)
+{
+    mSample =sample;
+    mChannelID = channelID;
+    mLeftVolume = leftVolume;
+    mRightVolume = rightVolume;
+    mPriority = priority;
+    mLoop = loop;
+    mRate =rate;
+}
+
+} // end namespace android
+
diff --git a/media/jni/soundpool/SoundPool.h b/media/jni/soundpool/SoundPool.h
new file mode 100644
index 0000000..7802781
--- /dev/null
+++ b/media/jni/soundpool/SoundPool.h
@@ -0,0 +1,224 @@
+/*
+ * 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 SOUNDPOOL_H_
+#define SOUNDPOOL_H_
+
+#include <utils/threads.h>
+#include <utils/List.h>
+#include <utils/Vector.h>
+#include <utils/KeyedVector.h>
+#include <media/AudioTrack.h>
+#include <cutils/atomic.h>
+
+#include <nativehelper/jni.h>
+
+namespace android {
+
+static const int IDLE_PRIORITY = -1;
+
+// forward declarations
+class SoundEvent;
+class SoundPoolThread;
+class SoundPool;
+
+// for queued events
+class SoundPoolEvent {
+public:
+    SoundPoolEvent(int msg, int arg1=0, int arg2=0) :
+        mMsg(msg), mArg1(arg1), mArg2(arg2) {}
+    int         mMsg;
+    int         mArg1;
+    int         mArg2;
+};
+
+// JNI for calling back Java SoundPool object
+extern void android_soundpool_SoundPool_notify(jobject ref, const SoundPoolEvent *event);
+
+// tracks samples used by application
+class Sample  : public RefBase {
+public:
+    enum sample_state { UNLOADED, LOADING, READY, UNLOADING };
+    Sample(int sampleID, const char* url);
+    Sample(int sampleID, int fd, int64_t offset, int64_t length);
+    ~Sample();
+    int sampleID() { return mSampleID; }
+    int numChannels() { return mNumChannels; }
+    int sampleRate() { return mSampleRate; }
+    int format() { return mFormat; }
+    size_t size() { return mSize; }
+    int state() { return mState; }
+    uint8_t* data() { return static_cast<uint8_t*>(mData->pointer()); }
+    void doLoad();
+    void startLoad() { mState = LOADING; }
+    sp<IMemory> getIMemory() { return mData; }
+
+    // hack
+    void init(int numChannels, int sampleRate, int format, size_t size, sp<IMemory> data ) {
+        mNumChannels = numChannels; mSampleRate = sampleRate; mFormat = format; mSize = size; mData = data; }
+
+private:
+    void init();
+
+    size_t              mSize;
+    volatile int32_t    mRefCount;
+    uint16_t            mSampleID;
+    uint16_t            mSampleRate;
+    uint8_t             mState : 3;
+    uint8_t             mNumChannels : 2;
+    uint8_t             mFormat : 2;
+    int                 mFd;
+    int64_t             mOffset;
+    int64_t             mLength;
+    char*               mUrl;
+    sp<IMemory>         mData;
+};
+
+// stores pending events for stolen channels
+class SoundEvent
+{
+public:
+    SoundEvent() : mChannelID(0), mLeftVolume(0), mRightVolume(0),
+            mPriority(IDLE_PRIORITY), mLoop(0), mRate(0) {}
+    void set(const sp<Sample>& sample, int channelID, float leftVolume,
+            float rightVolume, int priority, int loop, float rate);
+    sp<Sample>      sample() { return mSample; }
+    int             channelID() { return mChannelID; }
+    float           leftVolume() { return mLeftVolume; }
+    float           rightVolume() { return mRightVolume; }
+    int             priority() { return mPriority; }
+    int             loop() { return mLoop; }
+    float           rate() { return mRate; }
+    void            clear() { mChannelID = 0; mSample.clear(); }
+
+protected:
+    sp<Sample>      mSample;
+    int             mChannelID;
+    float           mLeftVolume;
+    float           mRightVolume;
+    int             mPriority;
+    int             mLoop;
+    float           mRate;
+};
+
+// for channels aka AudioTracks
+class SoundChannel : public SoundEvent {
+public:
+    enum state { IDLE, RESUMING, STOPPING, PAUSED, PLAYING };
+    SoundChannel() : mAudioTrack(0), mState(IDLE), mNumChannels(1), mPos(0), mToggle(0) {}
+    ~SoundChannel();
+    void init(SoundPool* soundPool);
+    void play(const sp<Sample>& sample, int channelID, float leftVolume, float rightVolume,
+            int priority, int loop, float rate);
+    void setVolume_l(float leftVolume, float rightVolume);
+    void setVolume(float leftVolume, float rightVolume);
+    void stop_l();
+    void stop();
+    void pause();
+    void resume();
+    void setRate(float rate);
+    int state() { return mState; }
+    void setPriority(int priority) { mPriority = priority; }
+    void setLoop(int loop);
+    int numChannels() { return mNumChannels; }
+    void clearNextEvent() { mNextEvent.clear(); }
+    void nextEvent();
+    int nextChannelID() { return mNextEvent.channelID(); }
+    void dump();
+
+private:
+    static void callback(int event, void* user, void *info);
+    void process(int event, void *info);
+
+    SoundPool*          mSoundPool;
+    AudioTrack*         mAudioTrack;
+    SoundEvent          mNextEvent;
+    Mutex               mLock;
+    int                 mState;
+    int                 mNumChannels;
+    int                 mPos;
+    int                 mAudioBufferSize;
+    unsigned long       mToggle;
+};
+
+// application object for managing a pool of sounds
+class SoundPool {
+    friend class SoundPoolThread;
+    friend class SoundChannel;
+public:
+    SoundPool(jobject soundPoolRef, int maxChannels, int streamType, int srcQuality);
+    ~SoundPool();
+    int load(const char* url, int priority);
+    int load(int fd, int64_t offset, int64_t length, int priority);
+    bool unload(int sampleID);
+    int play(int sampleID, float leftVolume, float rightVolume, int priority,
+            int loop, float rate);
+    void pause(int channelID);
+    void resume(int channelID);
+    void stop(int channelID);
+    void setVolume(int channelID, float leftVolume, float rightVolume);
+    void setPriority(int channelID, int priority);
+    void setLoop(int channelID, int loop);
+    void setRate(int channelID, float rate);
+    int streamType() const { return mStreamType; }
+    int srcQuality() const { return mSrcQuality; }
+
+    // called from SoundPoolThread
+    void sampleLoaded(int sampleID);
+
+    // called from AudioTrack thread
+    void done(SoundChannel* channel);
+
+private:
+    SoundPool() {} // no default constructor
+    bool startThreads();
+    void doLoad(sp<Sample>& sample);
+    inline void notify(const SoundPoolEvent* event) {
+        android_soundpool_SoundPool_notify(mSoundPoolRef, event);
+    }
+    sp<Sample> findSample(int sampleID) { return mSamples.valueFor(sampleID); }
+    SoundChannel* findChannel (int channelID);
+    SoundChannel* findNextChannel (int channelID);
+    SoundChannel* allocateChannel(int priority);
+    void moveToFront(SoundChannel* channel);
+    void dump();
+
+    // restart thread
+    void addToRestartList(SoundChannel* channel);
+    static int beginThread(void* arg);
+    int run();
+    void quit();
+
+    jobject                 mSoundPoolRef;
+    Mutex                   mLock;
+    Condition               mCondition;
+    SoundPoolThread*        mDecodeThread;
+    SoundChannel*           mChannelPool;
+    List<SoundChannel*>     mChannels;
+    List<SoundChannel*>     mRestart;
+    DefaultKeyedVector< int, sp<Sample> >   mSamples;
+    int                     mMaxChannels;
+    int                     mStreamType;
+    int                     mSrcQuality;
+    int                     mAllocated;
+    int                     mNextSampleID;
+    int                     mNextChannelID;
+    bool                    mQuit;
+};
+
+} // end namespace android
+
+#endif /*SOUNDPOOL_H_*/
diff --git a/media/jni/soundpool/SoundPoolThread.cpp b/media/jni/soundpool/SoundPoolThread.cpp
new file mode 100644
index 0000000..4e6798d
--- /dev/null
+++ b/media/jni/soundpool/SoundPoolThread.cpp
@@ -0,0 +1,108 @@
+/*
+ * 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "SoundPoolThread"
+#include "utils/Log.h"
+
+#include "SoundPoolThread.h"
+
+namespace android {
+
+void SoundPoolThread::MessageQueue::write(SoundPoolMsg msg) {
+    LOGV("MessageQueue::write - acquiring lock\n");
+    Mutex::Autolock lock(&mLock);
+    while (mQueue.size() >= maxMessages) {
+        LOGV("MessageQueue::write - wait\n");
+        mCondition.wait(mLock);
+    }
+    LOGV("MessageQueue::write - push message\n");
+    mQueue.push(msg);
+    mCondition.signal();
+}
+
+const SoundPoolMsg SoundPoolThread::MessageQueue::read() {
+    LOGV("MessageQueue::read - acquiring lock\n");
+    Mutex::Autolock lock(&mLock);
+    while (mQueue.size() == 0) {
+        LOGV("MessageQueue::read - wait\n");
+        mCondition.wait(mLock);
+    }
+    SoundPoolMsg msg = mQueue[0];
+    LOGV("MessageQueue::read - retrieve message\n");
+    mQueue.removeAt(0);
+    mCondition.signal();
+    return msg;
+}
+
+void SoundPoolThread::MessageQueue::quit() {
+    Mutex::Autolock lock(&mLock);
+    mQueue.clear();
+    mQueue.push(SoundPoolMsg(SoundPoolMsg::KILL, 0));
+    mCondition.signal();
+    mCondition.wait(mLock);
+    LOGV("return from quit");
+}
+
+SoundPoolThread::SoundPoolThread(SoundPool* soundPool) :
+    mSoundPool(soundPool)
+{
+    mMessages.setCapacity(maxMessages);
+    createThread(beginThread, this);
+}
+
+SoundPoolThread::~SoundPoolThread()
+{
+}
+
+int SoundPoolThread::beginThread(void* arg) {
+    LOGV("beginThread");
+    SoundPoolThread* soundPoolThread = (SoundPoolThread*)arg;
+    return soundPoolThread->run();
+}
+
+int SoundPoolThread::run() {
+    LOGV("run");
+    for (;;) {
+        SoundPoolMsg msg = mMessages.read();
+        LOGV("Got message m=%d, mData=%d", msg.mMessageType, msg.mData);
+        switch (msg.mMessageType) {
+        case SoundPoolMsg::KILL:
+            LOGV("goodbye");
+            return NO_ERROR;
+        case SoundPoolMsg::LOAD_SAMPLE:
+            doLoadSample(msg.mData);
+            break;
+        default:
+            LOGW("run: Unrecognized message %d\n",
+                    msg.mMessageType);
+            break;
+        }
+    }
+}
+
+void SoundPoolThread::loadSample(int sampleID) {
+    mMessages.write(SoundPoolMsg(SoundPoolMsg::LOAD_SAMPLE, sampleID));
+}
+
+void SoundPoolThread::doLoadSample(int sampleID) {
+    sp <Sample> sample = mSoundPool->findSample(sampleID);
+    if (sample != 0) {
+        sample->doLoad();
+    }
+}
+
+} // end namespace android
diff --git a/media/jni/soundpool/SoundPoolThread.h b/media/jni/soundpool/SoundPoolThread.h
new file mode 100644
index 0000000..459a764
--- /dev/null
+++ b/media/jni/soundpool/SoundPoolThread.h
@@ -0,0 +1,75 @@
+/*
+ * 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 SOUNDPOOLTHREAD_H_
+#define SOUNDPOOLTHREAD_H_
+
+#include <utils/threads.h>
+#include <utils/Vector.h>
+#include <media/AudioTrack.h>
+
+#include "SoundPool.h"
+
+namespace android {
+
+class SoundPoolMsg {
+public:
+    enum MessageType { INVALID, KILL, LOAD_SAMPLE, PLAY_SAMPLE, SAMPLE_DONE };
+    SoundPoolMsg() : mMessageType(INVALID), mData(0) {}
+    SoundPoolMsg(MessageType MessageType, int data) :
+        mMessageType(MessageType), mData(data) {}
+    uint8_t         mMessageType;
+    uint8_t         mData;
+    uint8_t         mData2;
+    uint8_t         mData3;
+};
+
+/*
+ * This class handles background requests from the SoundPool
+ */
+class SoundPoolThread {
+public:
+    SoundPoolThread(SoundPool* SoundPool);
+    ~SoundPoolThread();
+    void loadSample(int sampleID);
+    void quit() { mMessages.quit(); }
+
+private:
+    static const size_t maxMessages = 5;
+
+    class MessageQueue {
+    public:
+        void write(SoundPoolMsg msg);
+        const SoundPoolMsg read();
+        void setCapacity(size_t size) { mQueue.setCapacity(size); }
+        void quit();
+    private:
+        Vector<SoundPoolMsg>    mQueue;
+        Mutex                   mLock;
+        Condition               mCondition;
+    };
+
+    static int beginThread(void* arg);
+    int run();
+    void doLoadSample(int sampleID);
+
+    SoundPool*                  mSoundPool;
+    MessageQueue                mMessages;
+};
+
+} // end namespace android
+
+#endif /*SOUNDPOOLTHREAD_H_*/
diff --git a/media/jni/soundpool/android_media_SoundPool.cpp b/media/jni/soundpool/android_media_SoundPool.cpp
new file mode 100644
index 0000000..0ce2d6f
--- /dev/null
+++ b/media/jni/soundpool/android_media_SoundPool.cpp
@@ -0,0 +1,270 @@
+/*
+ * 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.
+ */
+
+#include <stdio.h>
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "SoundPool"
+
+#include <utils/Log.h>
+#include <nativehelper/jni.h>
+#include <nativehelper/JNIHelp.h>
+#include <android_runtime/AndroidRuntime.h>
+#include "SoundPool.h"
+
+using namespace android;
+
+static struct fields_t {
+    jfieldID    mNativeContext;
+    jclass      mSoundPoolClass;
+} fields;
+
+static inline SoundPool* MusterSoundPool(JNIEnv *env, jobject thiz) {
+    return (SoundPool*)env->GetIntField(thiz, fields.mNativeContext);
+}
+
+// ----------------------------------------------------------------------------
+static int
+android_media_SoundPool_load_URL(JNIEnv *env, jobject thiz, jstring path, jint priority)
+{
+    LOGV("android_media_SoundPool_load_URL");
+    SoundPool *ap = MusterSoundPool(env, thiz);
+    if (path == NULL) {
+        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
+        return 0;
+    }
+    const char* s = env->GetStringUTFChars(path, NULL);
+    int id = ap->load(s, priority);
+    env->ReleaseStringUTFChars(path, s);
+    return id;
+}
+
+static int
+android_media_SoundPool_load_FD(JNIEnv *env, jobject thiz, jobject fileDescriptor,
+        jlong offset, jlong length, jint priority)
+{
+    LOGV("android_media_SoundPool_load_FD");
+    SoundPool *ap = MusterSoundPool(env, thiz);
+    if (ap == NULL) return 0;
+    return ap->load(getParcelFileDescriptorFD(env, fileDescriptor),
+            int64_t(offset), int64_t(length), int(priority));
+}
+
+static bool
+android_media_SoundPool_unload(JNIEnv *env, jobject thiz, jint sampleID) {
+    LOGV("android_media_SoundPool_unload\n");
+    SoundPool *ap = MusterSoundPool(env, thiz);
+    if (ap == NULL) return 0;
+    return ap->unload(sampleID);
+}
+
+static int
+android_media_SoundPool_play(JNIEnv *env, jobject thiz, jint sampleID,
+        jfloat leftVolume, jfloat rightVolume, jint priority, jint loop,
+        jfloat rate)
+{
+    LOGV("android_media_SoundPool_play\n");
+    SoundPool *ap = MusterSoundPool(env, thiz);
+    if (ap == NULL) return 0;
+    return ap->play(sampleID, leftVolume, rightVolume, priority, loop, rate);
+}
+
+static void
+android_media_SoundPool_pause(JNIEnv *env, jobject thiz, jint channelID)
+{
+    LOGV("android_media_SoundPool_pause");
+    SoundPool *ap = MusterSoundPool(env, thiz);
+    if (ap == NULL) return;
+    ap->pause(channelID);
+}
+
+static void
+android_media_SoundPool_resume(JNIEnv *env, jobject thiz, jint channelID)
+{
+    LOGV("android_media_SoundPool_resume");
+    SoundPool *ap = MusterSoundPool(env, thiz);
+    if (ap == NULL) return;
+    ap->resume(channelID);
+}
+
+static void
+android_media_SoundPool_stop(JNIEnv *env, jobject thiz, jint channelID)
+{
+    LOGV("android_media_SoundPool_stop");
+    SoundPool *ap = MusterSoundPool(env, thiz);
+    if (ap == NULL) return;
+    ap->stop(channelID);
+}
+
+static void
+android_media_SoundPool_setVolume(JNIEnv *env, jobject thiz, jint channelID,
+        float leftVolume, float rightVolume)
+{
+    LOGV("android_media_SoundPool_setVolume");
+    SoundPool *ap = MusterSoundPool(env, thiz);
+    if (ap == NULL) return;
+    ap->setVolume(channelID, leftVolume, rightVolume);
+}
+
+static void
+android_media_SoundPool_setPriority(JNIEnv *env, jobject thiz, jint channelID,
+        int priority)
+{
+    LOGV("android_media_SoundPool_setPriority");
+    SoundPool *ap = MusterSoundPool(env, thiz);
+    if (ap == NULL) return;
+    ap->setPriority(channelID, priority);
+}
+
+static void
+android_media_SoundPool_setLoop(JNIEnv *env, jobject thiz, jint channelID,
+        int loop)
+{
+    LOGV("android_media_SoundPool_setLoop");
+    SoundPool *ap = MusterSoundPool(env, thiz);
+    if (ap == NULL) return;
+    ap->setLoop(channelID, loop);
+}
+
+static void
+android_media_SoundPool_setRate(JNIEnv *env, jobject thiz, jint channelID,
+        float rate)
+{
+    LOGV("android_media_SoundPool_setRate");
+    SoundPool *ap = MusterSoundPool(env, thiz);
+    if (ap == NULL) return;
+    ap->setRate(channelID, rate);
+}
+
+static void
+android_media_SoundPool_native_setup(JNIEnv *env, jobject thiz,
+        jobject weak_this, jint maxChannels, jint streamType, jint srcQuality)
+{
+    LOGV("android_media_SoundPool_native_setup");
+    SoundPool *ap = new SoundPool(weak_this, maxChannels, streamType, srcQuality);
+    if (ap == NULL) {
+        jniThrowException(env, "java/lang/RuntimeException", "Out of memory");
+        return;
+    }
+
+    // save pointer to SoundPool C++ object in opaque field in Java object
+    env->SetIntField(thiz, fields.mNativeContext, (int)ap);
+}
+
+static void
+android_media_SoundPool_release(JNIEnv *env, jobject thiz)
+{
+    LOGV("android_media_SoundPool_release");
+    SoundPool *ap = MusterSoundPool(env, thiz);
+    if (ap != NULL) {
+        env->SetIntField(thiz, fields.mNativeContext, 0);
+        delete ap;
+    }
+}
+
+// ----------------------------------------------------------------------------
+
+// Dalvik VM type signatures
+static JNINativeMethod gMethods[] = {
+    {   "_load",
+        "(Ljava/lang/String;I)I",
+        (void *)android_media_SoundPool_load_URL
+    },
+    {   "_load",
+        "(Ljava/io/FileDescriptor;JJI)I",
+        (void *)android_media_SoundPool_load_FD
+    },
+    {   "unload",
+        "(I)Z",
+        (void *)android_media_SoundPool_unload
+    },
+    {   "play",
+        "(IFFIIF)I",
+        (void *)android_media_SoundPool_play
+    },
+    {   "pause",
+        "(I)V",
+        (void *)android_media_SoundPool_pause
+    },
+    {   "resume",
+        "(I)V",
+        (void *)android_media_SoundPool_resume
+    },
+    {   "stop",
+        "(I)V",
+        (void *)android_media_SoundPool_stop
+    },
+    {   "setVolume",
+        "(IFF)V",
+        (void *)android_media_SoundPool_setVolume
+    },
+    {   "setPriority",
+        "(II)V",
+        (void *)android_media_SoundPool_setPriority
+    },
+    {   "setLoop",
+        "(II)V",
+        (void *)android_media_SoundPool_setLoop
+    },
+    {   "setRate",
+        "(IF)V",
+        (void *)android_media_SoundPool_setRate
+    },
+    {   "native_setup",
+        "(Ljava/lang/Object;III)V",
+        (void*)android_media_SoundPool_native_setup
+    },
+    {   "release",
+        "()V",
+        (void*)android_media_SoundPool_release
+    }
+};
+
+static const char* const kClassPathName = "android/media/SoundPool";
+
+jint JNI_OnLoad(JavaVM* vm, void* reserved)
+{
+    JNIEnv* env = NULL;
+    jint result = -1;
+    jclass clazz;
+
+    if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
+        LOGE("ERROR: GetEnv failed\n");
+        goto bail;
+    }
+    assert(env != NULL);
+
+    clazz = env->FindClass(kClassPathName);
+    if (clazz == NULL) {
+        LOGE("Can't find %s", kClassPathName);
+        goto bail;
+    }
+
+    fields.mNativeContext = env->GetFieldID(clazz, "mNativeContext", "I");
+    if (fields.mNativeContext == NULL) {
+        LOGE("Can't find SoundPool.mNativeContext");
+        goto bail;
+    }
+
+    if (AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods)) < 0)
+        goto bail;
+
+    /* success -- return valid version number */
+    result = JNI_VERSION_1_4;
+
+bail:
+    return result;
+}
diff --git a/media/libdrm/Android.mk b/media/libdrm/Android.mk
new file mode 100644
index 0000000..5053e7d
--- /dev/null
+++ b/media/libdrm/Android.mk
@@ -0,0 +1 @@
+include $(call all-subdir-makefiles)
diff --git a/media/libdrm/MODULE_LICENSE_APACHE2 b/media/libdrm/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/media/libdrm/MODULE_LICENSE_APACHE2
diff --git a/media/libdrm/NOTICE b/media/libdrm/NOTICE
new file mode 100644
index 0000000..c5b1efa
--- /dev/null
+++ b/media/libdrm/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/libdrm/mobile1/Android.mk b/media/libdrm/mobile1/Android.mk
new file mode 100644
index 0000000..2065cd2
--- /dev/null
+++ b/media/libdrm/mobile1/Android.mk
@@ -0,0 +1,81 @@
+LOCAL_PATH := $(call my-dir)
+
+# ---------------------------------------
+# First project
+# 
+# Build DRM1 core library
+#
+# Output: libdrm1.so
+# ---------------------------------------
+include $(CLEAR_VARS)
+
+ifeq ($(TARGET_ARCH), arm)
+LOCAL_DRM_CFLAG = -DDRM_DEVICE_ARCH_ARM
+endif
+
+ifeq ($(TARGET_ARCH), x86)
+LOCAL_DRM_CFLAG = -DDRM_DEVICE_ARCH_X86
+endif
+
+# DRM 1.0 core source files
+LOCAL_SRC_FILES :=                  \
+    src/objmng/drm_decoder.c        \
+    src/objmng/drm_file.c           \
+    src/objmng/drm_i18n.c           \
+    src/objmng/drm_time.c           \
+    src/objmng/drm_api.c            \
+    src/objmng/drm_rights_manager.c \
+    src/parser/parser_dcf.c         \
+    src/parser/parser_dm.c          \
+    src/parser/parser_rel.c         \
+    src/xml/xml_tinyparser.c
+
+# Header files path
+LOCAL_C_INCLUDES :=                 \
+    $(LOCAL_PATH)/include           \
+    $(LOCAL_PATH)/include/objmng    \
+    $(LOCAL_PATH)/include/parser    \
+    $(LOCAL_PATH)/include/xml       \
+    external/aes                     \
+    $(call include-path-for, system-core)/cutils
+
+LOCAL_CFLAGS := $(LOCAL_DRM_CFLAG)
+
+LOCAL_SHARED_LIBRARIES :=   \
+	libaes                  \
+	libutils                \
+	libcutils
+
+LOCAL_MODULE := libdrm1
+
+include $(BUILD_SHARED_LIBRARY)
+
+# ---------------------------------------
+# Second project
+# 
+# Build DRM1 Java Native Interface(JNI) library
+#
+# Output: libdrm1_jni.so
+# ------------------------------------------------
+include $(CLEAR_VARS)
+
+# Source files of DRM1 Java Native Interfaces
+LOCAL_SRC_FILES :=      \
+    src/jni/drm1_jni.c
+
+# Header files path
+LOCAL_C_INCLUDES :=         \
+    $(LOCAL_PATH)/include   \
+	$(LOCAL_PATH)/include/parser \
+    $(JNI_H_INCLUDE)    \
+	$(call include-path-for, system-core)/cutils \
+	external/aes
+	
+
+LOCAL_SHARED_LIBRARIES := libdrm1 \
+	libutils                      \
+	libcutils
+
+LOCAL_MODULE := libdrm1_jni
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libdrm/mobile1/include/drm_common_types.h b/media/libdrm/mobile1/include/drm_common_types.h
new file mode 100644
index 0000000..c6bea61
--- /dev/null
+++ b/media/libdrm/mobile1/include/drm_common_types.h
@@ -0,0 +1,45 @@
+/*
+ * 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 __COMMON_TYPES_H__
+#define __COMMON_TYPES_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <assert.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#define Trace(...)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __COMMON_TYPES_H__ */
diff --git a/media/libdrm/mobile1/include/jni/drm1_jni.h b/media/libdrm/mobile1/include/jni/drm1_jni.h
new file mode 100644
index 0000000..64e78ad
--- /dev/null
+++ b/media/libdrm/mobile1/include/jni/drm1_jni.h
@@ -0,0 +1,242 @@
+/*
+ * 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 __DRM1_JNI_H__
+#define __DRM1_JNI_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class android_drm_mobile1_DrmRawContent */
+
+#undef android_drm_mobile1_DrmRawContent_DRM_FORWARD_LOCK
+#define android_drm_mobile1_DrmRawContent_DRM_FORWARD_LOCK 1L
+#undef android_drm_mobile1_DrmRawContent_DRM_COMBINED_DELIVERY
+#define android_drm_mobile1_DrmRawContent_DRM_COMBINED_DELIVERY 2L
+#undef android_drm_mobile1_DrmRawContent_DRM_SEPARATE_DELIVERY
+#define android_drm_mobile1_DrmRawContent_DRM_SEPARATE_DELIVERY 3L
+#undef android_drm_mobile1_DrmRawContent_DRM_SEPARATE_DELIVERY_DM
+#define android_drm_mobile1_DrmRawContent_DRM_SEPARATE_DELIVERY_DM 4L
+#undef android_drm_mobile1_DrmRawContent_DRM_MIMETYPE_MESSAGE
+#define android_drm_mobile1_DrmRawContent_DRM_MIMETYPE_MESSAGE 1L
+#undef android_drm_mobile1_DrmRawContent_DRM_MIMETYPE_CONTENT
+#define android_drm_mobile1_DrmRawContent_DRM_MIMETYPE_CONTENT 2L
+#undef android_drm_mobile1_DrmRawContent_JNI_DRM_SUCCESS
+#define android_drm_mobile1_DrmRawContent_JNI_DRM_SUCCESS 0L
+#undef android_drm_mobile1_DrmRawContent_JNI_DRM_FAILURE
+#define android_drm_mobile1_DrmRawContent_JNI_DRM_FAILURE -1L
+#undef android_drm_mobile1_DrmRawContent_JNI_DRM_EOF
+#define android_drm_mobile1_DrmRawContent_JNI_DRM_EOF -2L
+#undef android_drm_mobile1_DrmRawContent_JNI_DRM_UNKNOWN_DATA_LEN
+#define android_drm_mobile1_DrmRawContent_JNI_DRM_UNKNOWN_DATA_LEN -3L
+/*
+ * Class:     android_drm_mobile1_DrmRawContent
+ * Method:    nativeConstructDrmContent
+ * Signature: (Ljava/io/InputStream;II)I
+ */
+JNIEXPORT jint JNICALL Java_android_drm_mobile1_DrmRawContent_nativeConstructDrmContent
+  (JNIEnv *, jobject, jobject, jint, jint);
+
+/*
+ * Class:     android_drm_mobile1_DrmRawContent
+ * Method:    nativeGetRightsAddress
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_android_drm_mobile1_DrmRawContent_nativeGetRightsAddress
+  (JNIEnv *, jobject);
+
+/*
+ * Class:     android_drm_mobile1_DrmRawContent
+ * Method:    nativeGetDeliveryMethod
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_android_drm_mobile1_DrmRawContent_nativeGetDeliveryMethod
+  (JNIEnv *, jobject);
+
+/*
+ * Class:     android_drm_mobile1_DrmRawContent
+ * Method:    nativeReadPieceOfContent
+ * Signature: ([BIII)I
+ */
+JNIEXPORT jint JNICALL Java_android_drm_mobile1_DrmRawContent_nativeReadContent
+  (JNIEnv *, jobject, jbyteArray, jint, jint, jint);
+
+/*
+ * Class:     android_drm_mobile1_DrmRawContent
+ * Method:    nativeGetContentType
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_android_drm_mobile1_DrmRawContent_nativeGetContentType
+  (JNIEnv *, jobject);
+
+/*
+ * Class:     android_drm_mobile1_DrmRawContent
+ * Method:    nativeGetContentLength
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_android_drm_mobile1_DrmRawContent_nativeGetContentLength
+  (JNIEnv *, jobject);
+
+/*
+ * Class:     android_drm_mobile1_DrmRawContent
+ * Method:    finalize
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_android_drm_mobile1_DrmRawContent_finalize
+  (JNIEnv *, jobject);
+
+/* Header for class android_drm_mobile1_DrmRights */
+
+#undef android_drm_mobile1_DrmRights_DRM_PERMISSION_PLAY
+#define android_drm_mobile1_DrmRights_DRM_PERMISSION_PLAY 1L
+#undef android_drm_mobile1_DrmRights_DRM_PERMISSION_DISPLAY
+#define android_drm_mobile1_DrmRights_DRM_PERMISSION_DISPLAY 2L
+#undef android_drm_mobile1_DrmRights_DRM_PERMISSION_EXECUTE
+#define android_drm_mobile1_DrmRights_DRM_PERMISSION_EXECUTE 3L
+#undef android_drm_mobile1_DrmRights_DRM_PERMISSION_PRINT
+#define android_drm_mobile1_DrmRights_DRM_PERMISSION_PRINT 4L
+#undef android_drm_mobile1_DrmRights_DRM_CONSUME_RIGHTS_SUCCESS
+#define android_drm_mobile1_DrmRights_DRM_CONSUME_RIGHTS_SUCCESS 0L
+#undef android_drm_mobile1_DrmRights_DRM_CONSUME_RIGHTS_FAILURE
+#define android_drm_mobile1_DrmRights_DRM_CONSUME_RIGHTS_FAILURE -1L
+#undef android_drm_mobile1_DrmRights_JNI_DRM_SUCCESS
+#define android_drm_mobile1_DrmRights_JNI_DRM_SUCCESS 0L
+#undef android_drm_mobile1_DrmRights_JNI_DRM_FAILURE
+#define android_drm_mobile1_DrmRights_JNI_DRM_FAILURE -1L
+/*
+ * Class:     android_drm_mobile1_DrmRights
+ * Method:    nativeGetConstraintInfo
+ * Signature: (ILandroid/drm/mobile1/DrmConstraintInfo;)I
+ */
+JNIEXPORT jint JNICALL Java_android_drm_mobile1_DrmRights_nativeGetConstraintInfo
+  (JNIEnv *, jobject, jint, jobject);
+
+/*
+ * Class:     android_drm_mobile1_DrmRights
+ * Method:    nativeConsumeRights
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_android_drm_mobile1_DrmRights_nativeConsumeRights
+  (JNIEnv *, jobject, jint);
+
+/* Header for class android_drm_mobile1_DrmRightsManager */
+
+#undef android_drm_mobile1_DrmRightsManager_DRM_MIMETYPE_RIGHTS_XML
+#define android_drm_mobile1_DrmRightsManager_DRM_MIMETYPE_RIGHTS_XML 3L
+#undef android_drm_mobile1_DrmRightsManager_DRM_MIMETYPE_RIGHTS_WBXML
+#define android_drm_mobile1_DrmRightsManager_DRM_MIMETYPE_RIGHTS_WBXML 4L
+#undef android_drm_mobile1_DrmRightsManager_DRM_MIMETYPE_MESSAGE
+#define android_drm_mobile1_DrmRightsManager_DRM_MIMETYPE_MESSAGE 1L
+#undef android_drm_mobile1_DrmRightsManager_JNI_DRM_SUCCESS
+#define android_drm_mobile1_DrmRightsManager_JNI_DRM_SUCCESS 0L
+#undef android_drm_mobile1_DrmRightsManager_JNI_DRM_FAILURE
+#define android_drm_mobile1_DrmRightsManager_JNI_DRM_FAILURE -1L
+/* Inaccessible static: singleton */
+/*
+ * Class:     android_drm_mobile1_DrmRightsManager
+ * Method:    nativeInstallDrmRights
+ * Signature: (Ljava/io/InputStream;IILandroid/drm/mobile1/DrmRights;)I
+ */
+JNIEXPORT jint JNICALL Java_android_drm_mobile1_DrmRightsManager_nativeInstallDrmRights
+  (JNIEnv *, jobject, jobject, jint, jint, jobject);
+
+/*
+ * Class:     android_drm_mobile1_DrmRightsManager
+ * Method:    nativeQueryRights
+ * Signature: (Landroid/drm/mobile1/DrmRawContent;Landroid/drm/mobile1/DrmRights;)I
+ */
+JNIEXPORT jint JNICALL Java_android_drm_mobile1_DrmRightsManager_nativeQueryRights
+  (JNIEnv *, jobject, jobject, jobject);
+
+/*
+ * Class:     android_drm_mobile1_DrmRightsManager
+ * Method:    nativeGetRightsNumber
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_android_drm_mobile1_DrmRightsManager_nativeGetNumOfRights
+  (JNIEnv *, jobject);
+
+/*
+ * Class:     android_drm_mobile1_DrmRightsManager
+ * Method:    nativeGetRightsList
+ * Signature: ([Landroid/drm/mobile1/DrmRights;I)I
+ */
+JNIEXPORT jint JNICALL Java_android_drm_mobile1_DrmRightsManager_nativeGetRightsList
+  (JNIEnv *, jobject, jobjectArray, jint);
+
+/*
+ * Class:     android_drm_mobile1_DrmRightsManager
+ * Method:    nativeDeleteRights
+ * Signature: (Landroid/drm/mobile1/DrmRights;)I
+ */
+JNIEXPORT jint JNICALL Java_android_drm_mobile1_DrmRightsManager_nativeDeleteRights
+  (JNIEnv *, jobject, jobject);
+
+/**
+ * DRM return value defines
+ */
+#define JNI_DRM_SUCCESS \
+    android_drm_mobile1_DrmRawContent_JNI_DRM_SUCCESS   /**< Successful operation */
+#define JNI_DRM_FAILURE \
+    android_drm_mobile1_DrmRawContent_JNI_DRM_FAILURE   /**< General failure */
+#define JNI_DRM_EOF \
+    android_drm_mobile1_DrmRawContent_JNI_DRM_EOF       /**< Indicates the end of the DRM content is reached */
+#define JNI_DRM_UNKNOWN_DATA_LEN \
+    android_drm_mobile1_DrmRawContent_JNI_DRM_UNKNOWN_DATA_LEN  /**< Indicates the data length is unknown */
+
+/**
+ * DRM MIME type defines
+ */
+#define JNI_DRM_MIMETYPE_MESSAGE \
+    android_drm_mobile1_DrmRawContent_DRM_MIMETYPE_MESSAGE          /**< The "application/vnd.oma.drm.message" MIME type */
+#define JNI_DRM_MIMETYPE_CONTENT \
+    android_drm_mobile1_DrmRawContent_DRM_MIMETYPE_CONTENT          /**< The "application/vnd.oma.drm.content" MIME type */
+#define JNI_DRM_MIMETYPE_RIGHTS_XML \
+    android_drm_mobile1_DrmRightsManager_DRM_MIMETYPE_RIGHTS_XML    /**< The "application/vnd.oma.drm.rights+xml" MIME type */
+#define JNI_DRM_MIMETYPE_RIGHTS_WBXML \
+    android_drm_mobile1_DrmRightsManager_DRM_MIMETYPE_RIGHTS_WBXML  /**< The "application/vnd.oma.drm.rights+wbxml" MIME type */
+
+/**
+ * DRM permission defines
+ */
+#define JNI_DRM_PERMISSION_PLAY \
+    android_drm_mobile1_DrmRights_DRM_PERMISSION_PLAY       /**< The permission to play */
+#define JNI_DRM_PERMISSION_DISPLAY \
+    android_drm_mobile1_DrmRights_DRM_PERMISSION_DISPLAY    /**< The permission to display */
+#define JNI_DRM_PERMISSION_EXECUTE \
+    android_drm_mobile1_DrmRights_DRM_PERMISSION_EXECUTE    /**< The permission to execute */
+#define JNI_DRM_PERMISSION_PRINT \
+    android_drm_mobile1_DrmRights_DRM_PERMISSION_PRINT      /**< The permission to print */
+
+/**
+ * DRM delivery type defines
+ */
+#define JNI_DRM_FORWARD_LOCK \
+    android_drm_mobile1_DrmRawContent_DRM_FORWARD_LOCK          /**< forward lock */
+#define JNI_DRM_COMBINED_DELIVERY \
+    android_drm_mobile1_DrmRawContent_DRM_COMBINED_DELIVERY     /**< combined delivery */
+#define JNI_DRM_SEPARATE_DELIVERY \
+    android_drm_mobile1_DrmRawContent_DRM_SEPARATE_DELIVERY     /**< separate delivery */
+#define JNI_DRM_SEPARATE_DELIVERY_DM \
+    android_drm_mobile1_DrmRawContent_DRM_SEPARATE_DELIVERY_DM  /**< separate delivery DRM message */
+#ifdef __cplusplus
+}
+#endif
+#endif /* __DRM1_JNI_H__ */
+
diff --git a/media/libdrm/mobile1/include/objmng/drm_decoder.h b/media/libdrm/mobile1/include/objmng/drm_decoder.h
new file mode 100644
index 0000000..a769c81
--- /dev/null
+++ b/media/libdrm/mobile1/include/objmng/drm_decoder.h
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+
+/**
+ * @file drm_decoder.h
+ *
+ * provide service to decode base64 data.
+ *
+ * <!-- #interface list begin -->
+ * \section drm decoder interface
+ * - drm_decodeBase64()
+ * <!-- #interface list end -->
+ */
+
+#ifndef __DRM_DECODER_H__
+#define __DRM_DECODER_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <drm_common_types.h>
+
+/**
+ * Decode base64
+ * \param dest          dest buffer to save decode base64 data
+ * \param destLen       dest buffer length
+ * \param src           source data to be decoded
+ * \param srcLen        source buffer length, and when return, give out how many bytes has been decoded
+ * \return
+ *        -when success, return a positive integer of dest buffer length,
+ *                       if input dest buffer is NULL or destLen is 0,
+ *                       return dest buffer length that user should allocate to save decoding data
+ *        -when failed, return -1
+ */
+int32_t drm_decodeBase64(uint8_t * dest, int32_t destLen, uint8_t * src, int32_t * srcLen);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __DRM_DECODER_H__ */
diff --git a/media/libdrm/mobile1/include/objmng/drm_file.h b/media/libdrm/mobile1/include/objmng/drm_file.h
new file mode 100644
index 0000000..b94ddd0
--- /dev/null
+++ b/media/libdrm/mobile1/include/objmng/drm_file.h
@@ -0,0 +1,296 @@
+/*
+ * 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.
+ */
+
+
+/**
+ * File Porting Layer.
+ */
+#ifndef __DRM_FILE_H__
+#define __DRM_FILE_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <drm_common_types.h>
+
+/** Type value of a regular file or file name. */
+#define DRM_FILE_ISREG 1
+/** Type value of a directory or directory name. */
+#define DRM_FILE_ISDIR 2
+/** Type value of a filter name */
+#define DRM_FILE_ISFILTER 3
+
+
+/** Return code that indicates successful completion of an operation. */
+#define DRM_FILE_SUCCESS 0
+/** Indicates that an operation failed. */
+#define DRM_FILE_FAILURE -1
+/** Indicates that the a DRM_file_read() call reached the end of the file. */
+#define DRM_FILE_EOF -2
+
+
+/** Open for read access. */
+#define DRM_FILE_MODE_READ 1
+/** Open for write access. */
+#define DRM_FILE_MODE_WRITE 2
+
+
+#ifndef MAX_FILENAME_LEN
+/** Maximum number of characters that a filename may have. By default assumes
+ *  that the entry results of DRM_file_listNextEntry() are returned in the async state
+ *  buffer, after the #DRM_file_result_s, and calculates the maximum name
+ *  from that.
+ */
+#define MAX_FILENAME_LEN 1024
+#endif
+
+
+/**
+ * Performs one-time initialization of the File System (FS).
+ * This function is called once during the lifetime of an application,
+ * and before any call to <code>DRM_file_*</code> functions by this application.
+ * When several applications are using the file interface, this function may be called
+ * several times, once per application.
+ *
+ * @return #DRM_FILE_SUCCESS, #DRM_FILE_FAILURE.
+ */
+int32_t DRM_file_startup(void);
+
+/**
+ * Returns the length of a file (by name, opened or unopened).
+ *
+ * @param name Name of the file, UCS-2 encoded.
+ * @param nameChars Number characters encoded in name.
+ * asynchronous operation returns #DRM_FILE_WOULDBLOCK.
+ * @return #DRM_FILE_WOULDBLOCK, #DRM_FILE_FAILURE or the file length.
+ */
+int32_t DRM_file_getFileLength(const uint16_t* name,
+                               int32_t nameChars);
+
+/**
+ * Initializes a list iteration session.
+ *
+ * @param prefix Prefix that must be matched, UCS-2 encoded. *
+ * @param prefixChars Number characters encoded in prefix.
+ * @param session List session identifier.
+ * @param iteration List iteration identifier.
+ *
+ * @return #DRM_FILE_WOULDBLOCK, #DRM_FILE_SUCCESS, #DRM_FILE_FAILURE.
+ */
+int32_t DRM_file_listOpen(const uint16_t* prefix,
+                          int32_t prefixChars,
+                          int32_t* session,
+                          int32_t* iteration);
+
+/**
+ * Used to fetch a list of file names that match a given name prefix.
+ *
+ * @param prefix See DRM_file_listOpen(). This does not change during the
+ * iteration session.
+ * @param prefixChars See DRM_file_listOpen(). This does not change during
+ * the iteration session.
+ * @param entry Buffer parameter to return the next file name that matches the
+ * #prefix parameter, if any, when the function returns a positive number of
+ * characters.
+ * @param entryBytes Size of entry in bytes.
+ * @param session See DRM_file_listOpen().
+ * @param iteration See DRM_file_listOpen().
+ * @return #DRM_FILE_WOULDBLOCK, #DRM_FILE_FAILURE or the number of
+ * characters encoded in entry. Returns 0 when the end of the list is reached.
+ */
+int32_t DRM_file_listNextEntry(const uint16_t* prefix,
+                               int32_t prefixChars,
+                               uint16_t* entry,
+                               int32_t entryBytes,
+                               int32_t* session,
+                               int32_t* iteration);
+
+/**
+ * Ends a list iteration session. Notifies the implementation
+ * that the list session is over and that any session resources
+ * can be released.
+ *
+ * @param session See DRM_file_listOpen().
+ * @param iteration See DRM_file_listOpen().
+ * @return #DRM_FILE_WOULDBLOCK, #DRM_FILE_SUCCESS, #DRM_FILE_FAILURE.
+ */
+int32_t DRM_file_listClose(int32_t session, int32_t iteration);
+
+/**
+ * Renames a file, given its old name. The file or directory is renamed
+ * immediately on the actual file system upon invocation of this method.
+ * Any open handles on the file specified by oldName become invalid after
+ * this method has been called.
+ *
+ * @param oldName Current file name (unopened), UCS-2 encoded.
+ * @param oldNameChars Number of characters encoded on oldName.
+ * @param newName New name for the file (unopened), UCS-2 encoded.
+ * @param newNameChars Number of characters encoded on newName.
+ * @return #DRM_FILE_WOULDBLOCK, #DRM_FILE_SUCCESS, #DRM_FILE_FAILURE. In particular,
+ * #DRM_FILE_FAILURE if a file or directory already exists with the new name.
+ */
+int32_t DRM_file_rename(const uint16_t* oldName,
+                        int32_t oldNameChars,
+                        const uint16_t* newName,
+                        int32_t newNameChars);
+
+/**
+ * Tests if a file exists given its name.
+ *
+ * @param name Name of the file, UCS-2 encoded.
+ * @param nameChars Number of characters encoded in name.
+ * @return #DRM_FILE_WOULDBLOCK, #DRM_FILE_ISREG, #DRM_FILE_ISDIR, #DRM_FILE_FAILURE. If name
+ * exists, returns #DRM_FILE_ISREG if it is a regular file and #DRM_FILE_ISDIR if it is a directory.
+ * Returns #DRM_FILE_FAILURE in all other cases, including those where name exists but is neither
+ * a regular file nor a directory. Platforms that do not support directories MUST NOT return
+ * #DRM_FILE_ISDIR.
+ */
+int32_t DRM_file_exists(const uint16_t* name,
+                        int32_t nameChars);
+
+/**
+ * Opens a file with the given name and returns its file handle.
+ *
+ * @param name Name of the file, UCS-2 encoded.
+ * @param nameChars Number of characters encoded in name.
+ * @param mode Any combination of the #DRM_FILE_MODE_READ and
+ * #DRM_FILE_MODE_WRITE flags. If the file does not exist and mode contains the
+ * #DRM_FILE_MODE_WRITE flag, then the file is automatically created. If the
+ * file exists and the mode contains the #DRM_FILE_MODE_WRITE flag, the file is
+ * opened so it can be modified, but the data is not modified by the open call.
+ * In all cases the current position is set to the start of the file.
+ * The following table shows how to map the mode semantics above to UNIX
+ * fopen-style modes.  For brevity in the table, R=#DRM_FILE_MODE_READ,
+ * W=#DRM_FILE_MODE_WRITE, E=File exists:
+ * <table>
+ * <tr><td>RW</td><td>E</td><td>Maps-to</td></tr>
+ * <tr><td>00</td><td>0</td><td>Return #DRM_FILE_FAILURE</td></tr>
+ * <tr><td>00</td><td>1</td><td>Return #DRM_FILE_FAILURE</td></tr>
+ * <tr><td>01</td><td>0</td><td>Use fopen mode "w"</td></tr>
+ * <tr><td>01</td><td>1</td><td>Use fopen mode "a" and fseek to the start</td></tr>
+ * <tr><td>10</td><td>0</td><td>Return #DRM_FILE_FAILURE</td></tr>
+ * <tr><td>10</td><td>1</td><td>Use fopen mode "r"</td></tr>
+ * <tr><td>11</td><td>0</td><td>Use fopen mode "w+"</td></tr>
+ * <tr><td>11</td><td>1</td><td>Use fopen mode "r+"</td></tr>
+ * </table>
+ * @param handle Pointer where the result handle value is placed when the function
+ * is called synchronously.
+ * @return #DRM_FILE_WOULDBLOCK, #DRM_FILE_SUCCESS, #DRM_FILE_FAILURE.
+ */
+int32_t DRM_file_open(const uint16_t* name,
+                      int32_t nameChars,
+                      int32_t mode,
+                      int32_t* handle);
+
+/**
+ * Deletes a file given its name, UCS-2 encoded. The file or directory is
+ * deleted immediately on the actual file system upon invocation of this
+ * method. Any open handles on the file specified by name become invalid
+ * after this method has been called.
+ *
+ * If the port needs to ensure that a specific application does not exceed a given storage
+ * space quota, then the bytes freed by the deletion must be added to the available space for
+ * that application.
+ *
+ * @param name Name of the file, UCS-2 encoded.
+ * @param nameChars Number of characters encoded in name.
+ * @return #DRM_FILE_WOULDBLOCK, #DRM_FILE_SUCCESS, #DRM_FILE_FAILURE.
+ */
+int32_t DRM_file_delete(const uint16_t* name,
+                        int32_t nameChars);
+
+/**
+ * Read bytes from a file at the current position to a buffer. Afterwards the
+ * new file position is the byte after the last byte read.
+ * DRM_FILE_FAILURE is returned if the handle is invalid (e.g., as a
+ * consquence of DRM_file_delete, DRM_file_rename, or DRM_file_close).
+ *
+ * @param handle File handle as returned by DRM_file_open().
+ * @param dst Buffer where the data is to be copied.
+ * @param length Number of bytes to be copied.
+ * @return #DRM_FILE_WOULDBLOCK, #DRM_FILE_SUCCESS, #DRM_FILE_FAILURE, #DRM_FILE_EOF
+ *         or the number of bytes that were read, i.e. in the range 0..length.
+ */
+int32_t DRM_file_read(int32_t handle,
+                      uint8_t* dst,
+                      int32_t length);
+
+/**
+ * Write bytes from a buffer to the file at the current position.  If the
+ * current position + number of bytes written > current size of the file,
+ * then the file is grown.  Afterwards the new file position is the byte
+ * after the last byte written.
+ * DRM_FILE_FAILURE is returned if the handle is invalid (e.g., as a
+ * consquence of DRM_file_delete, DRM_file_rename, or DRM_file_close).
+ *
+ * @param handle File handle as returned by DRM_file_open().
+ * @param src Buffer that contains the bytes to be written.
+ * @param length Number of bytes to be written.
+ * If the port needs to ensure that a specific application does not exceed a given storage
+ * space quota, the implementation must make sure the call does not violate that invariant.
+ * @return #DRM_FILE_WOULDBLOCK, #DRM_FILE_FAILURE or the number of bytes
+ *         that were written. This number must be in the range 0..length.
+ *         Returns #DRM_FILE_FAILURE when storage is full or exceeds quota.
+ */
+int32_t DRM_file_write(int32_t handle,
+                       const uint8_t* src,
+                       int32_t length);
+
+/**
+ * Closes a file.
+ * DRM_FILE_SUCCESS is returned if the handle is invalid (e.g., as a
+ * consquence of DRM_file_delete or DRM_file_rename).
+ *
+ * @param handle File handle as returned by DRM_file_open().
+ * @return #DRM_FILE_WOULDBLOCK, #DRM_FILE_SUCCESS, #DRM_FILE_FAILURE.
+ */
+int32_t DRM_file_close(int32_t handle);
+
+/**
+ * Sets the current position in an opened file.
+ * DRM_FILE_FAILURE is returned if the handle is invalid (e.g., as a
+ * consquence of DRM_file_delete, DRM_file_rename, or DRM_file_close).
+ *
+ * @param handle File handle as returned by DRM_file_open().
+ * @param value The new current position of the file. If value is greater
+ * than the length of the file then the file should be extended. The contents
+ * of the newly extended portion of the file is undefined.
+ * If the port needs to ensure that a specific application does not exceed a given storage
+ * space quota, the implementation must make sure the call does not violate that invariant.
+ * @return #DRM_FILE_WOULDBLOCK, #DRM_FILE_SUCCESS, #DRM_FILE_FAILURE.
+ *         Returns #DRM_FILE_FAILURE when storage is full or exceeds quota.
+ */
+int32_t DRM_file_setPosition(int32_t handle, int32_t value);
+
+/**
+ * Creates a directory with the assigned name and full file permissions on
+ * the file system. The full path to the new directory must already exist.
+ * The directory is created immediately on the actual file system upon
+ * invocation of this method.
+ *
+ * @param name Name of the directory, UCS-2 encoded.
+ * @param nameChars Number of characters encoded in name.
+ * @return #DRM_FILE_WOULDBLOCK, #DRM_FILE_SUCCESS, #DRM_FILE_FAILURE.
+ */
+int32_t DRM_file_mkdir(const uint16_t* name,
+                       int32_t nameChars);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __DRM_FILE_H__ */
diff --git a/media/libdrm/mobile1/include/objmng/drm_i18n.h b/media/libdrm/mobile1/include/objmng/drm_i18n.h
new file mode 100644
index 0000000..7487e9b
--- /dev/null
+++ b/media/libdrm/mobile1/include/objmng/drm_i18n.h
@@ -0,0 +1,107 @@
+/*
+ * 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 __DRM_I18N_H__
+#define __DRM_I18N_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <drm_common_types.h>
+
+/**
+ * @name Charset value defines
+ * @ingroup i18n
+ *
+ * Charset value defines
+ * see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/intl/unicode_81rn.asp
+ */
+typedef enum {
+    DRM_CHARSET_GBK        = 936,      /** Simplified Chinese GBK (CP936) */
+    DRM_CHARSET_GB2312     = 20936,    /** Simplified Chinese GB2312 (CP936) */
+    DRM_CHARSET_BIG5       = 950,      /** BIG5 (CP950) */
+    DRM_CHARSET_LATIN1     = 28591,    /** ISO 8859-1, Latin 1 */
+    DRM_CHARSET_LATIN2     = 28592,    /** ISO 8859-2, Latin 2 */
+    DRM_CHARSET_LATIN3     = 28593,    /** ISO 8859-3, Latin 3 */
+    DRM_CHARSET_LATIN4     = 28594,    /** ISO 8859-4, Latin 4 */
+    DRM_CHARSET_CYRILLIC   = 28595,    /** ISO 8859-5, Cyrillic */
+    DRM_CHARSET_ARABIC     = 28596,    /** ISO 8859-6, Arabic */
+    DRM_CHARSET_GREEK      = 28597,    /** ISO 8859-7, Greek */
+    DRM_CHARSET_HEBREW     = 28598,    /** ISO 8859-8, Hebrew */
+    DRM_CHARSET_LATIN5     = 28599,    /** ISO 8859-9, Latin 5 */
+    DRM_CHARSET_LATIN6     = 865,      /** ISO 8859-10, Latin 6 (not sure here) */
+    DRM_CHARSET_THAI       = 874,      /** ISO 8859-11, Thai */
+    DRM_CHARSET_LATIN7     = 1257,     /** ISO 8859-13, Latin 7 (not sure here) */
+    DRM_CHARSET_LATIN8     = 38598,    /** ISO 8859-14, Latin 8 (not sure here) */
+    DRM_CHARSET_LATIN9     = 28605,    /** ISO 8859-15, Latin 9 */
+    DRM_CHARSET_LATIN10    = 28606,    /** ISO 8859-16, Latin 10 */
+    DRM_CHARSET_UTF8       = 65001,    /** UTF-8 */
+    DRM_CHARSET_UTF16LE    = 1200,     /** UTF-16 LE */
+    DRM_CHARSET_UTF16BE    = 1201,     /** UTF-16 BE */
+    DRM_CHARSET_HINDI      = 57002,    /** Hindi/Mac Devanagari */
+    DRM_CHARSET_UNSUPPORTED = -1
+} DRM_Charset_t;
+
+/**
+ * Convert multibyte string of specified charset to unicode string.
+ * Note NO terminating '\0' will be appended to the output unicode string.
+ *
+ * @param charset Charset of the multibyte string.
+ * @param mbs Multibyte string to be converted.
+ * @param mbsLen Number of the bytes (in mbs) to be converted.
+ * @param wcsBuf Buffer for the converted unicode characters.
+ *               If wcsBuf is NULL, the function returns the number of unicode
+ *               characters required for the buffer.
+ * @param bufSizeInWideChar The size (in wide char) of wcsBuf
+ * @param bytesConsumed The number of bytes in mbs that have been successfully
+ *                      converted. The value of *bytesConsumed is undefined
+ *                      if wcsBuf is NULL.
+ *
+ * @return Number of the successfully converted unicode characters if wcsBuf
+ *         is not NULL. If wcsBuf is NULL, returns required unicode buffer
+ *         size. -1 for unrecoverable errors.
+ */
+int32_t DRM_i18n_mbsToWcs(DRM_Charset_t charset,
+        const uint8_t *mbs, int32_t mbsLen,
+        uint16_t *wcsBuf, int32_t bufSizeInWideChar,
+        int32_t *bytesConsumed);
+
+/**
+ * Convert unicode string to multibyte string with specified charset.
+ * Note NO terminating '\0' will be appended to the output multibyte string.
+ *
+ * @param charset Charset of the multibyte string to be converted to.
+ * @param wcs     Unicode string to be converted.
+ * @param wcsLen  Number of the unicode characters (in wcs) to be converted.
+ * @param mbsBuf  Buffer for converted multibyte characters.
+ *                If mbsBuf is NULL, the function returns the number of bytes
+ *                required for the buffer.
+ * @param bufSizeInByte The size (in byte) of mbsBuf.
+ *
+ * @return Number of the successfully converted bytes.
+ */
+int32_t DRM_i18n_wcsToMbs(DRM_Charset_t charset,
+        const uint16_t *wcs, int32_t wcsLen,
+        uint8_t *mbsBuf, int32_t bufSizeInByte);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/media/libdrm/mobile1/include/objmng/drm_inner.h b/media/libdrm/mobile1/include/objmng/drm_inner.h
new file mode 100644
index 0000000..55234f8
--- /dev/null
+++ b/media/libdrm/mobile1/include/objmng/drm_inner.h
@@ -0,0 +1,90 @@
+/*
+ * 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 __DRM_INNER_H__
+#define __DRM_INNER_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <drm_common_types.h>
+
+#define INT_2_YMD_HMS(year, mon, day, date, hour, min, sec, time) do{\
+    year = date / 10000;\
+    mon = date % 10000 / 100;\
+    day = date %100;\
+    hour = time / 10000;\
+    min = time % 10000 / 100;\
+    sec = time % 100;\
+}while(0)
+
+/**
+ * Define the max malloc length for a DRM.
+ */
+#define DRM_MAX_MALLOC_LEN          (50 * 1024) /* 50K */
+
+#define DRM_ONE_AES_BLOCK_LEN       16
+#define DRM_TWO_AES_BLOCK_LEN       32
+
+typedef struct _T_DRM_DM_Binary_Node {
+    uint8_t boundary[256];
+} T_DRM_DM_Binary_Node;
+
+typedef struct _T_DRM_DM_Base64_Node {
+    uint8_t boundary[256];
+    uint8_t b64DecodeData[4];
+    int32_t b64DecodeDataLen;
+} T_DRM_DM_Base64_Node;
+
+typedef struct _T_DRM_Dcf_Node {
+    uint8_t rightsIssuer[256];
+    int32_t encContentLength;
+    uint8_t aesDecData[16];
+    int32_t aesDecDataLen;
+    int32_t aesDecDataOff;
+    uint8_t aesBackupBuf[16];
+    int32_t bAesBackupBuf;
+} T_DRM_Dcf_Node;
+
+typedef struct _T_DRM_Session_Node {
+    int32_t sessionId;
+    int32_t inputHandle;
+    int32_t mimeType;
+    int32_t (*getInputDataLengthFunc)(int32_t inputHandle);
+    int32_t (*readInputDataFunc)(int32_t inputHandle, uint8_t* buf, int32_t bufLen);
+    int32_t (*seekInputDataFunc)(int32_t inputHandle, int32_t offset);
+    int32_t deliveryMethod;
+    int32_t transferEncoding;
+    uint8_t contentType[64];
+    int32_t contentLength;
+    int32_t contentOffset;
+    uint8_t contentID[256];
+    uint8_t* rawContent;
+    int32_t rawContentLen;
+    int32_t bEndData;
+    uint8_t* readBuf;
+    int32_t readBufLen;
+    int32_t readBufOff;
+    void* infoStruct;
+    struct _T_DRM_Session_Node* next;
+} T_DRM_Session_Node;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __DRM_INNER_H__ */
diff --git a/media/libdrm/mobile1/include/objmng/drm_rights_manager.h b/media/libdrm/mobile1/include/objmng/drm_rights_manager.h
new file mode 100644
index 0000000..dd2116c
--- /dev/null
+++ b/media/libdrm/mobile1/include/objmng/drm_rights_manager.h
@@ -0,0 +1,183 @@
+/*
+ * 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 __DRM_RIGHTS_MANAGER_H__
+#define __DRM_RIGHTS_MANAGER_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <drm_common_types.h>
+#include <parser_rel.h>
+#include <aes.h>
+
+#ifdef DRM_DEVICE_ARCH_ARM
+#define ANDROID_DRM_CORE_PATH   "/data/drm/rights/"
+#define DRM_UID_FILE_PATH       "/data/drm/rights/uid.txt"
+#else
+#define ANDROID_DRM_CORE_PATH   "/home/user/golf/esmertec/device/out/debug/host/linux-x86/product/sim/data/data/com.android.drm.mobile1/"
+#define DRM_UID_FILE_PATH       "/home/user/golf/esmertec/device/out/debug/host/linux-x86/product/sim/data/data/com.android.drm.mobile1/uid.txt"
+#endif
+
+#define EXTENSION_NAME_INFO     ".info"
+
+#define GET_ID      1
+#define GET_UID     2
+
+#define GET_ROAMOUNT        1
+#define GET_ALL_RO          2
+#define SAVE_ALL_RO         3
+#define GET_A_RO            4
+#define SAVE_A_RO           5
+
+/**
+ * Get the id or uid from the "uid.txt" file.
+ *
+ * \param Uid       The content id for a specially DRM object.
+ * \param id        The id number managed by DRM engine for a specially DRM object.
+ * \param option    The option to get id or uid, the value includes: GET_ID, GET_UID.
+ *
+ * \return
+ *      -TRUE, if the operation successfully.
+ *      -FALSE, if the operation failed.
+ */
+int32_t drm_readFromUidTxt(uint8_t* Uid, int32_t* id, int32_t option);
+
+/**
+ * Save or read the rights information on the "id.info" file.
+ *
+ * \param id        The id number managed by DRM engine for a specially DRM object.
+ * \param Ro        The rights structure to save the rights information.
+ * \param RoAmount  The number of rights for this DRM object.
+ * \param option    The option include: GET_ROAMOUNT, GET_ALL_RO, SAVE_ALL_RO, GET_A_RO, SAVE_A_RO.
+ *
+ * \return
+ *      -TRUE, if the operation successfully.
+ *      -FALSE, if the operation failed.
+ */
+int32_t drm_writeOrReadInfo(int32_t id, T_DRM_Rights* Ro, int32_t* RoAmount, int32_t option);
+
+/**
+ * Append a rights information to DRM engine storage.
+ *
+ * \param Ro        The rights structure to save the rights information.
+ *
+ * return
+ *      -TRUE, if the operation successfully.
+ *      -FALSE, if the operation failed.
+ */
+int32_t drm_appendRightsInfo(T_DRM_Rights* rights);
+
+/**
+ * Get the mex id number from the "uid.txt" file.
+ *
+ * \return
+ *      -an integer to indicate the max id number.
+ *      -(-1), if the operation failed.
+ */
+int32_t drm_getMaxIdFromUidTxt();
+
+/**
+ * Remove the "id.info" file if all the rights for this DRM object has been deleted.
+ *
+ * \param id        The id number managed by DRM engine for a specially DRM object.
+ *
+ * \return
+ *      -TRUE, if the operation successfully.
+ *      -FALSE, if the operation failed.
+ */
+int32_t drm_removeIdInfoFile(int32_t id);
+
+/**
+ * Update the "uid.txt" file when delete the rights object.
+ *
+ * \param id        The id number managed by DRM engine for a specially DRM object.
+ *
+ * \return
+ *      -TRUE, if the operation successfully.
+ *      -FALSE, if the operation failed.
+ */
+int32_t drm_updateUidTxtWhenDelete(int32_t id);
+
+/**
+ * Get the CEK according the given content id.
+ *
+ * \param uid       The content id for a specially DRM object.
+ * \param KeyValue  The buffer to save the CEK.
+ *
+ * \return
+ *      -TRUE, if the operation successfully.
+ *      -FALSE, if the operation failed.
+ */
+int32_t drm_getKey(uint8_t* uid, uint8_t* KeyValue);
+
+/**
+ * Discard the padding bytes in DCF decrypted data.
+ *
+ * \param decryptedBuf      The aes decrypted data buffer to be scanned.
+ * \param decryptedBufLen   The length of the buffer. And save the output result.
+ *
+ * \return
+ *      -0
+ */
+void drm_discardPaddingByte(uint8_t *decryptedBuf, int32_t *decryptedBufLen);
+
+/**
+ * Decrypt the media data according the CEK.
+ *
+ * \param Buffer    The buffer to decrypted and also used to save the output data.
+ * \param BufferLen The length of the buffer data and also save the output data length.
+ * \param ctx       The structure of the CEK.
+ *
+ * \return
+ *      -0
+ */
+int32_t drm_aesDecBuffer(uint8_t * Buffer, int32_t * BufferLen, aes_decrypt_ctx ctx[1]);
+
+/**
+ * Update the DCF data length according the CEK.
+ *
+ * \param pDcfLastData  The last several byte for the DCF.
+ * \param keyValue  The CEK of the DRM content.
+ * \param moreBytes Output the more bytes for discarded.
+ *
+ * \return
+ *      -TRUE, if the operation successfully.
+ *      -FALSE, if the operation failed.
+ */
+int32_t drm_updateDcfDataLen(uint8_t* pDcfLastData, uint8_t* keyValue, int32_t* moreBytes);
+
+/**
+ * Check and update the rights for a specially DRM content.
+ *
+ * \param id        The id number managed by DRM engine for a specially DRM object.
+ * \param permission    The permission to be check and updated.
+ *
+ * \return
+ *      -DRM_SUCCESS, if there is a valid rights and update it successfully.
+ *      -DRM_NO_RIGHTS, if there is no rights for this content.
+ *      -DRM_RIGHTS_PENDING, if the rights is pending.
+ *      -DRM_RIGHTS_EXPIRED, if the rights has expired.
+ *      -DRM_RIGHTS_FAILURE, if there is some other error occur.
+ */
+int32_t drm_checkRoAndUpdate(int32_t id, int32_t permission);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __DRM_RIGHTS_MANAGER_H__ */
diff --git a/media/libdrm/mobile1/include/objmng/drm_time.h b/media/libdrm/mobile1/include/objmng/drm_time.h
new file mode 100644
index 0000000..9b013e6
--- /dev/null
+++ b/media/libdrm/mobile1/include/objmng/drm_time.h
@@ -0,0 +1,77 @@
+/*
+ * 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.
+ */
+
+
+/**
+ * @file
+ * Time Porting Layer
+ *
+ * Basic support functions that are needed by time.
+ *
+ * <!-- #interface list begin -->
+ * \section drm_time Interface
+ * - DRM_time_getElapsedSecondsFrom1970()
+ * - DRM_time_sleep()
+ * - DRM_time_getSysTime()
+ * <!-- #interface list end -->
+ */
+
+#ifndef __DRM_TIME_H__
+#define __DRM_TIME_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <time.h>
+#include <drm_common_types.h>
+
+/** the time format */
+typedef struct __db_system_time_
+{
+    uint16_t year;
+    uint16_t month;
+    uint16_t day;
+    uint16_t hour;
+    uint16_t min;
+    uint16_t sec;
+} T_DB_TIME_SysTime;
+
+/**
+ * Get the system time.it's up to UTC
+ * \return Return the time in elapsed seconds.
+ */
+uint32_t DRM_time_getElapsedSecondsFrom1970(void);
+
+/**
+ * Suspend the execution of the current thread for a specified interval
+ * \param ms suspended time by millisecond
+ */
+void DRM_time_sleep(uint32_t ms);
+
+/**
+ * function: get current system time
+ * \param  time_ptr[OUT]  the system time got
+ * \attention
+ *    time_ptr must not be NULL
+ */
+void DRM_time_getSysTime(T_DB_TIME_SysTime *time_ptr);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __DRM_TIME_H__ */
diff --git a/media/libdrm/mobile1/include/objmng/svc_drm.h b/media/libdrm/mobile1/include/objmng/svc_drm.h
new file mode 100644
index 0000000..789343f
--- /dev/null
+++ b/media/libdrm/mobile1/include/objmng/svc_drm.h
@@ -0,0 +1,376 @@
+/*
+ * 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 __SVC_DRM_NEW_H__
+#define __SVC_DRM_NEW_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <drm_common_types.h>
+
+/**
+ * Define the mime type of DRM data.
+ */
+#define TYPE_DRM_MESSAGE            0x48    /**< The mime type is "application/vnd.oma.drm.message" */
+#define TYPE_DRM_CONTENT            0x49    /**< The mime type is "application/vnd.oma.drm.content" */
+#define TYPE_DRM_RIGHTS_XML         0x4a    /**< The mime type is "application/vnd.oma.drm.rights+xml" */
+#define TYPE_DRM_RIGHTS_WBXML       0x4b    /**< The mime type is "application/vnd.oma.drm.rights+wbxml" */
+#define TYPE_DRM_UNKNOWN            0xff    /**< The mime type is unknown */
+
+/**
+ * Define the delivery methods.
+ */
+#define FORWARD_LOCK                1       /**< Forward_lock */
+#define COMBINED_DELIVERY           2       /**< Combined delivery */
+#define SEPARATE_DELIVERY           3       /**< Separate delivery */
+#define SEPARATE_DELIVERY_FL        4       /**< Separate delivery but DCF is forward-lock */
+
+/**
+ * Define the permissions.
+ */
+#define DRM_PERMISSION_PLAY         0x01    /**< Play */
+#define DRM_PERMISSION_DISPLAY      0x02    /**< Display */
+#define DRM_PERMISSION_EXECUTE      0x04    /**< Execute */
+#define DRM_PERMISSION_PRINT        0x08    /**< Print */
+#define DRM_PERMISSION_FORWARD      0x10    /**< Forward */
+
+/**
+ * Define the constraints.
+ */
+#define DRM_NO_CONSTRAINT           0x80    /**< Indicate have no constraint, it can use freely */
+#define DRM_END_TIME_CONSTRAINT     0x08    /**< Indicate have end time constraint */
+#define DRM_INTERVAL_CONSTRAINT     0x04    /**< Indicate have interval constraint */
+#define DRM_COUNT_CONSTRAINT        0x02    /**< Indicate have count constraint */
+#define DRM_START_TIME_CONSTRAINT   0x01    /**< Indicate have start time constraint */
+#define DRM_NO_PERMISSION           0x00    /**< Indicate no rights */
+
+/**
+ * Define the return values for those interface.
+ */
+#define DRM_SUCCESS                 0
+#define DRM_FAILURE                 -1
+#define DRM_MEDIA_EOF               -2
+#define DRM_RIGHTS_DATA_INVALID     -3
+#define DRM_MEDIA_DATA_INVALID      -4
+#define DRM_SESSION_NOT_OPENED      -5
+#define DRM_NO_RIGHTS               -6
+#define DRM_NOT_SD_METHOD           -7
+#define DRM_RIGHTS_PENDING          -8
+#define DRM_RIGHTS_EXPIRED          -9
+#define DRM_UNKNOWN_DATA_LEN        -10
+
+/**
+ * The input DRM data structure, include DM, DCF, DR, DRC.
+ */
+typedef struct _T_DRM_Input_Data {
+    /**
+     * The handle of the input DRM data.
+     */
+    int32_t inputHandle;
+
+    /**
+     * The mime type of the DRM data, if the mime type set to unknown, DRM engine
+     * will try to scan the input data to confirm the mime type, but we must say that
+     * the scan and check of mime type is not strictly precise.
+     */
+    int32_t mimeType;
+
+    /**
+     * The function to get input data length, this function should be implement by out module,
+     * and DRM engine will call-back it.
+     *
+     * \param inputHandle   The handle of the DRM data.
+     *
+     * \return
+     *      -A positive integer indicate the length of input data.
+     *      -0, if some error occurred.
+     */
+    int32_t (*getInputDataLength)(int32_t inputHandle);
+
+    /**
+     * The function to read the input data, this function should be implement by out module,
+     * and DRM engine will call-back it.
+     *
+     * \param inputHandle   The handle of the DRM data.
+     * \param buf       The buffer mallocced by DRM engine to save the data.
+     * \param bufLen    The length of the buffer.
+     *
+     * \return
+     *      -A positive integer indicate the actually length of byte has been read.
+     *      -0, if some error occurred.
+     *      -(-1), if reach to the end of the data.
+     */
+    int32_t (*readInputData)(int32_t inputHandle, uint8_t* buf, int32_t bufLen);
+
+    /**
+     * The function to seek the current file pointer, this function should be implement by out module,
+     * and DRM engine will call-back it.
+     *
+     * \param inputHandle   The handle of the DRM data.
+     * \param offset    The offset from the start position to be seek.
+     *
+     * \return
+     *      -0, if seek operation success.
+     *      -(-1), if seek operation fail.
+     */
+    int32_t (*seekInputData)(int32_t inputHandle, int32_t offset);
+} T_DRM_Input_Data;
+
+/**
+ * The constraint structure.
+ */
+typedef struct _T_DRM_Constraint_Info {
+    uint8_t indicator;          /**< Whether there is a right */
+    uint8_t unUsed[3];
+    int32_t count;              /**< The constraint of count */
+    int32_t startDate;          /**< The constraint of start date */
+    int32_t startTime;          /**< The constraint of start time */
+    int32_t endDate;            /**< The constraint of end date */
+    int32_t endTime;            /**< The constraint of end time */
+    int32_t intervalDate;       /**< The constraint of interval date */
+    int32_t intervalTime;       /**< The constraint of interval time */
+} T_DRM_Constraint_Info;
+
+/**
+ * The rights permission and constraint information structure.
+ */
+typedef struct _T_DRM_Rights_Info {
+    uint8_t roId[256];                     /**< The unique id for a specially rights object */
+    T_DRM_Constraint_Info playRights;       /**< Constraint of play */
+    T_DRM_Constraint_Info displayRights;    /**< Constraint of display */
+    T_DRM_Constraint_Info executeRights;    /**< Constraint of execute */
+    T_DRM_Constraint_Info printRights;      /**< Constraint of print */
+} T_DRM_Rights_Info;
+
+/**
+ * The list node of the Rights information structure.
+ */
+typedef struct _T_DRM_Rights_Info_Node {
+    T_DRM_Rights_Info roInfo;
+    struct _T_DRM_Rights_Info_Node *next;
+} T_DRM_Rights_Info_Node;
+
+/**
+ * Install a rights object to DRM engine, include the rights in Combined Delivery cases.
+ * Because all the rights object is managed by DRM engine, so every incoming rights object
+ * must be install to the engine first, or the DRM engine will not recognize it.
+ *
+ * \param data      The rights object data or Combined Delivery case data.
+ * \param pRightsInfo   The structure to save this rights information.
+ *
+ * \return
+ *      -DRM_SUCCESS, when install successfully.
+ *      -DRM_RIGHTS_DATA_INVALID, when the input rights data is invalid.
+ *      -DRM_FAILURE, when some other error occur.
+ */
+int32_t SVC_drm_installRights(T_DRM_Input_Data data, T_DRM_Rights_Info* pRightsInfo);
+
+/**
+ * Open a session for a special DRM object, it will parse the input DRM data, and then user
+ * can try to get information for this DRM object, or try to use it if the rights is valid.
+ *
+ * \param data      The DRM object data, DM or DCF.
+ *
+ * \return
+ *      -A handle for this opened DRM object session.
+ *      -DRM_MEDIA_DATA_INVALID, when the input DRM object data is invalid.
+ *      -DRM_FAILURE, when some other error occurred.
+ */
+int32_t SVC_drm_openSession(T_DRM_Input_Data data);
+
+/**
+ * Get the delivery method of the DRM object.
+ *
+ * \param session   The handle for this DRM object session.
+ *
+ * \return
+ *      -The delivery method of this DRM object, include: FORWARD_LOCK, COMBINED_DELIVERY, SEPARATE_DELIVERY, SEPARATE_DELIVERY_FL.
+ *      -DRM_FAILURE, when some other error occurred.
+ */
+int32_t SVC_drm_getDeliveryMethod(int32_t session);
+
+/**
+ * Get DRM object media object content type.
+ *
+ * \param session   The handle for this DRM object session.
+ * \param mediaType The buffer to save the media type string, 64 bytes is enough.
+ *
+ * \return
+ *      -DRM_SUCCESS, when get the media object content type successfully.
+ *      -DRM_SESSION_NOT_OPENED, when the session is not opened or has been closed.
+ *      -DRM_FAILURE, when some other error occured.
+ */
+int32_t SVC_drm_getContentType(int32_t session, uint8_t* mediaType);
+
+/**
+ * Check whether a specific DRM object has the specific permission rights or not.
+ *
+ * \param session   The handle for this DRM object session.
+ * \param permission    Specify the permission to be checked.
+ *
+ * \return
+ *      -DRM_SUCCESS, when it has the rights for the permission.
+ *      -DRM_SESSION_NOT_OPENED, when the session is not opened or has been closed.
+ *      -DRM_NO_RIGHTS, when it has no rights.
+ *      -DRM_RIGHTS_PENDING, when it has the rights, but currently it is pending.
+ *      -DRM_RIGHTS_EXPIRED, when the rights has expired.
+ *      -DRM_FAILURE, when some other error occured.
+ */
+int32_t SVC_drm_checkRights(int32_t session, int32_t permission);
+
+/**
+ * Consume the rights when try to use the DRM object.
+ *
+ * \param session   The handle for this DRM object session.
+ * \param permission    Specify the permission to be checked.
+ *
+ * \return
+ *      -DRM_SUCCESS, when consume rights successfully.
+ *      -DRM_SESSION_NOT_OPENED, when the session is not opened or has been closed.
+ *      -DRM_NO_RIGHTS, when it has no rights.
+ *      -DRM_RIGHTS_PENDING, when it has the rights, but currently it is pending.
+ *      -DRM_RIGHTS_EXPIRED, when the rights has expired.
+ *      -DRM_FAILURE, when some other error occured.
+ */
+int32_t SVC_drm_consumeRights(int32_t session, int32_t permission);
+
+/**
+ * Get DRM media object content data length.
+ *
+ * \param session   The handle for this DRM object session.
+ *
+ * \return
+ *      -A positive integer indicate the length of the media object content data.
+ *      -DRM_SESSION_NOT_OPENED, when the session is not opened or has been closed.
+ *      -DRM_NO_RIGHTS, when the rights object is not existed.
+ *      -DRM_UNKNOWN_DATA_LEN, when DRM object media data length is unknown in case of DCF has no rights.
+ *      -DRM_FAILURE, when some other error occured.
+ */
+int32_t SVC_drm_getContentLength(int32_t session);
+
+/**
+ * Get DRM media object content data. Support get the data piece by piece if the content is too large.
+ *
+ * \param session   The handle for this DRM object session.
+ * \param offset    The offset to start to get content.
+ * \param mediaBuf  The buffer to save media object data.
+ * \param mediaBufLen   The length of the buffer.
+ *
+ * \return
+ *      -A positive integer indicate the actually length of the data has been got.
+ *      -DRM_SESSION_NOT_OPENED, when the session is not opened or has been closed.
+ *      -DRM_NO_RIGHTS, when the rights object is not existed.
+ *      -DRM_MEDIA_EOF, when reach to the end of the media data.
+ *      -DRM_FAILURE, when some other error occured.
+ */
+int32_t SVC_drm_getContent(int32_t session, int32_t offset, uint8_t* mediaBuf, int32_t mediaBufLen);
+
+/**
+ * Get the rights issuer address, this interface is specially for Separate Delivery method.
+ *
+ * \param session   The handle for this DRM object session.
+ * \param rightsIssuer  The buffer to save rights issuer, 256 bytes are enough.
+ *
+ * \return
+ *      -DRM_SUCCESS, when get the rights issuer successfully.
+ *      -DRM_SESSION_NOT_OPENED, when the session is not opened or has been closed.
+ *      -DRM_NOT_SD_METHOD, when it is not a Separate Delivery DRM object.
+ *      -DRM_FAILURE, when some other error occured.
+ */
+int32_t SVC_drm_getRightsIssuer(int32_t session, uint8_t* rightsIssuer);
+
+/**
+ * Get DRM object constraint informations.
+ *
+ * \param session   The handle for this DRM object session.
+ * \param rights    The structue to save the rights object information.
+ *
+ * \return
+ *      -DRM_SUCCESS, when get the rights information successfully.
+ *      -DRM_SESSION_NOT_OPENED, when the session is not opened or has been closed.
+ *      -DRM_NO_RIGHTS, when this DRM object has not rights.
+ *      -DRM_FAILURE, when some other error occured.
+ */
+int32_t SVC_drm_getRightsInfo(int32_t session, T_DRM_Rights_Info* rights);
+
+/**
+ * Close the opened session, after closed, the handle become invalid.
+ *
+ * \param session   The handle for this DRM object session.
+ *
+ * \return
+ *      -DRM_SUCCESS, when close operation success.
+ *      -DRM_SESSION_NOT_OPENED, when the session is not opened or has been closed.
+ *      -DRM_FAILURE, when some other error occured.
+ */
+int32_t SVC_drm_closeSession(int32_t session);
+
+/**
+ * Check and update the given rights according the given permission.
+ *
+ * \param contentID The unique id of the rights object.
+ * \param permission    The permission to be updated.
+ *
+ * \return
+ *      -DRM_SUCCESS, when update operation success.
+ *      -DRM_NO_RIGHTS, when it has no rights.
+ *      -DRM_RIGHTS_PENDING, when it has the rights, but currently it is pending.
+ *      -DRM_RIGHTS_EXPIRED, when the rights has expired.
+ *      -DRM_FAILURE, when some other error occured.
+ */
+int32_t SVC_drm_updateRights(uint8_t* contentID, int32_t permission);
+
+/**
+ * Scan all the rights object in current DRM engine, and get all their information.
+ *
+ * \param ppRightsInfo  The pointer to the list structure to save rights info.
+ *
+ * \return
+ *      -DRM_SUCCESS, when get information successfully.
+ *      -DRM_FAILURE, when some other error occured.
+ */
+int32_t SVC_drm_viewAllRights(T_DRM_Rights_Info_Node **ppRightsInfo);
+
+/**
+ * Free the allocated memory when call "SVC_drm_viewAllRights".
+ *
+ * \param pRightsHeader The header pointer of the list to be free.
+ *
+ * \return
+ *      -DRM_SUCCESS, when free operation successfully.
+ *      -DRM_FAILURE, when some other error occured.
+ */
+int32_t SVC_drm_freeRightsInfoList(T_DRM_Rights_Info_Node *pRightsHeader);
+
+/**
+ * Delete a specify rights.
+ *
+ * \param roId      The unique id of the rights.
+ *
+ * \return
+ *      -DRM_SUCCESS, when free operation successfully.
+ *      -DRM_NO_RIGHTS, when there is not this rights object.
+ *      -DRM_FAILURE, when some other error occured.
+ */
+int32_t SVC_drm_deleteRights(uint8_t* roId);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __SVC_DRM_NEW_H__ */
diff --git a/media/libdrm/mobile1/include/parser/parser_dcf.h b/media/libdrm/mobile1/include/parser/parser_dcf.h
new file mode 100644
index 0000000..c63a195
--- /dev/null
+++ b/media/libdrm/mobile1/include/parser/parser_dcf.h
@@ -0,0 +1,91 @@
+/*
+ * 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 __PARSER_DCF_H__
+#define __PARSER_DCF_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <drm_common_types.h>
+
+#define MAX_ENCRYPTION_METHOD_LEN                            64
+#define MAX_RIGHTS_ISSUER_LEN                                256
+#define MAX_CONTENT_NAME_LEN                                 64
+#define MAX_CONTENT_DESCRIPTION_LEN                          256
+#define MAX_CONTENT_VENDOR_LEN                               256
+#define MAX_ICON_URI_LEN                                     256
+#define MAX_CONTENT_TYPE_LEN                                 64
+#define MAX_CONTENT_URI_LEN                                  256
+
+#define HEADER_ENCRYPTION_METHOD                             "Encryption-Method: "
+#define HEADER_RIGHTS_ISSUER                                 "Rights-Issuer: "
+#define HEADER_CONTENT_NAME                                  "Content-Name: "
+#define HEADER_CONTENT_DESCRIPTION                           "Content-Description: "
+#define HEADER_CONTENT_VENDOR                                "Content-Vendor: "
+#define HEADER_ICON_URI                                      "Icon-Uri: "
+
+#define HEADER_ENCRYPTION_METHOD_LEN                         19
+#define HEADER_RIGHTS_ISSUER_LEN                             15
+#define HEADER_CONTENT_NAME_LEN                              14
+#define HEADER_CONTENT_DESCRIPTION_LEN                       21
+#define HEADER_CONTENT_VENDOR_LEN                            16
+#define HEADER_ICON_URI_LEN                                  10
+
+#define UINT_VAR_FLAG                                        0x80
+#define UINT_VAR_DATA                                        0x7F
+#define MAX_UINT_VAR_BYTE                                    5
+#define DRM_UINT_VAR_ERR                                     -1
+
+typedef struct _T_DRM_DCF_Info {
+    uint8_t Version;
+    uint8_t ContentTypeLen;                                  /**< Length of the ContentType field */
+    uint8_t ContentURILen;                                   /**< Length of the ContentURI field */
+    uint8_t unUsed;
+    uint8_t ContentType[MAX_CONTENT_TYPE_LEN];               /**< The MIME media type of the plaintext data */
+    uint8_t ContentURI[MAX_CONTENT_URI_LEN];                 /**< The unique identifier of this content object */
+    int32_t HeadersLen;                                      /**< Length of the Headers field */
+    int32_t EncryptedDataLen;                                /**< Length of the encrypted data field */
+    int32_t DecryptedDataLen;                                /**< Length of the decrypted data field */
+    uint8_t Encryption_Method[MAX_ENCRYPTION_METHOD_LEN];    /**< Encryption method */
+    uint8_t Rights_Issuer[MAX_RIGHTS_ISSUER_LEN];            /**< Rights issuer */
+    uint8_t Content_Name[MAX_CONTENT_NAME_LEN];              /**< Content name */
+    uint8_t ContentDescription[MAX_CONTENT_DESCRIPTION_LEN]; /**< Content description */
+    uint8_t ContentVendor[MAX_CONTENT_VENDOR_LEN];           /**< Content vendor */
+    uint8_t Icon_URI[MAX_ICON_URI_LEN];                      /**< Icon URI */
+} T_DRM_DCF_Info;
+
+/**
+ * Parse the DRM content format data
+ *
+ * \param buffer            (in)Input the DCF format data
+ * \param bufferLen         (in)The input buffer length
+ * \param pDcfInfo          (out)A structure pointer which contain information of DCF headers
+ * \param ppEncryptedData   (out)The location of encrypted data
+ *
+ * \return
+ *      -TRUE, when success
+ *      -FALSE, when failed
+ */
+int32_t drm_dcfParser(uint8_t *buffer, int32_t bufferLen, T_DRM_DCF_Info *pDcfInfo,
+                      uint8_t **ppEncryptedData);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __PARSER_DCF_H__ */
diff --git a/media/libdrm/mobile1/include/parser/parser_dm.h b/media/libdrm/mobile1/include/parser/parser_dm.h
new file mode 100644
index 0000000..ec8b6b2
--- /dev/null
+++ b/media/libdrm/mobile1/include/parser/parser_dm.h
@@ -0,0 +1,101 @@
+/*
+ * 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 __PARSER_DM_H__
+#define __PARSER_DM_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <drm_common_types.h>
+
+#define MAX_CONTENT_TYPE_LEN                                64
+#define MAX_CONTENT_ID                                      256
+#define MAX_CONTENT_BOUNDARY_LEN                            256
+#define MAX_RIGHTS_ISSUER_LEN                               256
+
+#define DRM_MIME_TYPE_RIGHTS_XML                            "application/vnd.oma.drm.rights+xml"
+#define DRM_MIME_TYPE_CONTENT                               "application/vnd.oma.drm.content"
+
+#define HEADERS_TRANSFER_CODING                             "Content-Transfer-Encoding:"
+#define HEADERS_CONTENT_TYPE                                "Content-Type:"
+#define HEADERS_CONTENT_ID                                  "Content-ID:"
+
+#define TRANSFER_CODING_TYPE_7BIT                           "7bit"
+#define TRANSFER_CODING_TYPE_8BIT                           "8bit"
+#define TRANSFER_CODING_TYPE_BINARY                         "binary"
+#define TRANSFER_CODING_TYPE_BASE64                         "base64"
+
+#define DRM_UID_TYPE_FORWORD_LOCK                           "forwardlock"
+#define DRM_NEW_LINE_CRLF                                   "\r\n"
+
+#define HEADERS_TRANSFER_CODING_LEN                         26
+#define HEADERS_CONTENT_TYPE_LEN                            13
+#define HEADERS_CONTENT_ID_LEN                              11
+
+#define DRM_MESSAGE_CODING_7BIT                             0  /* default */
+#define DRM_MESSAGE_CODING_8BIT                             1
+#define DRM_MESSAGE_CODING_BINARY                           2
+#define DRM_MESSAGE_CODING_BASE64                           3
+
+#define DRM_B64_DEC_BLOCK                                   3
+#define DRM_B64_ENC_BLOCK                                   4
+
+typedef struct _T_DRM_DM_Info {
+    uint8_t contentType[MAX_CONTENT_TYPE_LEN];  /**< Content type */
+    uint8_t contentID[MAX_CONTENT_ID];          /**< Content ID */
+    uint8_t boundary[MAX_CONTENT_BOUNDARY_LEN]; /**< DRM message's boundary */
+    uint8_t deliveryType;                       /**< The Delivery type */
+    uint8_t transferEncoding;                   /**< Transfer encoding type */
+    int32_t contentOffset;                      /**< The offset of the media content from the original DRM data */
+    int32_t contentLen;                         /**< The length of the media content */
+    int32_t rightsOffset;                       /**< The offset of the rights object in case of combined delivery */
+    int32_t rightsLen;                          /**< The length of the rights object in case of combined delivery */
+    uint8_t rightsIssuer[MAX_RIGHTS_ISSUER_LEN];/**< The rights issuer address in case of separate delivery */
+} T_DRM_DM_Info;
+
+/**
+ * Search the string in a limited length.
+ *
+ * \param str           The original string
+ * \param strSearch     The sub-string to be searched
+ * \param len           The length limited
+ *
+ * \return
+ *      -NULL, when there is not the searched string in length
+ *      -The pointer of this sub-string
+ */
+const uint8_t* drm_strnstr(const uint8_t* str, const uint8_t* strSearch, int32_t len);
+
+/**
+ * Parse the DRM message format data.
+ *
+ * \param buffer        (in)Input the DRM message format data
+ * \param bufferLen     (in)The input buffer length
+ * \param pDmInfo       (out)A structure pointer which contain information of DRM message headers
+ *
+ * \return
+ *      -TRUE, when success
+ *      -FALSE, when failed
+ */
+int32_t drm_parseDM(const uint8_t* buffer, int32_t bufferLen, T_DRM_DM_Info* pDmInfo);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __PARSER_DM_H__ */
diff --git a/media/libdrm/mobile1/include/parser/parser_rel.h b/media/libdrm/mobile1/include/parser/parser_rel.h
new file mode 100644
index 0000000..8def199
--- /dev/null
+++ b/media/libdrm/mobile1/include/parser/parser_rel.h
@@ -0,0 +1,123 @@
+/*
+ * 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 __PARSER_REL_H__
+#define __PARSER_REL_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <drm_common_types.h>
+
+#define WRITE_RO_FLAG(whoIsAble, boolValue, Indicator, RIGHTS) do{\
+    whoIsAble = boolValue;\
+    Indicator |= RIGHTS;\
+}while(0)
+
+#define CHECK_VALIDITY(ret) do{\
+    if(ret == NULL){\
+        if(XML_ERROR_NO_SUCH_NODE != xml_errno)\
+            return FALSE;\
+    }\
+    else\
+    {\
+        if(XML_ERROR_OK != xml_errno)\
+            return FALSE;\
+    }\
+}while(0)
+
+#define YMD_HMS_2_INT(year, mon, day, date, hour, min, sec, time) do{\
+    date = year * 10000 + mon * 100 + day;\
+    time = hour * 10000 + min * 100 + sec;\
+}while(0)
+
+#define DRM_UID_LEN         256
+#define DRM_KEY_LEN         16
+
+#define XML_DOM_PARSER
+
+typedef struct _T_DRM_DATETIME {
+    int32_t date; /**< year * 10000 + mon *100 + day */
+    int32_t time; /**< hour * 10000 + min *100 + sec */
+} T_DRM_DATETIME;
+
+typedef struct _T_DRM_Rights_Constraint {
+    uint8_t Indicator;          /**< Indicate which is constrainted, the first one indicate 0001, second one indicate 0010 */
+    uint8_t unUsed[3];
+    int32_t Count;              /**< The times that can be used */
+    T_DRM_DATETIME StartTime;   /**< The starting time */
+    T_DRM_DATETIME EndTime;     /**< The ending time */
+    T_DRM_DATETIME Interval;    /**< The interval time */
+} T_DRM_Rights_Constraint;
+
+typedef struct _T_DRM_Rights {
+    uint8_t Version[8];                         /**< Version number */
+    uint8_t uid[256];                           /**< record the rights object name */
+    uint8_t KeyValue[16];                       /**< Decode base64 */
+    int32_t bIsPlayable;                        /**< Is playable */
+    int32_t bIsDisplayable;                     /**< Is displayable */
+    int32_t bIsExecuteable;                     /**< Is executeable */
+    int32_t bIsPrintable;                       /**< Is printable */
+    T_DRM_Rights_Constraint PlayConstraint;     /**< Play constraint */
+    T_DRM_Rights_Constraint DisplayConstraint;  /**< Display constraint */
+    T_DRM_Rights_Constraint ExecuteConstraint;  /**< Execute constraint */
+    T_DRM_Rights_Constraint PrintConstraint;    /**< Print constraint */
+} T_DRM_Rights;
+
+/**
+ * Input year and month, return how many days that month have
+ * \param year          (in)Input the year
+ * \param month         (in)Input the month
+ * \return
+ *      -A positive integer, which is how many days that month have
+ *      -When wrong input, return -1
+ */
+int32_t drm_monthDays(int32_t year, int32_t month);
+
+/**
+ * Check whether the date and time is valid.
+ * \param year          year of the date
+ * \param month         month of the date
+ * \param day           day of the date
+ * \param hour          hour of the time
+ * \param min           minute of the time
+ * \param sec           second of the time
+ * \return
+ *      -when it is a valid time, return 0
+ *      -when it is a invalid time, return -1
+ */
+int32_t drm_checkDate(int32_t year, int32_t month, int32_t day, int32_t hour, int32_t min, int32_t sec);
+
+/**
+ * Parse the rights object include xml format and wbxml format data
+ *
+ * \param buffer        (in)Input the DRM rights object data
+ * \param bufferLen     (in)The buffer length
+ * \param format        (in)Which format, xml or wbxml
+ * \param pRights       (out)A structure pointer which save the rights information
+ *
+ * \return
+ *      -TRUE, when success
+ *      -FALSE, when failed
+ */
+int32_t drm_relParser(uint8_t* buffer, int32_t bufferLen, int32_t Format, T_DRM_Rights* pRights);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __PARSER_REL_H__ */
diff --git a/media/libdrm/mobile1/include/xml/wbxml_tinyparser.h b/media/libdrm/mobile1/include/xml/wbxml_tinyparser.h
new file mode 100644
index 0000000..1c40467
--- /dev/null
+++ b/media/libdrm/mobile1/include/xml/wbxml_tinyparser.h
@@ -0,0 +1,52 @@
+/*
+ * 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 __WBXML_TINYPARSER_H__
+#define __WBXML_TINYPARSER_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <drm_common_types.h>
+
+#define REL_TAG_RIGHTS                                       0x05
+#define REL_TAG_CONTEXT                                      0x06
+#define REL_TAG_VERSION                                      0x07
+#define REL_TAG_UID                                          0x08
+#define REL_TAG_AGREEMENT                                    0x09
+#define REL_TAG_ASSET                                        0x0A
+#define REL_TAG_KEYINFO                                      0x0B
+#define REL_TAG_KEYVALUE                                     0x0C
+#define REL_TAG_PERMISSION                                   0x0D
+#define REL_TAG_PLAY                                         0x0E
+#define REL_TAG_DISPLAY                                      0x0F
+#define REL_TAG_EXECUTE                                      0x10
+#define REL_TAG_PRINT                                        0x11
+#define REL_TAG_CONSTRAINT                                   0x12
+#define REL_TAG_COUNT                                        0x13
+#define REL_TAG_DATETIME                                     0x14
+#define REL_TAG_START                                        0x15
+#define REL_TAG_END                                          0x16
+#define REL_TAG_INTERVAL                                     0x17
+
+#define REL_CHECK_WBXML_HEADER(x) ((x != NULL) && (x[0] == 0x03) && (x[1] == 0x0E) && (x[2] == 0x6A))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __WBXML_TINYPARSER_H__ */
diff --git a/media/libdrm/mobile1/include/xml/xml_tinyParser.h b/media/libdrm/mobile1/include/xml/xml_tinyParser.h
new file mode 100644
index 0000000..4ad65b8
--- /dev/null
+++ b/media/libdrm/mobile1/include/xml/xml_tinyParser.h
@@ -0,0 +1,171 @@
+/*
+ * 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 __XML_TINYPARSER_H__
+#define __XML_TINYPARSER_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <drm_common_types.h>
+
+#define XML_DOM_PARSER
+#define WBXML_DOM_PARSER
+#define XML_DOM_CHECK_ENDTAG
+#define XML_ENABLE_ERRNO
+#define WBXML_OLD_VERSION /* for drm only */
+
+#ifdef DEBUG_MODE
+void XML_PrintMallocInfo();
+#endif /* DEBUG_MODE */
+
+#define XML_TRUE                                             1
+#define XML_FALSE                                            0
+#define XML_EOF                                              0
+#define XML_TAG_START                                        0
+#define XML_TAG_END                                          1
+#define XML_TAG_SELF                                         2
+
+#define XML_MAX_PROPERTY_LEN                                 256
+#define XML_MAX_ATTR_NAME_LEN                                256
+#define XML_MAX_ATTR_VALUE_LEN                               256
+#define XML_MAX_VALUE_LEN                                    256
+
+#define XML_ERROR_OK                                         0
+#define XML_ERROR_BUFFER_NULL                                -1
+#define XML_ERROR_ATTR_NAME                                  -2
+#define XML_ERROR_ATTR_MISSED_EQUAL                          -3
+#define XML_ERROR_PROPERTY_NAME                              -4
+#define XML_ERROR_ATTR_VALUE                                 -5
+#define XML_ERROR_ENDTAG                                     -6
+#define XML_ERROR_NO_SUCH_NODE                               -7
+#define XML_ERROR_PROPERTY_END                               -8
+#define XML_ERROR_VALUE                                      -9
+#define XML_ERROR_NO_START_TAG                               -14
+#define XML_ERROR_NOVALUE                                    -15
+
+#define WBXML_ERROR_MISSED_CONTENT                           -10
+#define WBXML_ERROR_MBUINT32                                 -11
+#define WBXML_ERROR_MISSED_STARTTAG                          -12
+#define WBXML_ERROR_MISSED_ENDTAG                            -13
+
+#ifdef XML_ENABLE_ERRNO
+extern int32_t xml_errno;
+#define XML_ERROR(x) do { xml_errno = x; } while (0)
+#else  /* XML_ENABLE_ERRNO */
+#define XML_ERROR
+#endif /* XML_ENABLE_ERRNO */
+
+#ifdef XML_DOM_PARSER
+uint8_t *XML_DOM_getNode(uint8_t *buffer, const uint8_t *const node);
+uint8_t *XML_DOM_getNodeValue(uint8_t *buffer, uint8_t *node,
+                           uint8_t **value, int32_t *valueLen);
+
+uint8_t *XML_DOM_getValue(uint8_t *buffer, uint8_t **pValue, int32_t *valueLen);
+uint8_t *XML_DOM_getAttr(uint8_t *buffer, uint8_t **pName, int32_t *nameLen,
+                      uint8_t **pValue, int32_t *valueLen);
+
+uint8_t *XML_DOM_getNextNode(uint8_t *buffer, uint8_t **pNodeName,
+                          int32_t *nodenameLen);
+
+uint8_t *XML_DOM_getTag(uint8_t *buffer, int32_t *tagLen, int32_t *tagType);
+#endif /* XML_DOM_PARSER */
+
+#ifdef WBXML_DOM_PARSER
+
+#define WBXML_WITH_ATTR                                      0x80
+#define WBXML_WITH_CONTENT                                   0x40
+#define WBXML_ATTR_END                                       0x01
+#define WBXML_CONTENT_END                                    0x01
+
+#define WBXML_SWITCH_PAGE                                    0x00
+#define WBXML_STR_I                                          0x03
+#define WBXML_END                                            0x00
+#define WBXML_OPAUE                                          0xC3
+#define WBXML_STR_T                                          0x83
+#define WBXML_OPAQUE                                         0xC3
+
+#define WBXML_GET_TAG(x) ((x) & 0x3F) /* get 6-digits */
+#define WBXML_HAS_ATTR(x) ((x) & WBXML_WITH_ATTR)
+#define WBXML_HAS_CONTENT(x) ((x) & WBXML_WITH_CONTENT)
+
+typedef struct _WBXML {
+    uint8_t version;
+    uint8_t unUsed[3];
+    uint32_t publicid;
+    uint32_t charset;
+    int32_t strTableLen;
+    uint8_t *strTable;
+    uint8_t *Content;
+    uint8_t *End;
+    uint8_t *curPtr;
+    int32_t depth;
+} WBXML;
+
+typedef int32_t XML_BOOL;
+
+#ifdef WBXML_OLD_VERSION
+uint8_t *WBXML_DOM_getNode(uint8_t *buffer, int32_t bufferLen,
+                                 uint8_t *node);
+uint8_t *WBXML_DOM_getNodeValue(uint8_t *buffer, int32_t bufferLen,
+                                      uint8_t *node,
+                                      uint8_t **value,
+                                      int32_t *valueLen);
+#endif /* WBXML_OLD_VERSION */
+
+XML_BOOL WBXML_DOM_Init(WBXML * pWbxml, uint8_t *buffer,
+                        int32_t bufferLen);
+XML_BOOL WBXML_DOM_Eof(WBXML * pWbxml);
+uint8_t WBXML_DOM_GetTag(WBXML * pWbxml);
+uint8_t WBXML_DOM_GetChar(WBXML * pWbxml);
+uint8_t WBXML_DOM_GetUIntVar(WBXML * pWbxml);
+void WBXML_DOM_Rewind(WBXML * pWbxml);
+void WBXML_DOM_Seek(WBXML * pWbxml, int32_t offset);
+int32_t WBXML_GetUintVar(const uint8_t *const buffer, int32_t *len);
+
+#endif /* WBXML_DOM_PARSER */
+
+#ifdef XML_TREE_STRUCTURE
+
+typedef struct _XML_TREE_ATTR XML_TREE_ATTR;
+struct _XML_TREE_ATTR {
+    uint8_t name[XML_MAX_ATTR_VALUE_LEN];
+    uint8_t value[XML_MAX_ATTR_VALUE_LEN];
+    XML_TREE_ATTR *next;
+};
+
+typedef struct _XML_TREE XML_TREE;
+struct _XML_TREE {
+    uint8_t tag[XML_MAX_PROPERTY_LEN];
+    uint8_t value[XML_MAX_VALUE_LEN];
+    XML_TREE_ATTR *attr;
+    XML_TREE_ATTR *last_attr;
+    XML_TREE *brother;
+    XML_TREE *last_brother;
+    XML_TREE *child;
+};
+
+XML_TREE *XML_makeTree(uint8_t **buf);
+void XML_freeTree(XML_TREE * pTree);
+
+#endif /* XML_TREE_STRUCTURE */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __XML_TINYPARSER_H__ */
diff --git a/media/libdrm/mobile1/src/jni/drm1_jni.c b/media/libdrm/mobile1/src/jni/drm1_jni.c
new file mode 100644
index 0000000..79ce931
--- /dev/null
+++ b/media/libdrm/mobile1/src/jni/drm1_jni.c
@@ -0,0 +1,1175 @@
+/*
+ * 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.
+ */
+
+/**
+ * @file drm1_jni.c
+ *
+ * This file implement the Java Native Interface
+ * for supporting OMA DRM 1.0
+ */
+
+#include <jni/drm1_jni.h>
+#include <objmng/svc_drm.h>
+#include "log.h"
+
+
+#define MS_PER_SECOND 1000                  /* Milliseconds per second */
+#define MS_PER_MINUTE 60 * MS_PER_SECOND    /* Milliseconds per minute */
+#define MS_PER_HOUR   60 * MS_PER_MINUTE    /* Milliseconds per hour */
+#define MS_PER_DAY    24 * MS_PER_HOUR      /* Milliseconds per day */
+
+#define SECONDS_PER_MINUTE 60                       /* Seconds per minute*/
+#define SECONDS_PER_HOUR   60 * SECONDS_PER_MINUTE  /* Seconds per hour */
+#define SECONDS_PER_DAY    24 * SECONDS_PER_HOUR    /* Seconds per day */
+
+#define DAY_PER_MONTH 30                    /* Days per month */
+#define DAY_PER_YEAR  365                   /* Days per year */
+
+/** Nonzero if 'y' is a leap year, else zero. */
+#define leap(y) (((y) % 4 == 0 && (y) % 100 != 0) || (y) % 400 == 0)
+
+/** Number of leap years from 1970 to 'y' (not including 'y' itself). */
+#define nleap(y) (((y) - 1969) / 4 - ((y) - 1901) / 100 + ((y) - 1601) / 400)
+
+/** Accumulated number of days from 01-Jan up to start of current month. */
+static const int32_t ydays[] = {
+    0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
+};
+
+#define int64_const(s)          (s)
+#define int64_add(dst, s1, s2)  ((void)((dst) = (s1) + (s2)))
+#define int64_mul(dst, s1, s2)  ((void)((dst) = (int64_t)(s1) * (int64_t)(s2)))
+
+/**
+ * DRM data structure
+ */
+typedef struct _DrmData {
+    /**
+     * The id of the DRM content.
+     */
+    int32_t id;
+
+    /**
+     * The pointer of JNI interface.
+     */
+    JNIEnv* env;
+
+    /**
+     * The pointer of DRM raw content InputStream object.
+     */
+    jobject* pInData;
+
+    /**
+     * The len of the InputStream object.
+     */
+    int32_t len;
+
+    /**
+     * The next DRM data.
+     */
+    struct _DrmData *next;
+} DrmData;
+
+/** The table to hold all the DRM data. */
+static DrmData *drmTable = NULL;
+
+/**
+ * Allocate a new item of DrmData.
+ *
+ * \return a pointer to a DrmData item if allocate successfully,
+ *         otherwise return NULL
+ */
+static DrmData * newItem(void)
+{
+    DrmData *d = (DrmData *)malloc(sizeof(DrmData));
+
+    if (d != NULL) {
+        d->id = -1;
+        d->next = NULL;
+    }
+
+    return d;
+}
+
+/**
+ * Free the memory of the specified DrmData item <code>d</code>.
+ *
+ * \param d - a pointer to DrmData
+ */
+static void freeItem(DrmData *d)
+{
+    assert(d != NULL);
+
+    free(d);
+}
+
+/**
+ * Insert a DrmData item with given <code>name</code> into the head of
+ * the DrmData list.
+ *
+ * @param d - the pointer of the JNI interface
+ * @param pInData - the pointer of the DRM content InputStream object.
+ *
+ * @return <code>JNI_DRM_SUCCESS</code> if insert successfully, otherwise
+ *         return <code>JNI_DRM_FAILURE</code>
+ */
+static int32_t addItem(DrmData* d)
+{
+    if (NULL == d)
+        return JNI_DRM_FAILURE;
+
+    if (NULL == drmTable) {
+        drmTable = d;
+        return JNI_DRM_SUCCESS;
+    }
+
+    d->next = drmTable;
+    drmTable = d;
+
+    return JNI_DRM_SUCCESS;
+}
+
+/**
+ * Get the item from the DrmData list by the specified <code>
+ * id</code>.
+ *
+ * @param p - the pointer of the DRM content InputStream object.
+ *
+ * @return a pointer to the DrmData item if find it successfuly,
+ *         otherwise return NULL
+ */
+static DrmData * getItem(int32_t id)
+{
+    DrmData *d;
+
+    if (NULL == drmTable)
+        return NULL;
+
+    for (d = drmTable; d != NULL; d = d->next) {
+        if (id == d->id)
+            return d;
+    }
+
+    return NULL;
+}
+
+/**
+ * Remove the specified DrmData item <code>d</code>.
+ *
+ * @param p - the pointer of the DRM content InputStream object.
+ *
+ * @return <code>JNI_DRM_SUCCESS</code> if remove successfuly,
+ *         otherwise return <code>JNI_DRM_FAILURE</code>
+ */
+static int32_t removeItem(int32_t id)
+{
+    DrmData *curItem, *preItem, *dstItem;
+
+    if (NULL == drmTable)
+        return JNI_DRM_FAILURE;
+
+    preItem = NULL;
+    for (curItem = drmTable; curItem != NULL; curItem = curItem->next) {
+        if (id == curItem->id) {
+            if (curItem == drmTable)
+                drmTable = curItem->next;
+            else
+                preItem->next = curItem->next;
+
+            freeItem(curItem);
+
+            return JNI_DRM_SUCCESS;
+        }
+
+        preItem = curItem;
+    }
+
+    return JNI_DRM_FAILURE;
+}
+
+
+static int32_t getInputStreamDataLength(int32_t handle)
+{
+    JNIEnv* env;
+    jobject* pInputStream;
+    int32_t len;
+    DrmData* p;
+    jclass cls;
+    jmethodID mid;
+
+    p = (DrmData *)handle;
+
+    if (NULL == p)
+        return 0;
+
+    env = p->env;
+    pInputStream = p->pInData;
+    len = p->len;
+
+    if (NULL == env || p->len <= 0 || NULL == pInputStream)
+        return 0;
+
+    /* check the original InputStream is available or not */
+    cls = (*env)->GetObjectClass(env, *pInputStream);
+    mid = (*env)->GetMethodID(env, cls, "available", "()I");
+    (*env)->DeleteLocalRef(env, cls);
+
+    if (NULL == mid)
+        return 0;
+
+    if (0 > (*env)->CallIntMethod(env, *pInputStream, mid))
+        return 0;
+
+    return len;
+}
+
+static int32_t readInputStreamData(int32_t handle, uint8_t* buf, int32_t bufLen)
+{
+    JNIEnv* env;
+    jobject* pInputStream;
+    int32_t len;
+    DrmData* p;
+    jclass cls;
+    jmethodID mid;
+    jbyteArray tmp;
+    int tmpLen;
+    jbyte* pNativeBuf;
+
+    p = (DrmData *)handle;
+
+    if (NULL == p || NULL == buf || bufLen <- 0)
+        return 0;
+
+    env = p->env;
+    pInputStream = p->pInData;
+    len = p->len;
+
+    if (NULL == env || p->len <= 0 || NULL == pInputStream)
+        return 0;
+
+    cls = (*env)->GetObjectClass(env, *pInputStream);
+    mid = (*env)->GetMethodID(env, cls, "read", "([BII)I");
+    tmp = (*env)->NewByteArray(env, bufLen);
+    bufLen = (*env)->CallIntMethod(env, *pInputStream, mid, tmp, 0, bufLen);
+
+    (*env)->DeleteLocalRef(env, cls);
+
+    if (-1 == bufLen)
+        return -1;
+
+    pNativeBuf = (*env)->GetByteArrayElements(env, tmp, NULL);
+    memcpy(buf, pNativeBuf, bufLen);
+    (*env)->ReleaseByteArrayElements(env, tmp, pNativeBuf, 0);
+    (*env)->DeleteLocalRef(env, tmp);
+
+    return bufLen;
+}
+
+static const T_DRM_Rights_Info_Node *searchRightsObject(const jbyte* roId, const T_DRM_Rights_Info_Node* pRightsList)
+{
+    const T_DRM_Rights_Info_Node *pTmp;
+
+    if (NULL == roId || NULL == pRightsList)
+        return NULL;
+
+    pTmp = pRightsList;
+
+    while (NULL != pTmp) {
+        if(0 == strcmp((char *)roId, (char *)pTmp->roInfo.roId))
+            break;
+        pTmp = pTmp->next;
+    }
+
+    return pTmp;
+}
+
+/**
+ * Returns the difference in seconds between the given GMT time
+ * and 1970-01-01 00:00:00 GMT.
+ *
+ * \param year the year (since 1970)
+ * \param month the month (1 - 12)
+ * \param day the day (1 - 31)
+ * \param hour the hour (0 - 23)
+ * \param minute the minute (0 - 59)
+ * \param second the second (0 - 59)
+ *
+ * \return the difference in seconds between the given GMT time
+ *         and 1970-01-01 00:00:00 GMT.
+ */
+static int64_t mkgmtime(
+        uint32_t year, uint32_t month, uint32_t day,
+        uint32_t hour, uint32_t minute, uint32_t second)
+{
+    int64_t result;
+
+    /*
+     * FIXME: It does not check whether the specified days
+     *        is valid based on the specified months.
+     */
+    assert(year >= 1970
+            && month > 0 && month <= 12
+            && day > 0 && day <= 31
+            && hour < 24 && minute < 60
+            && second < 60);
+
+    /* Set 'day' to the number of days into the year. */
+    day += ydays[month - 1] + (month > 2 && leap (year)) - 1;
+
+    /* Now calculate 'day' to the number of days since Jan 1, 1970. */
+    day = day + 365 * (year - 1970) + nleap(year);
+
+    int64_mul(result, int64_const(day), int64_const(SECONDS_PER_DAY));
+    int64_add(result, result, int64_const(
+        SECONDS_PER_HOUR * hour + SECONDS_PER_MINUTE * minute + second));
+
+    return result;
+}
+
+/**
+ * Compute the milliseconds by the specified <code>date</code>
+ * and <code>time</code>.
+ *
+ * @param date - the specified date,
+ *               <code>date = year * 10000 + month * 100 + day</code>
+ * @param time - the specified time,
+ *               <code>time = hour * 10000 + minute * 100 + second</code>
+ *
+ * @return the related milliseconds
+ */
+static int64_t computeTime(int32_t date, int32_t time)
+{
+    int32_t year, month, day, hour, minute, second;
+
+    year = date / 10000;
+    month = (date / 100) % 100;
+    day = date % 100;
+    hour = time / 10000;
+    minute = (time / 100) % 100;
+    second = time % 100;
+
+    /* Adjust the invalid parameters. */
+    if (year < 1970) year = 1970;
+    if (month < 1) month = 1;
+    if (month > 12) month = 12;
+    if (day < 1) day = 1;
+    if (day > 31) day = 31;
+    if (hour < 0) hour = 0;
+    if (hour > 23) hour = 23;
+    if (minute < 0) minute = 0;
+    if (minute > 59) minute = 59;
+    if (second < 0) second = 0;
+    if (second > 59) second = 59;
+
+    return mkgmtime(year, month, day, hour, minute, second) * 1000;
+}
+
+/**
+ * Compute the milliseconds by the specified <code>date</code>
+ * and <code>time</code>.
+ * Note that here we always treat 1 year as 365 days and 1 month as 30 days
+ * that is not precise. But it should not be a problem since OMA DRM 2.0
+ * already restricts the interval representation to be day-based,
+ * i.e. there will not be an interval with year or month any more in the
+ * future.
+ *
+ * @param date - the specified date,
+ *               <code>date = year * 10000 + month * 100 + day</code>
+ * @param time - the specified time,
+ *               <code>time = hour * 10000 + minute * 100 + second</code>
+ *
+ * @return the related milliseconds
+ */
+static int64_t computeInterval(int32_t date, int32_t time)
+{
+    int32_t year, month, day, hour, minute, second;
+    int64_t milliseconds;
+
+    year = date / 10000;
+    month = (date / 100) % 100;
+    day = date % 100;
+    hour = time / 10000;
+    minute = (time / 100) % 100;
+    second = time % 100;
+
+    /* milliseconds = ((((year * 365 + month * 30 + day) * 24
+     *                + hour) * 60 + minute) * 60 + second) * 1000;
+     */
+    int64_mul(milliseconds,
+        int64_const(year * DAY_PER_YEAR + month * DAY_PER_MONTH + day),
+        int64_const(MS_PER_DAY));
+    int64_add(milliseconds, milliseconds,
+        int64_const(hour * MS_PER_HOUR + minute * MS_PER_MINUTE +
+            second * MS_PER_SECOND));
+
+    return milliseconds;
+}
+
+static jint getObjectIntField(JNIEnv * env, jobject obj, const char *name, jint * value)
+{
+    jclass clazz;
+    jfieldID field;
+
+    clazz = (*env)->GetObjectClass(env, obj);
+    if (NULL == clazz)
+        return JNI_DRM_FAILURE;
+
+    field = (*env)->GetFieldID(env, clazz, name, "I");
+    (*env)->DeleteLocalRef(env, clazz);
+
+    if (NULL == field)
+        return JNI_DRM_FAILURE;
+
+    *value = (*env)->GetIntField(env, obj, field);
+
+    return JNI_DRM_SUCCESS;
+}
+
+static jint setObjectIntField(JNIEnv * env, jobject obj, const char *name, jint value)
+{
+    jclass clazz;
+    jfieldID field;
+
+    clazz = (*env)->GetObjectClass(env, obj);
+    if (NULL == clazz)
+        return JNI_DRM_FAILURE;
+
+    field = (*env)->GetFieldID(env, clazz, name, "I");
+    (*env)->DeleteLocalRef(env, clazz);
+
+    if (NULL == field)
+        return JNI_DRM_FAILURE;
+
+    (*env)->SetIntField(env, obj, field, value);
+
+    return JNI_DRM_SUCCESS;
+}
+
+static jint setObjectLongField(JNIEnv * env, jobject obj, const char *name, jlong value)
+{
+    jclass clazz;
+    jfieldID field;
+
+    clazz = (*env)->GetObjectClass(env, obj);
+    if (NULL == clazz)
+        return JNI_DRM_FAILURE;
+
+    field = (*env)->GetFieldID(env, clazz, name, "J");
+    (*env)->DeleteLocalRef(env, clazz);
+
+    if (NULL == field)
+        return JNI_DRM_FAILURE;
+
+    (*env)->SetLongField(env, obj, field, value);
+
+    return JNI_DRM_SUCCESS;
+}
+
+static jint setConstraintFields(JNIEnv * env, jobject constraint, T_DRM_Constraint_Info * pConstraint)
+{
+    /* if no this permission */
+    if (pConstraint->indicator == (uint8_t)DRM_NO_RIGHTS) {
+        if (JNI_DRM_FAILURE == setObjectIntField(env, constraint, "count", 0))
+            return JNI_DRM_FAILURE;
+
+        return JNI_DRM_SUCCESS;
+    }
+
+    /* set count field */
+    if (pConstraint->indicator & DRM_COUNT_CONSTRAINT) {
+        if (JNI_DRM_FAILURE == setObjectIntField(env, constraint, "count", pConstraint->count))
+            return JNI_DRM_FAILURE;
+    }
+
+    /* set start time field */
+    if (pConstraint->indicator & DRM_START_TIME_CONSTRAINT) {
+        int64_t startTime;
+
+        startTime = computeTime(pConstraint->startDate, pConstraint->startTime);
+
+        if (JNI_DRM_FAILURE == setObjectLongField(env, constraint, "startDate", startTime))
+            return JNI_DRM_FAILURE;
+    }
+
+    /* set end time field */
+    if (pConstraint->indicator & DRM_END_TIME_CONSTRAINT) {
+        int64_t endTime;
+
+        endTime = computeTime(pConstraint->endDate, pConstraint->endTime);
+
+        if (JNI_DRM_FAILURE == setObjectLongField(env, constraint, "endDate", endTime))
+            return JNI_DRM_FAILURE;
+    }
+
+    /* set interval field */
+    if (pConstraint->indicator & DRM_INTERVAL_CONSTRAINT) {
+        int64_t interval;
+
+        interval = computeInterval(pConstraint->intervalDate, pConstraint->intervalTime);
+
+        if (JNI_DRM_FAILURE == setObjectLongField(env, constraint, "interval", interval))
+            return JNI_DRM_FAILURE;
+    }
+
+    return JNI_DRM_SUCCESS;
+}
+
+static jint setRightsFields(JNIEnv * env, jobject rights, T_DRM_Rights_Info* pRoInfo)
+{
+    jclass clazz;
+    jfieldID field;
+    jstring str;
+    jint index;
+
+    clazz = (*env)->GetObjectClass(env, rights);
+    if (NULL == clazz)
+        return JNI_DRM_FAILURE;
+
+    /* set roId field */
+    field = (*env)->GetFieldID(env, clazz, "roId", "Ljava/lang/String;");
+    (*env)->DeleteLocalRef(env, clazz);
+
+    if (NULL == field)
+        return JNI_DRM_FAILURE;
+
+    str = (*env)->NewStringUTF(env, (char *)pRoInfo->roId);
+    if (NULL == str)
+        return JNI_DRM_FAILURE;
+
+    (*env)->SetObjectField(env, rights, field, str);
+    (*env)->DeleteLocalRef(env, str);
+
+    return JNI_DRM_SUCCESS;
+}
+
+/* native interface */
+JNIEXPORT jint JNICALL
+Java_android_drm_mobile1_DrmRawContent_nativeConstructDrmContent
+  (JNIEnv * env, jobject rawContent, jobject data, jint len, jint mimeType)
+{
+    int32_t id;
+    T_DRM_Input_Data inData;
+    DrmData* drmInData;
+
+    switch (mimeType) {
+    case JNI_DRM_MIMETYPE_MESSAGE:
+        mimeType = TYPE_DRM_MESSAGE;
+        break;
+    case JNI_DRM_MIMETYPE_CONTENT:
+        mimeType = TYPE_DRM_CONTENT;
+        break;
+    default:
+        return JNI_DRM_FAILURE;
+    }
+
+    drmInData = newItem();
+    if (NULL == drmInData)
+        return JNI_DRM_FAILURE;
+
+    drmInData->env = env;
+    drmInData->pInData = &data;
+    drmInData->len = len;
+
+    if (JNI_DRM_FAILURE == addItem(drmInData))
+        return JNI_DRM_FAILURE;
+
+    inData.inputHandle = (int32_t)drmInData;
+    inData.mimeType = mimeType;
+    inData.getInputDataLength = getInputStreamDataLength;
+    inData.readInputData = readInputStreamData;
+
+    id = SVC_drm_openSession(inData);
+    if (id < 0)
+        return JNI_DRM_FAILURE;
+
+    drmInData->id = id;
+
+    return id;
+}
+
+/* native interface */
+JNIEXPORT jstring JNICALL
+Java_android_drm_mobile1_DrmRawContent_nativeGetRightsAddress
+  (JNIEnv * env, jobject rawContent)
+{
+    jint id;
+    uint8_t rightsIssuer[256] = {0};
+    jstring str = NULL;
+
+    if (JNI_DRM_FAILURE == getObjectIntField(env, rawContent, "id", &id))
+        return NULL;
+
+    if (DRM_SUCCESS == SVC_drm_getRightsIssuer(id, rightsIssuer))
+        str = (*env)->NewStringUTF(env, (char *)rightsIssuer);
+
+    return str;
+}
+
+/* native interface */
+JNIEXPORT jint JNICALL
+Java_android_drm_mobile1_DrmRawContent_nativeGetDeliveryMethod
+  (JNIEnv * env, jobject rawContent)
+{
+    jint id;
+    int32_t res;
+
+    if (JNI_DRM_FAILURE == getObjectIntField(env, rawContent, "id", &id))
+        return JNI_DRM_FAILURE;
+
+    res = SVC_drm_getDeliveryMethod(id);
+
+    switch (res) {
+    case FORWARD_LOCK:
+        return JNI_DRM_FORWARD_LOCK;
+    case COMBINED_DELIVERY:
+        return JNI_DRM_COMBINED_DELIVERY;
+    case SEPARATE_DELIVERY:
+        return JNI_DRM_SEPARATE_DELIVERY;
+    case SEPARATE_DELIVERY_FL:
+        return JNI_DRM_SEPARATE_DELIVERY_DM;
+    default:
+        return JNI_DRM_FAILURE;
+    }
+}
+
+/* native interface */
+JNIEXPORT jint JNICALL
+Java_android_drm_mobile1_DrmRawContent_nativeReadContent
+  (JNIEnv * env, jobject rawContent, jbyteArray buf, jint bufOff, jint len, jint mediaOff)
+{
+    jint id;
+    jbyte *nativeBuf;
+    jclass cls;
+    jmethodID mid;
+    DrmData* p;
+    jobject inputStream;
+    jfieldID field;
+
+    if (NULL == buf) {
+        jclass newExcCls = (*env)->FindClass(env, "java/lang/NullPointerException");
+
+        if (newExcCls == NULL)
+            /* Unable to find the exception class, give up. */
+            return JNI_DRM_FAILURE;
+
+        (*env)->ThrowNew(env, newExcCls, "b is null");
+    }
+
+    if (len < 0 || bufOff < 0 || len + bufOff > (*env)->GetArrayLength(env, buf)) {
+        jclass newExcCls = (*env)->FindClass(env, "java/lang/IndexOutOfBoundsException");
+
+        if (newExcCls == NULL)
+            /* Unable to find the exception class, give up. */
+            return JNI_DRM_FAILURE;
+
+        (*env)->ThrowNew(env, newExcCls, NULL);
+    }
+
+    if (mediaOff < 0 || len == 0)
+        return JNI_DRM_FAILURE;
+
+    if (JNI_DRM_FAILURE == getObjectIntField(env, rawContent, "id", &id))
+        return JNI_DRM_FAILURE;
+
+    p = getItem(id);
+    if (NULL == p)
+        return JNI_DRM_FAILURE;
+
+    cls = (*env)->GetObjectClass(env, rawContent);
+    if (NULL == cls)
+        return JNI_DRM_FAILURE;
+
+    field = (*env)->GetFieldID(env, cls, "inData", "Ljava/io/BufferedInputStream;");
+    (*env)->DeleteLocalRef(env, cls);
+
+    if (NULL == field)
+        return JNI_DRM_FAILURE;
+
+    inputStream = (*env)->GetObjectField(env, rawContent, field);
+
+    p->env = env;
+    p->pInData = &inputStream;
+
+    nativeBuf = (*env)->GetByteArrayElements(env, buf, NULL);
+
+    len = SVC_drm_getContent(id, mediaOff, (uint8_t *)nativeBuf + bufOff, len);
+
+    (*env)->ReleaseByteArrayElements(env, buf, nativeBuf, 0);
+
+    if (DRM_MEDIA_EOF == len)
+        return JNI_DRM_EOF;
+    if (len <= 0)
+        return JNI_DRM_FAILURE;
+
+    return len;
+}
+
+/* native interface */
+JNIEXPORT jstring JNICALL
+Java_android_drm_mobile1_DrmRawContent_nativeGetContentType
+  (JNIEnv * env, jobject rawContent)
+{
+    jint id;
+    uint8_t contentType[64] = {0};
+    jstring str = NULL;
+
+    if (JNI_DRM_FAILURE == getObjectIntField(env, rawContent, "id", &id))
+        return NULL;
+
+    if (DRM_SUCCESS == SVC_drm_getContentType(id, contentType))
+        str = (*env)->NewStringUTF(env, (char *)contentType);
+
+    return str;
+}
+
+/* native interface */
+JNIEXPORT jint JNICALL
+Java_android_drm_mobile1_DrmRawContent_nativeGetContentLength
+  (JNIEnv * env, jobject rawContent)
+{
+    jint id;
+    int32_t len;
+
+    if (JNI_DRM_FAILURE == getObjectIntField(env, rawContent, "id", &id))
+        return JNI_DRM_FAILURE;
+
+    len = SVC_drm_getContentLength(id);
+
+    if (DRM_UNKNOWN_DATA_LEN == len)
+        return JNI_DRM_UNKNOWN_DATA_LEN;
+
+    if (0 > len)
+        return JNI_DRM_FAILURE;
+
+    return len;
+}
+
+/* native interface */
+JNIEXPORT void JNICALL
+Java_android_drm_mobile1_DrmRawContent_finalize
+  (JNIEnv * env, jobject rawContent)
+{
+    jint id;
+
+    if (JNI_DRM_FAILURE == getObjectIntField(env, rawContent, "id", &id))
+        return;
+
+    removeItem(id);
+
+    SVC_drm_closeSession(id);
+}
+
+/* native interface */
+JNIEXPORT jint JNICALL
+Java_android_drm_mobile1_DrmRights_nativeGetConstraintInfo
+  (JNIEnv * env, jobject rights, jint permission, jobject constraint)
+{
+    jclass clazz;
+    jfieldID field;
+    jstring str;
+    uint8_t *nativeStr;
+    T_DRM_Rights_Info_Node *pRightsList;
+    T_DRM_Rights_Info_Node *pCurNode;
+    T_DRM_Constraint_Info *pConstraint;
+
+    clazz = (*env)->GetObjectClass(env, rights);
+    if (NULL == clazz)
+        return JNI_DRM_FAILURE;
+
+    field = (*env)->GetFieldID(env, clazz, "roId", "Ljava/lang/String;");
+    (*env)->DeleteLocalRef(env, clazz);
+
+    if (NULL == field)
+        return JNI_DRM_FAILURE;
+
+    str = (*env)->GetObjectField(env, rights, field);
+
+    nativeStr = (uint8_t *)(*env)->GetStringUTFChars(env, str, NULL);
+    if (NULL == nativeStr)
+        return JNI_DRM_FAILURE;
+
+    /* this means forward-lock rights */
+    if (0 == strcmp((char *)nativeStr, "ForwardLock")) {
+        (*env)->ReleaseStringUTFChars(env, str, (char *)nativeStr);
+        return JNI_DRM_SUCCESS;
+    }
+
+    if (DRM_FAILURE == SVC_drm_viewAllRights(&pRightsList)) {
+        (*env)->ReleaseStringUTFChars(env, str, (char *)nativeStr);
+        return JNI_DRM_FAILURE;
+    }
+
+    pCurNode = searchRightsObject((jbyte *)nativeStr, pRightsList);
+    if (NULL == pCurNode) {
+        (*env)->ReleaseStringUTFChars(env, str, (char *)nativeStr);
+        SVC_drm_freeRightsInfoList(pRightsList);
+        return JNI_DRM_FAILURE;
+    }
+    (*env)->ReleaseStringUTFChars(env, str, (char *)nativeStr);
+
+    switch (permission) {
+    case JNI_DRM_PERMISSION_PLAY:
+        pConstraint = &(pCurNode->roInfo.playRights);
+        break;
+    case JNI_DRM_PERMISSION_DISPLAY:
+        pConstraint = &(pCurNode->roInfo.displayRights);
+        break;
+    case JNI_DRM_PERMISSION_EXECUTE:
+        pConstraint = &(pCurNode->roInfo.executeRights);
+        break;
+    case JNI_DRM_PERMISSION_PRINT:
+        pConstraint = &(pCurNode->roInfo.printRights);
+        break;
+    default:
+        SVC_drm_freeRightsInfoList(pRightsList);
+        return JNI_DRM_FAILURE;
+    }
+
+    /* set constraint field */
+    if (JNI_DRM_FAILURE == setConstraintFields(env, constraint, pConstraint)) {
+        SVC_drm_freeRightsInfoList(pRightsList);
+        return JNI_DRM_FAILURE;
+    }
+
+    SVC_drm_freeRightsInfoList(pRightsList);
+
+    return JNI_DRM_SUCCESS;
+}
+
+/* native interface */
+JNIEXPORT jint JNICALL
+Java_android_drm_mobile1_DrmRights_nativeConsumeRights
+  (JNIEnv * env, jobject rights, jint permission)
+{
+    jclass clazz;
+    jfieldID field;
+    jstring str;
+    uint8_t *nativeStr;
+    int32_t id;
+
+    switch (permission) {
+    case JNI_DRM_PERMISSION_PLAY:
+        permission = DRM_PERMISSION_PLAY;
+        break;
+    case JNI_DRM_PERMISSION_DISPLAY:
+        permission = DRM_PERMISSION_DISPLAY;
+        break;
+    case JNI_DRM_PERMISSION_EXECUTE:
+        permission = DRM_PERMISSION_EXECUTE;
+        break;
+    case JNI_DRM_PERMISSION_PRINT:
+        permission = DRM_PERMISSION_PRINT;
+        break;
+    default:
+        return JNI_DRM_FAILURE;
+    }
+
+    clazz = (*env)->GetObjectClass(env, rights);
+    if (NULL == clazz)
+        return JNI_DRM_FAILURE;
+
+    field = (*env)->GetFieldID(env, clazz, "roId", "Ljava/lang/String;");
+    (*env)->DeleteLocalRef(env, clazz);
+
+    if (NULL == field)
+        return JNI_DRM_FAILURE;
+
+    str = (*env)->GetObjectField(env, rights, field);
+
+    nativeStr = (uint8_t *)(*env)->GetStringUTFChars(env, str, NULL);
+    if (NULL == nativeStr)
+        return JNI_DRM_FAILURE;
+
+    if (0 == strcmp("ForwardLock", (char *)nativeStr)) {
+        (*env)->ReleaseStringUTFChars(env, str, (char *)nativeStr);
+        return JNI_DRM_SUCCESS;
+    }
+
+    if (DRM_SUCCESS != SVC_drm_updateRights(nativeStr, permission)) {
+        (*env)->ReleaseStringUTFChars(env, str, (char *)nativeStr);
+        return JNI_DRM_FAILURE;
+    }
+
+    (*env)->ReleaseStringUTFChars(env, str, (char *)nativeStr);
+
+    return JNI_DRM_SUCCESS;
+}
+
+/* native interface */
+JNIEXPORT jint JNICALL
+Java_android_drm_mobile1_DrmRightsManager_nativeInstallDrmRights
+  (JNIEnv * env, jobject rightsManager, jobject data, jint len, jint mimeType, jobject rights)
+{
+    int32_t id;
+    T_DRM_Input_Data inData;
+    DrmData* drmInData;
+    jclass cls;
+    jmethodID mid;
+    T_DRM_Rights_Info rightsInfo;
+
+    switch (mimeType) {
+    case JNI_DRM_MIMETYPE_RIGHTS_XML:
+        mimeType = TYPE_DRM_RIGHTS_XML;
+        break;
+    case JNI_DRM_MIMETYPE_RIGHTS_WBXML:
+        mimeType = TYPE_DRM_RIGHTS_WBXML;
+        break;
+    case JNI_DRM_MIMETYPE_MESSAGE:
+        mimeType = TYPE_DRM_MESSAGE;
+        break;
+    default:
+        return JNI_DRM_FAILURE;
+    }
+
+    drmInData = newItem();
+    if (NULL == drmInData)
+        return JNI_DRM_FAILURE;
+
+    drmInData->env = env;
+    drmInData->pInData = &data;
+    drmInData->len = len;
+
+    inData.inputHandle = (int32_t)drmInData;
+    inData.mimeType = mimeType;
+    inData.getInputDataLength = getInputStreamDataLength;
+    inData.readInputData = readInputStreamData;
+
+    memset(&rightsInfo, 0, sizeof(T_DRM_Rights_Info));
+    if (DRM_FAILURE == SVC_drm_installRights(inData, &rightsInfo))
+        return JNI_DRM_FAILURE;
+
+    freeItem(drmInData);
+
+    return setRightsFields(env, rights, &rightsInfo);
+}
+
+/* native interface */
+JNIEXPORT jint JNICALL
+Java_android_drm_mobile1_DrmRightsManager_nativeQueryRights
+  (JNIEnv * env, jobject rightsManager, jobject rawContent, jobject rights)
+{
+    jint id;
+    T_DRM_Rights_Info rightsInfo;
+
+    if (JNI_DRM_FAILURE == getObjectIntField(env, rawContent, "id", &id))
+        return JNI_DRM_FAILURE;
+
+    memset(&rightsInfo, 0, sizeof(T_DRM_Rights_Info));
+    if (DRM_SUCCESS != SVC_drm_getRightsInfo(id, &rightsInfo))
+        return JNI_DRM_FAILURE;
+
+    return setRightsFields(env, rights, &rightsInfo);
+}
+
+/* native interface */
+JNIEXPORT jint JNICALL
+Java_android_drm_mobile1_DrmRightsManager_nativeGetNumOfRights
+  (JNIEnv * env, jobject rightsManager)
+{
+    T_DRM_Rights_Info_Node *pRightsList;
+    T_DRM_Rights_Info_Node *pCurNode;
+    int32_t num = 0;
+
+    if (DRM_FAILURE == SVC_drm_viewAllRights(&pRightsList))
+        return JNI_DRM_FAILURE;
+
+    pCurNode = pRightsList;
+    while (pCurNode != NULL) {
+        num++;
+        pCurNode = pCurNode->next;
+    }
+
+    SVC_drm_freeRightsInfoList(pRightsList);
+
+    return num;
+}
+
+/* native interface */
+JNIEXPORT jint JNICALL
+Java_android_drm_mobile1_DrmRightsManager_nativeGetRightsList
+  (JNIEnv * env, jobject rightsManager, jobjectArray rightsArray, jint num)
+{
+    T_DRM_Rights_Info_Node *pRightsList;
+    T_DRM_Rights_Info_Node *pCurNode;
+    int32_t index;
+
+    if (DRM_FAILURE == SVC_drm_viewAllRights(&pRightsList))
+        return JNI_DRM_FAILURE;
+
+    pCurNode = pRightsList;
+    for (index = 0; NULL != pCurNode; index++) {
+        jobject rights = (*env)->GetObjectArrayElement(env, rightsArray, index);
+        if (NULL == rights)
+            break;
+
+        if (JNI_DRM_FAILURE == setRightsFields(env, rights, &(pCurNode->roInfo)))
+            break;
+
+        (*env)->SetObjectArrayElement(env, rightsArray, index, rights);
+
+        pCurNode = pCurNode->next;
+    }
+
+    SVC_drm_freeRightsInfoList(pRightsList);
+
+    return index;
+}
+
+/* native interface */
+JNIEXPORT jint JNICALL
+Java_android_drm_mobile1_DrmRightsManager_nativeDeleteRights
+  (JNIEnv * env, jobject rightsManager, jobject rights)
+{
+    jclass clazz;
+    jfieldID field;
+    jstring str;
+    uint8_t *nativeStr;
+
+    clazz = (*env)->GetObjectClass(env, rights);
+    if (NULL == clazz)
+        return JNI_DRM_FAILURE;
+
+    field = (*env)->GetFieldID(env, clazz, "roId", "Ljava/lang/String;");
+    if (NULL == field)
+        return JNI_DRM_FAILURE;
+
+    str = (*env)->GetObjectField(env, rights, field);
+
+    nativeStr = (uint8_t *)(*env)->GetStringUTFChars(env, str, NULL);
+    if (NULL == nativeStr)
+        return JNI_DRM_FAILURE;
+
+    if (0 == strcmp("ForwardLock", (char *)nativeStr))
+        return JNI_DRM_SUCCESS;
+
+    if (DRM_SUCCESS != SVC_drm_deleteRights(nativeStr)) {
+        (*env)->ReleaseStringUTFChars(env, str, (char *)nativeStr);
+        return JNI_DRM_FAILURE;
+    }
+
+    (*env)->ReleaseStringUTFChars(env, str, (char *)nativeStr);
+    return JNI_DRM_SUCCESS;
+}
+
+/*
+ * Table of methods associated with the DrmRawContent class.
+ */
+static JNINativeMethod gDrmRawContentMethods[] = {
+    /* name, signature, funcPtr */
+    {"nativeConstructDrmContent", "(Ljava/io/InputStream;II)I",
+        (void*)Java_android_drm_mobile1_DrmRawContent_nativeConstructDrmContent},
+    {"nativeGetRightsAddress", "()Ljava/lang/String;",
+        (void*)Java_android_drm_mobile1_DrmRawContent_nativeGetRightsAddress},
+    {"nativeGetDeliveryMethod", "()I",
+        (void*)Java_android_drm_mobile1_DrmRawContent_nativeGetDeliveryMethod},
+    {"nativeReadContent", "([BIII)I",
+        (void*)Java_android_drm_mobile1_DrmRawContent_nativeReadContent},
+    {"nativeGetContentType", "()Ljava/lang/String;",
+        (void*)Java_android_drm_mobile1_DrmRawContent_nativeGetContentType},
+    {"nativeGetContentLength", "()I",
+        (void*)Java_android_drm_mobile1_DrmRawContent_nativeGetContentLength},
+    {"finalize", "()V",
+        (void*)Java_android_drm_mobile1_DrmRawContent_finalize},
+};
+
+/*
+ * Table of methods associated with the DrmRights class.
+ */
+static JNINativeMethod gDrmRightsMethods[] = {
+    /* name, signature, funcPtr */
+    {"nativeGetConstraintInfo", "(ILandroid/drm/mobile1/DrmConstraintInfo;)I",
+        (void*)Java_android_drm_mobile1_DrmRights_nativeGetConstraintInfo},
+    {"nativeConsumeRights", "(I)I",
+        (void*)Java_android_drm_mobile1_DrmRights_nativeConsumeRights},
+};
+
+/*
+ * Table of methods associated with the DrmRightsManager class.
+ */
+static JNINativeMethod gDrmRightsManagerMethods[] = {
+    /* name, signature, funcPtr */
+    {"nativeInstallDrmRights", "(Ljava/io/InputStream;IILandroid/drm/mobile1/DrmRights;)I",
+        (void*)Java_android_drm_mobile1_DrmRightsManager_nativeInstallDrmRights},
+    {"nativeQueryRights", "(Landroid/drm/mobile1/DrmRawContent;Landroid/drm/mobile1/DrmRights;)I",
+        (void*)Java_android_drm_mobile1_DrmRightsManager_nativeQueryRights},
+    {"nativeGetNumOfRights", "()I",
+        (void*)Java_android_drm_mobile1_DrmRightsManager_nativeGetNumOfRights},
+    {"nativeGetRightsList", "([Landroid/drm/mobile1/DrmRights;I)I",
+        (void*)Java_android_drm_mobile1_DrmRightsManager_nativeGetRightsList},
+    {"nativeDeleteRights", "(Landroid/drm/mobile1/DrmRights;)I",
+        (void*)Java_android_drm_mobile1_DrmRightsManager_nativeDeleteRights},
+};
+
+/*
+ * Register several native methods for one class.
+ */
+static int registerNativeMethods(JNIEnv* env, const char* className,
+    JNINativeMethod* gMethods, int numMethods)
+{
+    jclass clazz;
+
+    clazz = (*env)->FindClass(env, className);
+    if (clazz == NULL)
+        return JNI_FALSE;
+
+    if ((*env)->RegisterNatives(env, clazz, gMethods, numMethods) < 0)
+        return JNI_FALSE;
+
+    return JNI_TRUE;
+}
+
+/*
+ * Register native methods for all classes we know about.
+ */
+static int registerNatives(JNIEnv* env)
+{
+    if (!registerNativeMethods(env, "android/drm/mobile1/DrmRawContent",
+            gDrmRawContentMethods, sizeof(gDrmRawContentMethods) / sizeof(gDrmRawContentMethods[0])))
+        return JNI_FALSE;
+
+    if (!registerNativeMethods(env, "android/drm/mobile1/DrmRights",
+            gDrmRightsMethods, sizeof(gDrmRightsMethods) / sizeof(gDrmRightsMethods[0])))
+        return JNI_FALSE;
+
+    if (!registerNativeMethods(env, "android/drm/mobile1/DrmRightsManager",
+            gDrmRightsManagerMethods, sizeof(gDrmRightsManagerMethods) / sizeof(gDrmRightsManagerMethods[0])))
+        return JNI_FALSE;
+
+    return JNI_TRUE;
+}
+
+jint JNI_OnLoad(JavaVM* vm, void* reserved)
+{
+    JNIEnv* env = NULL;
+    jint result = -1;
+
+    printf("Entering JNI_OnLoad\n");
+
+    if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_4) != JNI_OK)
+        goto bail;
+
+    assert(env != NULL);
+
+    if (!registerNatives(env))
+        goto bail;
+
+    /* success -- return valid version number */
+    result = JNI_VERSION_1_4;
+
+bail:
+    printf("Leaving JNI_OnLoad (result=0x%x)\n", result);
+    return result;
+}
diff --git a/media/libdrm/mobile1/src/objmng/drm_api.c b/media/libdrm/mobile1/src/objmng/drm_api.c
new file mode 100644
index 0000000..0e453de
--- /dev/null
+++ b/media/libdrm/mobile1/src/objmng/drm_api.c
@@ -0,0 +1,1944 @@
+/*
+ * 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.
+ */
+
+#include <svc_drm.h>
+#include <drm_inner.h>
+#include <parser_dm.h>
+#include <parser_dcf.h>
+#include <parser_rel.h>
+#include <drm_rights_manager.h>
+#include <drm_time.h>
+#include <drm_decoder.h>
+#include <aes.h>
+#include "log.h"
+
+/**
+ * Current id.
+ */
+static int32_t curID = 0;
+
+/**
+ * The header pointer for the session list.
+ */
+static T_DRM_Session_Node* sessionTable = NULL;
+
+/**
+ * New a session.
+ */
+static T_DRM_Session_Node* newSession(T_DRM_Input_Data data)
+{
+    T_DRM_Session_Node* s = (T_DRM_Session_Node *)malloc(sizeof(T_DRM_Session_Node));
+
+    if (NULL != s) {
+        memset(s, 0, sizeof(T_DRM_Session_Node));
+
+        s->sessionId = curID++;
+        s->inputHandle = data.inputHandle;
+        s->mimeType = data.mimeType;
+        s->getInputDataLengthFunc = data.getInputDataLength;
+        s->readInputDataFunc = data.readInputData;
+        s->seekInputDataFunc = data.seekInputData;
+    }
+
+    return s;
+}
+
+/**
+ * Free a session.
+ */
+static void freeSession(T_DRM_Session_Node* s)
+{
+    if (NULL == s)
+        return;
+
+    if (NULL != s->rawContent)
+        free(s->rawContent);
+
+    if (NULL != s->readBuf)
+        free(s->readBuf);
+
+    if (NULL != s->infoStruct)
+        free(s->infoStruct);
+
+    free(s);
+}
+
+/**
+ * Add a session to list.
+ */
+static int32_t addSession(T_DRM_Session_Node* s)
+{
+    if (NULL == s)
+        return -1;
+
+    s->next = sessionTable;
+    sessionTable = s;
+
+    return s->sessionId;
+}
+
+/**
+ * Get a session from the list.
+ */
+static T_DRM_Session_Node* getSession(int32_t sessionId)
+{
+    T_DRM_Session_Node* s;
+
+    if (sessionId < 0 || NULL == sessionTable)
+        return NULL;
+
+    for (s = sessionTable; s != NULL; s = s->next) {
+        if (sessionId == s->sessionId)
+            return s;
+    }
+
+    return NULL;
+}
+
+/**
+ * Remove a session from the list.
+ */
+static void removeSession(int32_t sessionId)
+{
+    T_DRM_Session_Node *curS, *preS;
+
+    if (sessionId < 0 || NULL == sessionTable)
+        return;
+
+    if (sessionId == sessionTable->sessionId) {
+        curS = sessionTable;
+        sessionTable = curS->next;
+        freeSession(curS);
+        return;
+    }
+
+    for (preS = sessionTable; preS->next != NULL; preS = preS->next) {
+        if (preS->next->sessionId == sessionId)
+            curS = preS->next;
+    }
+
+    if (NULL == preS->next)
+        return;
+
+    preS->next = curS->next;
+    freeSession(curS);
+}
+
+/**
+ * Try to identify the mimetype according the input DRM data.
+ */
+static int32_t getMimeType(const uint8_t *buf, int32_t bufLen)
+{
+    const uint8_t *p;
+
+    if (NULL == buf || bufLen <= 0)
+        return TYPE_DRM_UNKNOWN;
+
+    p = buf;
+
+    /* check if it is DRM Content Format, only check the first field of Version, it must be "0x01" */
+    if (0x01 == *p)
+        return TYPE_DRM_CONTENT;
+
+    /* check if it is DRM Message, only check the first two bytes, it must be the start flag of boundary: "--" */
+    if (bufLen >= 2 && '-' == *p && '-' == *(p + 1))
+        return TYPE_DRM_MESSAGE;
+
+    /* check if it is DRM Rights XML format, only check the first several bytes, it must be: "<o-ex:rights" */
+    if (bufLen >= 12 && 0 == strncmp("<o-ex:rights", (char *)p, 12))
+        return TYPE_DRM_RIGHTS_XML;
+
+    /* check if it is DRM Rights WBXML format, only check the first two bytes, it must be: 0x03, 0x0e */
+    if (bufLen >= 2 && 0x03 == *p && 0x0e == *(p + 1))
+        return TYPE_DRM_RIGHTS_WBXML;
+
+    return TYPE_DRM_UNKNOWN;
+}
+
+static int32_t drm_skipCRLFinB64(const uint8_t* b64Data, int32_t len)
+{
+    const uint8_t* p;
+    int32_t skipLen = 0;
+
+    if (NULL == b64Data || len <= 0)
+        return -1;
+
+    p = b64Data;
+    while (p - b64Data < len) {
+        if ('\r' == *p || '\n'== *p)
+            skipLen++;
+        p++;
+    }
+
+    return skipLen;
+}
+
+static int32_t drm_scanEndBoundary(const uint8_t* pBuf, int32_t len, uint8_t* const boundary)
+{
+    const uint8_t* p;
+    int32_t leftLen;
+    int32_t boundaryLen;
+
+    if (NULL == pBuf || len <=0 || NULL == boundary)
+        return -1;
+
+    p = pBuf;
+    boundaryLen = strlen((char *)boundary) + 2; /* 2 means: '\r' and '\n' */
+    leftLen = len - (p - pBuf);
+    while (leftLen > 0) {
+        if (NULL == (p = memchr(p, '\r', leftLen)))
+            break;
+
+        leftLen = len - (p - pBuf);
+        if (leftLen < boundaryLen)
+            return -2; /* here means may be the boundary has been split */
+
+        if (('\n' == *(p + 1)) && (0 == memcmp(p + 2, boundary, strlen((char *)boundary))))
+            return p - pBuf; /* find the boundary here */
+
+        p++;
+        leftLen--;
+    }
+
+    return len; /* no boundary found */
+}
+
+static int32_t drm_getLicenseInfo(T_DRM_Rights* pRights, T_DRM_Rights_Info* licenseInfo)
+{
+    if (NULL != licenseInfo && NULL != pRights) {
+        strcpy((char *)licenseInfo->roId, (char *)pRights->uid);
+
+        if (1 == pRights->bIsDisplayable) {
+            licenseInfo->displayRights.indicator = pRights->DisplayConstraint.Indicator;
+            licenseInfo->displayRights.count =
+                pRights->DisplayConstraint.Count;
+            licenseInfo->displayRights.startDate =
+                pRights->DisplayConstraint.StartTime.date;
+            licenseInfo->displayRights.startTime =
+                pRights->DisplayConstraint.StartTime.time;
+            licenseInfo->displayRights.endDate =
+                pRights->DisplayConstraint.EndTime.date;
+            licenseInfo->displayRights.endTime =
+                pRights->DisplayConstraint.EndTime.time;
+            licenseInfo->displayRights.intervalDate =
+                pRights->DisplayConstraint.Interval.date;
+            licenseInfo->displayRights.intervalTime =
+                pRights->DisplayConstraint.Interval.time;
+        }
+        if (1 == pRights->bIsPlayable) {
+            licenseInfo->playRights.indicator = pRights->PlayConstraint.Indicator;
+            licenseInfo->playRights.count = pRights->PlayConstraint.Count;
+            licenseInfo->playRights.startDate =
+                pRights->PlayConstraint.StartTime.date;
+            licenseInfo->playRights.startTime =
+                pRights->PlayConstraint.StartTime.time;
+            licenseInfo->playRights.endDate =
+                pRights->PlayConstraint.EndTime.date;
+            licenseInfo->playRights.endTime =
+                pRights->PlayConstraint.EndTime.time;
+            licenseInfo->playRights.intervalDate =
+                pRights->PlayConstraint.Interval.date;
+            licenseInfo->playRights.intervalTime =
+                pRights->PlayConstraint.Interval.time;
+        }
+        if (1 == pRights->bIsExecuteable) {
+            licenseInfo->executeRights.indicator = pRights->ExecuteConstraint.Indicator;
+            licenseInfo->executeRights.count =
+                pRights->ExecuteConstraint.Count;
+            licenseInfo->executeRights.startDate =
+                pRights->ExecuteConstraint.StartTime.date;
+            licenseInfo->executeRights.startTime =
+                pRights->ExecuteConstraint.StartTime.time;
+            licenseInfo->executeRights.endDate =
+                pRights->ExecuteConstraint.EndTime.date;
+            licenseInfo->executeRights.endTime =
+                pRights->ExecuteConstraint.EndTime.time;
+            licenseInfo->executeRights.intervalDate =
+                pRights->ExecuteConstraint.Interval.date;
+            licenseInfo->executeRights.intervalTime =
+                pRights->ExecuteConstraint.Interval.time;
+        }
+        if (1 == pRights->bIsPrintable) {
+            licenseInfo->printRights.indicator = pRights->PrintConstraint.Indicator;
+            licenseInfo->printRights.count =
+                pRights->PrintConstraint.Count;
+            licenseInfo->printRights.startDate =
+                pRights->PrintConstraint.StartTime.date;
+            licenseInfo->printRights.startTime =
+                pRights->PrintConstraint.StartTime.time;
+            licenseInfo->printRights.endDate =
+                pRights->PrintConstraint.EndTime.date;
+            licenseInfo->printRights.endTime =
+                pRights->PrintConstraint.EndTime.time;
+            licenseInfo->printRights.intervalDate =
+                pRights->PrintConstraint.Interval.date;
+            licenseInfo->printRights.intervalTime =
+                pRights->PrintConstraint.Interval.time;
+        }
+        return TRUE;
+    }
+    return FALSE;
+}
+
+static int32_t drm_addRightsNodeToList(T_DRM_Rights_Info_Node **ppRightsHeader,
+                                       T_DRM_Rights_Info_Node *pInputRightsNode)
+{
+    T_DRM_Rights_Info_Node *pRightsNode;
+
+    if (NULL == ppRightsHeader || NULL == pInputRightsNode)
+        return FALSE;
+
+    pRightsNode = (T_DRM_Rights_Info_Node *)malloc(sizeof(T_DRM_Rights_Info_Node));
+    if (NULL == pRightsNode)
+        return FALSE;
+
+    memcpy(pRightsNode, pInputRightsNode, sizeof(T_DRM_Rights_Info_Node));
+    pRightsNode->next = NULL;
+
+    /* this means it is the first node */
+    if (NULL == *ppRightsHeader)
+        *ppRightsHeader = pRightsNode;
+    else {
+        T_DRM_Rights_Info_Node *pTmp;
+
+        pTmp = *ppRightsHeader;
+        while (NULL != pTmp->next)
+            pTmp = pTmp->next;
+
+        pTmp->next = pRightsNode;
+    }
+    return TRUE;
+}
+
+static int32_t drm_startConsumeRights(int32_t * bIsXXable,
+                                      T_DRM_Rights_Constraint * XXConstraint,
+                                      int32_t * writeFlag)
+{
+    T_DB_TIME_SysTime curDateTime;
+    T_DRM_DATETIME CurrentTime;
+    uint8_t countFlag = 0;
+
+    memset(&CurrentTime, 0, sizeof(T_DRM_DATETIME));
+
+    if (NULL == bIsXXable || 0 == *bIsXXable || NULL == XXConstraint || NULL == writeFlag)
+        return DRM_FAILURE;
+
+    if (0 != (uint8_t)(XXConstraint->Indicator & DRM_NO_CONSTRAINT)) /* Have utter right? */
+        return DRM_SUCCESS;
+
+    *bIsXXable = 0; /* Assume have invalid rights at first */
+    *writeFlag = 0;
+
+    if (0 != (XXConstraint->Indicator & (DRM_START_TIME_CONSTRAINT | DRM_END_TIME_CONSTRAINT | DRM_INTERVAL_CONSTRAINT))) {
+        DRM_time_getSysTime(&curDateTime);
+
+        if (-1 == drm_checkDate(curDateTime.year, curDateTime.month, curDateTime.day,
+                                curDateTime.hour, curDateTime.min, curDateTime.sec))
+            return DRM_FAILURE;
+
+        YMD_HMS_2_INT(curDateTime.year, curDateTime.month, curDateTime.day,
+                      CurrentTime.date, curDateTime.hour, curDateTime.min,
+                      curDateTime.sec, CurrentTime.time);
+    }
+
+    if (0 != (uint8_t)(XXConstraint->Indicator & DRM_COUNT_CONSTRAINT)) { /* Have count restrict? */
+        *writeFlag = 1;
+        /* If it has only one time for use, after use this function, we will delete this rights */
+        if (XXConstraint->Count <= 0) {
+            XXConstraint->Indicator &= ~DRM_COUNT_CONSTRAINT;
+            return DRM_RIGHTS_EXPIRED;
+        }
+
+        if (XXConstraint->Count-- <= 1) {
+            XXConstraint->Indicator &= ~DRM_COUNT_CONSTRAINT;
+            countFlag = 1;
+        }
+    }
+
+    if (0 != (uint8_t)(XXConstraint->Indicator & DRM_START_TIME_CONSTRAINT)) {
+        if (XXConstraint->StartTime.date > CurrentTime.date ||
+            (XXConstraint->StartTime.date == CurrentTime.date &&
+             XXConstraint->StartTime.time >= CurrentTime.time)) {
+            *bIsXXable = 1;
+            return DRM_RIGHTS_PENDING;
+        }
+    }
+
+    if (0 != (uint8_t)(XXConstraint->Indicator & DRM_END_TIME_CONSTRAINT)) { /* Have end time restrict? */
+        if (XXConstraint->EndTime.date < CurrentTime.date ||
+            (XXConstraint->EndTime.date == CurrentTime.date &&
+             XXConstraint->EndTime.time <= CurrentTime.time)) {
+            *writeFlag = 1;
+            XXConstraint->Indicator &= ~DRM_END_TIME_CONSTRAINT;
+            return DRM_RIGHTS_EXPIRED;
+        }
+    }
+
+    if (0 != (uint8_t)(XXConstraint->Indicator & DRM_INTERVAL_CONSTRAINT)) { /* Have interval time restrict? */
+        int32_t year, mon, day, hour, min, sec, date, time;
+        int32_t ret;
+
+        XXConstraint->Indicator |= DRM_END_TIME_CONSTRAINT;
+        XXConstraint->Indicator &= ~DRM_INTERVAL_CONSTRAINT; /* Write off interval right */
+        *writeFlag = 1;
+
+        if (XXConstraint->Interval.date == 0
+            && XXConstraint->Interval.time == 0) {
+            return DRM_RIGHTS_EXPIRED;
+        }
+        date = CurrentTime.date + XXConstraint->Interval.date;
+        time = CurrentTime.time + XXConstraint->Interval.time;
+        INT_2_YMD_HMS(year, mon, day, date, hour, min, sec, time);
+
+        if (sec > 59) {
+            min += sec / 60;
+            sec %= 60;
+        }
+        if (min > 59) {
+            hour += min / 60;
+            min %= 60;
+        }
+        if (hour > 23) {
+            day += hour / 24;
+            hour %= 24;
+        }
+        if (day > 31) {
+            mon += day / 31;
+            day %= 31;
+        }
+        if (mon > 12) {
+            year += mon / 12;
+            mon %= 12;
+        }
+        if (day > (ret = drm_monthDays(year, mon))) {
+            day -= ret;
+            mon++;
+            if (mon > 12) {
+                mon -= 12;
+                year++;
+            }
+        }
+        YMD_HMS_2_INT(year, mon, day, XXConstraint->EndTime.date, hour,
+                      min, sec, XXConstraint->EndTime.time);
+    }
+
+    if (1 != countFlag)
+        *bIsXXable = 1; /* Can go here ,so  right must be valid */
+    return DRM_SUCCESS;
+}
+
+static int32_t drm_startCheckRights(int32_t * bIsXXable,
+                                    T_DRM_Rights_Constraint * XXConstraint)
+{
+    T_DB_TIME_SysTime curDateTime;
+    T_DRM_DATETIME CurrentTime;
+
+    memset(&CurrentTime, 0, sizeof(T_DRM_DATETIME));
+
+    if (NULL == bIsXXable || 0 == *bIsXXable || NULL == XXConstraint)
+        return DRM_FAILURE;
+
+    if (0 != (uint8_t)(XXConstraint->Indicator & DRM_NO_CONSTRAINT)) /* Have utter right? */
+        return DRM_SUCCESS;
+
+    *bIsXXable = 0; /* Assume have invalid rights at first */
+
+    if (0 != (XXConstraint->Indicator & (DRM_START_TIME_CONSTRAINT | DRM_END_TIME_CONSTRAINT))) {
+        DRM_time_getSysTime(&curDateTime);
+
+        if (-1 == drm_checkDate(curDateTime.year, curDateTime.month, curDateTime.day,
+                                curDateTime.hour, curDateTime.min, curDateTime.sec))
+            return DRM_FAILURE;
+
+        YMD_HMS_2_INT(curDateTime.year, curDateTime.month, curDateTime.day,
+                      CurrentTime.date, curDateTime.hour, curDateTime.min,
+                      curDateTime.sec, CurrentTime.time);
+    }
+
+    if (0 != (uint8_t)(XXConstraint->Indicator & DRM_COUNT_CONSTRAINT)) { /* Have count restrict? */
+        if (XXConstraint->Count <= 0) {
+            XXConstraint->Indicator &= ~DRM_COUNT_CONSTRAINT;
+            return DRM_RIGHTS_EXPIRED;
+        }
+    }
+
+    if (0 != (uint8_t)(XXConstraint->Indicator & DRM_START_TIME_CONSTRAINT)) {
+        if (XXConstraint->StartTime.date > CurrentTime.date ||
+            (XXConstraint->StartTime.date == CurrentTime.date &&
+             XXConstraint->StartTime.time >= CurrentTime.time)) {
+            *bIsXXable = 1;
+            return DRM_RIGHTS_PENDING;
+        }
+    }
+
+    if (0 != (uint8_t)(XXConstraint->Indicator & DRM_END_TIME_CONSTRAINT)) { /* Have end time restrict? */
+        if (XXConstraint->EndTime.date < CurrentTime.date ||
+            (XXConstraint->EndTime.date == CurrentTime.date &&
+             XXConstraint->EndTime.time <= CurrentTime.time)) {
+            XXConstraint->Indicator &= ~DRM_END_TIME_CONSTRAINT;
+            return DRM_RIGHTS_EXPIRED;
+        }
+    }
+
+    if (0 != (uint8_t)(XXConstraint->Indicator & DRM_INTERVAL_CONSTRAINT)) { /* Have interval time restrict? */
+        if (XXConstraint->Interval.date == 0 && XXConstraint->Interval.time == 0) {
+            XXConstraint->Indicator &= ~DRM_INTERVAL_CONSTRAINT;
+            return DRM_RIGHTS_EXPIRED;
+        }
+    }
+
+    *bIsXXable = 1;
+    return DRM_SUCCESS;
+}
+
+int32_t drm_checkRoAndUpdate(int32_t id, int32_t permission)
+{
+    int32_t writeFlag = 0;
+    int32_t roAmount;
+    int32_t validRoAmount = 0;
+    int32_t flag = DRM_FAILURE;
+    int32_t i, j;
+    T_DRM_Rights *pRo;
+    T_DRM_Rights *pCurRo;
+    int32_t * pNumOfPriority;
+    int32_t iNum;
+    T_DRM_Rights_Constraint * pCurConstraint;
+    T_DRM_Rights_Constraint * pCompareConstraint;
+    int priority[8] = {1, 2, 4, 3, 8, 6, 7, 5};
+
+    if (FALSE == drm_writeOrReadInfo(id, NULL, &roAmount, GET_ROAMOUNT))
+        return DRM_FAILURE;
+
+    validRoAmount = roAmount;
+    if (roAmount < 1)
+        return DRM_NO_RIGHTS;
+
+    pRo = malloc(roAmount * sizeof(T_DRM_Rights));
+    pCurRo = pRo;
+    if (NULL == pRo)
+        return DRM_FAILURE;
+
+    if (FALSE == drm_writeOrReadInfo(id, pRo, &roAmount, GET_ALL_RO)) {
+        free(pRo);
+        return DRM_FAILURE;
+    }
+
+    /** check the right priority */
+    pNumOfPriority = malloc(sizeof(int32_t) * roAmount);
+    for(i = 0; i < roAmount; i++) {
+        iNum = roAmount - 1;
+        for(j = 0; j < roAmount; j++) {
+            if(i == j)
+                continue;
+            switch(permission) {
+            case DRM_PERMISSION_PLAY:
+                pCurConstraint = &pRo[i].PlayConstraint;
+                pCompareConstraint = &pRo[j].PlayConstraint;
+                break;
+            case DRM_PERMISSION_DISPLAY:
+                pCurConstraint = &pRo[i].DisplayConstraint;
+                pCompareConstraint = &pRo[j].DisplayConstraint;
+                break;
+            case DRM_PERMISSION_EXECUTE:
+                pCurConstraint = &pRo[i].ExecuteConstraint;
+                pCompareConstraint = &pRo[j].ExecuteConstraint;
+                break;
+            case DRM_PERMISSION_PRINT:
+                pCurConstraint = &pRo[i].PrintConstraint;
+                pCompareConstraint = &pRo[j].PrintConstraint;
+                break;
+            default:
+                free(pRo);
+                free(pNumOfPriority);
+                return DRM_FAILURE;
+            }
+
+            /**get priority by Indicator*/
+            if(0 == (pCurConstraint->Indicator & DRM_NO_CONSTRAINT) &&
+                0 == (pCompareConstraint->Indicator & DRM_NO_CONSTRAINT)) {
+                    int num1, num2;
+                    num1 = (pCurConstraint->Indicator & 0x0e) >> 1;
+                    num2 = (pCompareConstraint->Indicator & 0x0e) >> 1;
+                    if(priority[num1] > priority[num2]) {
+                        iNum--;
+                        continue;
+                    } else if(priority[pCurConstraint->Indicator] < priority[pCompareConstraint->Indicator])
+                        continue;
+            } else if(pCurConstraint->Indicator > pCompareConstraint->Indicator) {
+                iNum--;
+                continue;
+            } else if(pCurConstraint->Indicator < pCompareConstraint->Indicator)
+                continue;
+
+            if(0 != (pCurConstraint->Indicator & DRM_END_TIME_CONSTRAINT)) {
+                if(pCurConstraint->EndTime.date < pCompareConstraint->EndTime.date) {
+                    iNum--;
+                    continue;
+                } else if(pCurConstraint->EndTime.date > pCompareConstraint->EndTime.date)
+                    continue;
+
+                if(pCurConstraint->EndTime.time < pCompareConstraint->EndTime.time) {
+                    iNum--;
+                    continue;
+                } else if(pCurConstraint->EndTime.date > pCompareConstraint->EndTime.date)
+                    continue;
+            }
+
+            if(0 != (pCurConstraint->Indicator & DRM_INTERVAL_CONSTRAINT)) {
+                if(pCurConstraint->Interval.date < pCompareConstraint->Interval.date) {
+                    iNum--;
+                    continue;
+                } else if(pCurConstraint->Interval.date > pCompareConstraint->Interval.date)
+                    continue;
+
+                if(pCurConstraint->Interval.time < pCompareConstraint->Interval.time) {
+                    iNum--;
+                    continue;
+                } else if(pCurConstraint->Interval.time > pCompareConstraint->Interval.time)
+                    continue;
+            }
+
+            if(0 != (pCurConstraint->Indicator & DRM_COUNT_CONSTRAINT)) {
+                if(pCurConstraint->Count < pCompareConstraint->Count) {
+                    iNum--;
+                    continue;
+                } else if(pCurConstraint->Count > pCompareConstraint->Count)
+                    continue;
+            }
+
+            if(i < j)
+                iNum--;
+        }
+        pNumOfPriority[iNum] = i;
+    }
+
+    for (i = 0; i < validRoAmount; i++) {
+        /** check the right priority */
+        if (pNumOfPriority[i] >= validRoAmount)
+            break;
+
+        pCurRo = pRo + pNumOfPriority[i];
+
+        switch (permission) {
+        case DRM_PERMISSION_PLAY:
+            flag =
+                drm_startConsumeRights(&pCurRo->bIsPlayable,
+                                       &pCurRo->PlayConstraint, &writeFlag);
+            break;
+        case DRM_PERMISSION_DISPLAY:
+            flag =
+                drm_startConsumeRights(&pCurRo->bIsDisplayable,
+                                       &pCurRo->DisplayConstraint,
+                                       &writeFlag);
+            break;
+        case DRM_PERMISSION_EXECUTE:
+            flag =
+                drm_startConsumeRights(&pCurRo->bIsExecuteable,
+                                       &pCurRo->ExecuteConstraint,
+                                       &writeFlag);
+            break;
+        case DRM_PERMISSION_PRINT:
+            flag =
+                drm_startConsumeRights(&pCurRo->bIsPrintable,
+                                       &pCurRo->PrintConstraint, &writeFlag);
+            break;
+        default:
+            free(pNumOfPriority);
+            free(pRo);
+            return DRM_FAILURE;
+        }
+
+        /* Here confirm the valid RO amount and set the writeFlag */
+        if (0 == pCurRo->bIsPlayable && 0 == pCurRo->bIsDisplayable &&
+            0 == pCurRo->bIsExecuteable && 0 == pCurRo->bIsPrintable) {
+            int32_t iCurPri;
+
+            /** refresh the right priority */
+            iCurPri = pNumOfPriority[i];
+            for(j = i; j < validRoAmount - 1; j++)
+                pNumOfPriority[j] = pNumOfPriority[j + 1];
+
+            if(iCurPri != validRoAmount - 1) {
+                memcpy(pCurRo, pRo + validRoAmount - 1,
+                    sizeof(T_DRM_Rights));
+                for(j = 0; j < validRoAmount -1; j++) {
+                    if(validRoAmount - 1 == pNumOfPriority[j])
+                        pNumOfPriority[j] = iCurPri;
+                }
+            }
+
+            /* Here means it is not the last one RO, so the invalid RO should be deleted */
+            writeFlag = 1;
+            validRoAmount--; /* If current right is invalid */
+            i--;
+        }
+
+        /* If the flag is TRUE, this means: we have found a valid RO, so break, no need to check other RO */
+        if (DRM_SUCCESS == flag)
+            break;
+    }
+
+    if (1 == writeFlag) {
+        /* Delete the *.info first */
+        //drm_removeIdInfoFile(id);
+
+        if (FALSE == drm_writeOrReadInfo(id, pRo, &validRoAmount, SAVE_ALL_RO))
+            flag = DRM_FAILURE;
+    }
+
+    free(pNumOfPriority);
+    free(pRo);
+    return flag;
+}
+
+
+/* see svc_drm.h */
+int32_t SVC_drm_installRights(T_DRM_Input_Data data, T_DRM_Rights_Info* pRightsInfo)
+{
+    uint8_t *buf;
+    int32_t dataLen, bufLen;
+    T_DRM_Rights rights;
+
+    if (0 == data.inputHandle)
+        return DRM_RIGHTS_DATA_INVALID;
+
+    /* Get input rights data length */
+    dataLen = data.getInputDataLength(data.inputHandle);
+    if (dataLen <= 0)
+        return DRM_RIGHTS_DATA_INVALID;
+
+    /* Check if the length is larger than DRM max malloc length */
+    if (dataLen > DRM_MAX_MALLOC_LEN)
+        bufLen = DRM_MAX_MALLOC_LEN;
+    else
+        bufLen = dataLen;
+
+    buf = (uint8_t *)malloc(bufLen);
+    if (NULL == buf)
+        return DRM_FAILURE;
+
+    /* Read input data to buffer */
+    if (0 >= data.readInputData(data.inputHandle, buf, bufLen)) {
+        free(buf);
+        return DRM_RIGHTS_DATA_INVALID;
+    }
+
+    /* if the input mime type is unknown, DRM engine will try to recognize it. */
+    if (TYPE_DRM_UNKNOWN == data.mimeType)
+        data.mimeType = getMimeType(buf, bufLen);
+
+    switch(data.mimeType) {
+    case TYPE_DRM_MESSAGE: /* in case of Combined Delivery, extract the rights part to install */
+        {
+            T_DRM_DM_Info dmInfo;
+
+            memset(&dmInfo, 0, sizeof(T_DRM_DM_Info));
+            if (FALSE == drm_parseDM(buf, bufLen, &dmInfo)) {
+                free(buf);
+                return DRM_RIGHTS_DATA_INVALID;
+            }
+
+            /* if it is not Combined Delivery, it can not use to "SVC_drm_installRights" */
+            if (COMBINED_DELIVERY != dmInfo.deliveryType || dmInfo.rightsOffset <= 0 || dmInfo.rightsLen <= 0) {
+                free(buf);
+                return DRM_RIGHTS_DATA_INVALID;
+            }
+
+            memset(&rights, 0, sizeof(T_DRM_Rights));
+            if (FALSE == drm_relParser(buf + dmInfo.rightsOffset, dmInfo.rightsLen, TYPE_DRM_RIGHTS_XML, &rights)) {
+                free(buf);
+                return DRM_RIGHTS_DATA_INVALID;
+            }
+        }
+        break;
+    case TYPE_DRM_RIGHTS_XML:
+    case TYPE_DRM_RIGHTS_WBXML:
+        memset(&rights, 0, sizeof(T_DRM_Rights));
+        if (FALSE == drm_relParser(buf, bufLen, data.mimeType, &rights)) {
+            free(buf);
+            return DRM_RIGHTS_DATA_INVALID;
+        }
+        break;
+    case TYPE_DRM_CONTENT: /* DCF should not using "SVC_drm_installRights", it should be used to open a session. */
+    case TYPE_DRM_UNKNOWN:
+    default:
+        free(buf);
+        return DRM_MEDIA_DATA_INVALID;
+    }
+
+    free(buf);
+
+    /* append the rights information to DRM engine storage */
+    if (FALSE == drm_appendRightsInfo(&rights))
+        return DRM_FAILURE;
+
+    memset(pRightsInfo, 0, sizeof(T_DRM_Rights_Info));
+    drm_getLicenseInfo(&rights, pRightsInfo);
+
+    return DRM_SUCCESS;
+}
+
+/* see svc_drm.h */
+int32_t SVC_drm_openSession(T_DRM_Input_Data data)
+{
+    int32_t session;
+    int32_t dataLen;
+    T_DRM_Session_Node* s;
+
+    if (0 == data.inputHandle)
+        return DRM_MEDIA_DATA_INVALID;
+
+    /* Get input data length */
+    dataLen = data.getInputDataLength(data.inputHandle);
+    if (dataLen <= 0)
+        return DRM_MEDIA_DATA_INVALID;
+
+    s = newSession(data);
+    if (NULL == s)
+        return DRM_FAILURE;
+
+    /* Check if the length is larger than DRM max malloc length */
+    if (dataLen > DRM_MAX_MALLOC_LEN)
+        s->rawContentLen = DRM_MAX_MALLOC_LEN;
+    else
+        s->rawContentLen = dataLen;
+
+    s->rawContent = (uint8_t *)malloc(s->rawContentLen);
+    if (NULL == s->rawContent)
+        return DRM_FAILURE;
+
+    /* Read input data to buffer */
+    if (0 >= data.readInputData(data.inputHandle, s->rawContent, s->rawContentLen)) {
+        freeSession(s);
+        return DRM_MEDIA_DATA_INVALID;
+    }
+
+    /* if the input mime type is unknown, DRM engine will try to recognize it. */
+    if (TYPE_DRM_UNKNOWN == data.mimeType)
+        data.mimeType = getMimeType(s->rawContent, s->rawContentLen);
+
+    switch(data.mimeType) {
+    case TYPE_DRM_MESSAGE:
+        {
+            T_DRM_DM_Info dmInfo;
+
+            memset(&dmInfo, 0, sizeof(T_DRM_DM_Info));
+            if (FALSE == drm_parseDM(s->rawContent, s->rawContentLen, &dmInfo)) {
+                freeSession(s);
+                return DRM_MEDIA_DATA_INVALID;
+            }
+
+            s->deliveryMethod = dmInfo.deliveryType;
+
+            if (SEPARATE_DELIVERY_FL == s->deliveryMethod)
+                s->contentLength = DRM_UNKNOWN_DATA_LEN;
+            else
+                s->contentLength = dmInfo.contentLen;
+
+            s->transferEncoding = dmInfo.transferEncoding;
+            s->contentOffset = dmInfo.contentOffset;
+            s->bEndData = FALSE;
+            strcpy((char *)s->contentType, (char *)dmInfo.contentType);
+            strcpy((char *)s->contentID, (char *)dmInfo.contentID);
+
+            if (SEPARATE_DELIVERY_FL == s->deliveryMethod) {
+                s->infoStruct = (T_DRM_Dcf_Node *)malloc(sizeof(T_DRM_Dcf_Node));
+                if (NULL == s->infoStruct)
+                    return DRM_FAILURE;
+                memset(s->infoStruct, 0, sizeof(T_DRM_Dcf_Node));
+
+                ((T_DRM_Dcf_Node *)(s->infoStruct))->encContentLength = dmInfo.contentLen;
+                strcpy((char *)((T_DRM_Dcf_Node *)(s->infoStruct))->rightsIssuer, (char *)dmInfo.rightsIssuer);
+                break;
+            }
+
+            if (DRM_MESSAGE_CODING_BASE64 == s->transferEncoding) {
+                s->infoStruct = (T_DRM_DM_Base64_Node *)malloc(sizeof(T_DRM_DM_Base64_Node));
+                if (NULL == s->infoStruct)
+                    return DRM_FAILURE;
+                memset(s->infoStruct, 0, sizeof(T_DRM_DM_Base64_Node));
+
+                strcpy((char *)((T_DRM_DM_Base64_Node *)(s->infoStruct))->boundary, (char *)dmInfo.boundary);
+            } else {
+                s->infoStruct = (T_DRM_DM_Binary_Node *)malloc(sizeof(T_DRM_DM_Binary_Node));
+                if (NULL == s->infoStruct)
+                    return DRM_FAILURE;
+                memset(s->infoStruct, 0, sizeof(T_DRM_DM_Binary_Node));
+
+                strcpy((char *)((T_DRM_DM_Binary_Node *)(s->infoStruct))->boundary, (char *)dmInfo.boundary);
+            }
+
+
+            if (DRM_MESSAGE_CODING_BASE64 == s->transferEncoding) {
+                if (s->contentLength > 0) {
+                    int32_t encLen, decLen;
+
+                    encLen = s->contentLength;
+                    decLen = encLen / DRM_B64_ENC_BLOCK * DRM_B64_DEC_BLOCK;
+
+                    decLen = drm_decodeBase64(s->rawContent, decLen, s->rawContent + s->contentOffset, &encLen);
+                    s->contentLength = decLen;
+                } else {
+                    int32_t encLen = DRM_MAX_MALLOC_LEN - s->contentOffset, decLen;
+                    int32_t skipLen, needBytes, i;
+                    uint8_t *pStart;
+                    int32_t res, bFoundBoundary = FALSE;
+
+                    pStart = s->rawContent + s->contentOffset;
+                    if (-1 == (skipLen = drm_skipCRLFinB64(pStart, encLen))) {
+                        freeSession(s);
+                        return DRM_FAILURE;
+                    }
+
+                    needBytes = DRM_B64_ENC_BLOCK - ((encLen - skipLen) % DRM_B64_ENC_BLOCK);
+                    if (needBytes < DRM_B64_ENC_BLOCK) {
+                        s->rawContent = (uint8_t *)realloc(s->rawContent, DRM_MAX_MALLOC_LEN + needBytes);
+                        if (NULL == s->rawContent) {
+                            freeSession(s);
+                            return DRM_FAILURE;
+                        }
+
+                        i = 0;
+                        while (i < needBytes) {
+                            if (-1 != data.readInputData(data.inputHandle, s->rawContent + DRM_MAX_MALLOC_LEN + i, 1)) {
+                                if ('\r' == *(s->rawContent + DRM_MAX_MALLOC_LEN + i) || '\n' == *(s->rawContent + DRM_MAX_MALLOC_LEN + i))
+                                    continue;
+                                i++;
+                            } else
+                                break;
+                        }
+                        encLen += i;
+                    }
+
+                    res = drm_scanEndBoundary(pStart, encLen, ((T_DRM_DM_Base64_Node *)(s->infoStruct))->boundary);
+                    if (-1 == res) {
+                        freeSession(s);
+                        return DRM_FAILURE;
+                    }
+                    if (-2 == res) { /* may be there is a boundary */
+                        int32_t boundaryLen, leftLen, readBytes;
+                        char* pTmp = memrchr(pStart, '\r', encLen);
+
+                        if (NULL == pTmp) {
+                            freeSession(s);
+                            return DRM_FAILURE; /* conflict */
+                        }
+                        boundaryLen = strlen((char *)((T_DRM_DM_Base64_Node *)(s->infoStruct))->boundary) + 2; /* 2 means: '\r''\n' */
+                        s->readBuf = (uint8_t *)malloc(boundaryLen);
+                        if (NULL == s->readBuf) {
+                            freeSession(s);
+                            return DRM_FAILURE;
+                        }
+                        s->readBufOff = encLen - ((uint8_t *)pTmp - pStart);
+                        s->readBufLen = boundaryLen - s->readBufOff;
+                        memcpy(s->readBuf, pTmp, s->readBufOff);
+                        readBytes = data.readInputData(data.inputHandle, s->readBuf + s->readBufOff, s->readBufLen);
+                        if (-1 == readBytes || readBytes < s->readBufLen) {
+                            freeSession(s);
+                            return DRM_MEDIA_DATA_INVALID;
+                        }
+
+                        if (0 == drm_scanEndBoundary(s->readBuf, boundaryLen, ((T_DRM_DM_Base64_Node *)(s->infoStruct))->boundary)) {
+                            encLen = (uint8_t *)pTmp - pStart; /* yes, it is the end boundary */
+                            bFoundBoundary = TRUE;
+                        }
+                    } else {
+                        if (res >= 0 && res < encLen) {
+                            encLen = res;
+                            bFoundBoundary = TRUE;
+                        }
+                    }
+
+                    decLen = encLen / DRM_B64_ENC_BLOCK * DRM_B64_DEC_BLOCK;
+                    decLen = drm_decodeBase64(s->rawContent, decLen, s->rawContent + s->contentOffset, &encLen);
+                    ((T_DRM_DM_Base64_Node *)(s->infoStruct))->b64DecodeDataLen = decLen;
+                    if (bFoundBoundary)
+                        s->contentLength = decLen;
+                }
+            } else {
+                /* binary data */
+                if (DRM_UNKNOWN_DATA_LEN == s->contentLength) {
+                    /* try to check whether there is boundary may be split */
+                    int32_t res, binContentLen;
+                    uint8_t* pStart;
+                    int32_t bFoundBoundary = FALSE;
+
+                    pStart = s->rawContent + s->contentOffset;
+                    binContentLen = s->rawContentLen - s->contentOffset;
+                    res = drm_scanEndBoundary(pStart, binContentLen, ((T_DRM_DM_Binary_Node *)(s->infoStruct))->boundary);
+
+                    if (-1 == res) {
+                        freeSession(s);
+                        return DRM_FAILURE;
+                    }
+
+                    if (-2 == res) { /* may be the boundary is split */
+                        int32_t boundaryLen, leftLen, readBytes;
+                        char* pTmp = memrchr(pStart, '\r', binContentLen);
+
+                        if (NULL == pTmp) {
+                            freeSession(s);
+                            return DRM_FAILURE; /* conflict */
+                        }
+
+                        boundaryLen = strlen((char *)((T_DRM_DM_Binary_Node *)(s->infoStruct))->boundary) + 2; /* 2 means: '\r''\n' */
+                        s->readBuf = (uint8_t *)malloc(boundaryLen);
+                        if (NULL == s->readBuf) {
+                            freeSession(s);
+                            return DRM_FAILURE;
+                        }
+                        s->readBufOff = binContentLen - ((uint8_t *)pTmp - pStart);
+                        s->readBufLen = boundaryLen - s->readBufOff;
+                        memcpy(s->readBuf, pTmp, s->readBufOff);
+                        readBytes = data.readInputData(data.inputHandle, s->readBuf + s->readBufOff, s->readBufLen);
+                        if (-1 == readBytes || readBytes < s->readBufLen) {
+                            freeSession(s);
+                            return DRM_MEDIA_DATA_INVALID;
+                        }
+
+                        if (0 == drm_scanEndBoundary(s->readBuf, boundaryLen, ((T_DRM_DM_Binary_Node *)(s->infoStruct))->boundary)) {
+                            binContentLen = (uint8_t *)pTmp - pStart; /* yes, it is the end boundary */
+                            bFoundBoundary = TRUE;
+                        }
+                    } else {
+                        if (res >= 0 && res < binContentLen) {
+                            binContentLen = res;
+                            bFoundBoundary = TRUE;
+                        }
+                    }
+
+                    if (bFoundBoundary)
+                        s->contentLength = binContentLen;
+                }
+            }
+        }
+        break;
+    case TYPE_DRM_CONTENT:
+        {
+            T_DRM_DCF_Info dcfInfo;
+            uint8_t* pEncData = NULL;
+
+            memset(&dcfInfo, 0, sizeof(T_DRM_DCF_Info));
+            if (FALSE == drm_dcfParser(s->rawContent, s->rawContentLen, &dcfInfo, &pEncData)) {
+                freeSession(s);
+                return DRM_MEDIA_DATA_INVALID;
+            }
+
+            s->infoStruct = (T_DRM_Dcf_Node *)malloc(sizeof(T_DRM_Dcf_Node));
+            if (NULL == s->infoStruct)
+                return DRM_FAILURE;
+            memset(s->infoStruct, 0, sizeof(T_DRM_Dcf_Node));
+
+            s->deliveryMethod = SEPARATE_DELIVERY;
+            s->contentLength = dcfInfo.DecryptedDataLen;
+            ((T_DRM_Dcf_Node *)(s->infoStruct))->encContentLength = dcfInfo.EncryptedDataLen;
+            s->contentOffset = pEncData - s->rawContent;
+            strcpy((char *)s->contentType, (char *)dcfInfo.ContentType);
+            strcpy((char *)s->contentID, (char *)dcfInfo.ContentURI);
+            strcpy((char *)((T_DRM_Dcf_Node *)(s->infoStruct))->rightsIssuer, (char *)dcfInfo.Rights_Issuer);
+        }
+        break;
+    case TYPE_DRM_RIGHTS_XML:   /* rights object should using "SVC_drm_installRights", it can not open a session */
+    case TYPE_DRM_RIGHTS_WBXML: /* rights object should using "SVC_drm_installRights", it can not open a session */
+    case TYPE_DRM_UNKNOWN:
+    default:
+        freeSession(s);
+        return DRM_MEDIA_DATA_INVALID;
+    }
+
+    if ((SEPARATE_DELIVERY_FL == s->deliveryMethod || SEPARATE_DELIVERY == s->deliveryMethod) &&
+        s->contentOffset + ((T_DRM_Dcf_Node *)(s->infoStruct))->encContentLength <= DRM_MAX_MALLOC_LEN) {
+        uint8_t keyValue[DRM_KEY_LEN];
+        uint8_t lastDcfBuf[DRM_TWO_AES_BLOCK_LEN];
+        int32_t seekPos, moreBytes;
+
+        if (TRUE == drm_getKey(s->contentID, keyValue)) {
+            seekPos = s->contentOffset + ((T_DRM_Dcf_Node *)(s->infoStruct))->encContentLength - DRM_TWO_AES_BLOCK_LEN;
+            memcpy(lastDcfBuf, s->rawContent + seekPos, DRM_TWO_AES_BLOCK_LEN);
+
+            if (TRUE == drm_updateDcfDataLen(lastDcfBuf, keyValue, &moreBytes)) {
+                s->contentLength = ((T_DRM_Dcf_Node *)(s->infoStruct))->encContentLength;
+                s->contentLength -= moreBytes;
+            }
+        }
+    }
+
+    session = addSession(s);
+    if (-1 == session)
+        return DRM_FAILURE;
+
+    return session;
+}
+
+/* see svc_drm.h */
+int32_t SVC_drm_getDeliveryMethod(int32_t session)
+{
+    T_DRM_Session_Node* s;
+
+    if (session < 0)
+        return DRM_FAILURE;
+
+    s = getSession(session);
+    if (NULL == s)
+        return DRM_SESSION_NOT_OPENED;
+
+    return s->deliveryMethod;
+}
+
+/* see svc_drm.h */
+int32_t SVC_drm_getContentType(int32_t session, uint8_t* mediaType)
+{
+    T_DRM_Session_Node* s;
+
+    if (session < 0 || NULL == mediaType)
+        return DRM_FAILURE;
+
+    s = getSession(session);
+    if (NULL == s)
+        return DRM_SESSION_NOT_OPENED;
+
+    strcpy((char *)mediaType, (char *)s->contentType);
+
+    return DRM_SUCCESS;
+}
+
+/* see svc_drm.h */
+int32_t SVC_drm_checkRights(int32_t session, int32_t permission)
+{
+    T_DRM_Session_Node* s;
+    int32_t id;
+    T_DRM_Rights *pRo, *pCurRo;
+    int32_t roAmount;
+    int32_t i;
+    int32_t res = DRM_FAILURE;
+
+    if (session < 0)
+        return DRM_FAILURE;
+
+    s = getSession(session);
+    if (NULL == s)
+        return DRM_SESSION_NOT_OPENED;
+
+    /* if it is Forward-Lock cases, check it and return directly */
+    if (FORWARD_LOCK == s->deliveryMethod) {
+        if (DRM_PERMISSION_PLAY == permission ||
+            DRM_PERMISSION_DISPLAY == permission ||
+            DRM_PERMISSION_EXECUTE == permission ||
+            DRM_PERMISSION_PRINT == permission)
+            return DRM_SUCCESS;
+
+        return DRM_FAILURE;
+    }
+
+    /* if try to forward, only DCF can be forwarded */
+    if (DRM_PERMISSION_FORWARD == permission) {
+        if (SEPARATE_DELIVERY == s->deliveryMethod)
+            return DRM_SUCCESS;
+
+        return DRM_FAILURE;
+    }
+
+    /* The following will check CD or SD other permissions */
+    if (FALSE == drm_readFromUidTxt(s->contentID, &id, GET_ID))
+        return DRM_FAILURE;
+
+    drm_writeOrReadInfo(id, NULL, &roAmount, GET_ROAMOUNT);
+    if (roAmount <= 0)
+        return DRM_FAILURE;
+
+    pRo = malloc(roAmount * sizeof(T_DRM_Rights));
+    if (NULL == pRo)
+        return DRM_FAILURE;
+
+    drm_writeOrReadInfo(id, pRo, &roAmount, GET_ALL_RO);
+
+    pCurRo = pRo;
+    for (i = 0; i < roAmount; i++) {
+        switch (permission) {
+        case DRM_PERMISSION_PLAY:
+            res = drm_startCheckRights(&(pCurRo->bIsPlayable), &(pCurRo->PlayConstraint));
+            break;
+        case DRM_PERMISSION_DISPLAY:
+            res = drm_startCheckRights(&(pCurRo->bIsDisplayable), &(pCurRo->DisplayConstraint));
+            break;
+        case DRM_PERMISSION_EXECUTE:
+            res = drm_startCheckRights(&(pCurRo->bIsExecuteable), &(pCurRo->ExecuteConstraint));
+            break;
+        case DRM_PERMISSION_PRINT:
+            res = drm_startCheckRights(&(pCurRo->bIsPrintable), &(pCurRo->PrintConstraint));
+            break;
+        default:
+            free(pRo);
+            return DRM_FAILURE;
+        }
+
+        if (DRM_SUCCESS == res) {
+            free(pRo);
+            return DRM_SUCCESS;
+        }
+        pCurRo++;
+    }
+
+    free(pRo);
+    return res;
+}
+
+/* see svc_drm.h */
+int32_t SVC_drm_consumeRights(int32_t session, int32_t permission)
+{
+    T_DRM_Session_Node* s;
+    int32_t id;
+
+    if (session < 0)
+        return DRM_FAILURE;
+
+    s = getSession(session);
+    if (NULL == s)
+        return DRM_SESSION_NOT_OPENED;
+
+    if (DRM_PERMISSION_FORWARD == permission) {
+        if (SEPARATE_DELIVERY == s->deliveryMethod)
+            return DRM_SUCCESS;
+
+        return DRM_FAILURE;
+    }
+
+    if (FORWARD_LOCK == s->deliveryMethod) /* Forwardlock type have utter rights */
+        return DRM_SUCCESS;
+
+    if (FALSE == drm_readFromUidTxt(s->contentID, &id, GET_ID))
+        return DRM_FAILURE;
+
+    return drm_checkRoAndUpdate(id, permission);
+}
+
+/* see svc_drm.h */
+int32_t SVC_drm_getContentLength(int32_t session)
+{
+    T_DRM_Session_Node* s;
+
+    if (session < 0)
+        return DRM_FAILURE;
+
+    s = getSession(session);
+    if (NULL == s)
+        return DRM_SESSION_NOT_OPENED;
+
+    if (DRM_UNKNOWN_DATA_LEN == s->contentLength && s->contentOffset + ((T_DRM_Dcf_Node *)(s->infoStruct))->encContentLength <= DRM_MAX_MALLOC_LEN &&
+        (SEPARATE_DELIVERY == s->deliveryMethod || SEPARATE_DELIVERY_FL == s->deliveryMethod)) {
+        uint8_t keyValue[DRM_KEY_LEN];
+        uint8_t lastDcfBuf[DRM_TWO_AES_BLOCK_LEN];
+        int32_t seekPos, moreBytes;
+
+        if (TRUE == drm_getKey(s->contentID, keyValue)) {
+            seekPos = s->contentOffset + ((T_DRM_Dcf_Node *)(s->infoStruct))->encContentLength - DRM_TWO_AES_BLOCK_LEN;
+            memcpy(lastDcfBuf, s->rawContent + seekPos, DRM_TWO_AES_BLOCK_LEN);
+
+            if (TRUE == drm_updateDcfDataLen(lastDcfBuf, keyValue, &moreBytes)) {
+                s->contentLength = ((T_DRM_Dcf_Node *)(s->infoStruct))->encContentLength;
+                s->contentLength -= moreBytes;
+            }
+        }
+    }
+
+    return s->contentLength;
+}
+
+static int32_t drm_readAesData(uint8_t* buf, T_DRM_Session_Node* s, int32_t aesStart, int32_t bufLen)
+{
+    if (NULL == buf || NULL == s || aesStart < 0 || bufLen < 0)
+        return -1;
+
+    if (aesStart - s->contentOffset + bufLen > ((T_DRM_Dcf_Node *)(s->infoStruct))->encContentLength)
+        return -2;
+
+    if (aesStart < DRM_MAX_MALLOC_LEN) {
+        if (aesStart + bufLen <= DRM_MAX_MALLOC_LEN) { /* read from buffer */
+            memcpy(buf, s->rawContent + aesStart, bufLen);
+            return bufLen;
+        } else { /* first read from buffer and then from InputStream */
+            int32_t point = DRM_MAX_MALLOC_LEN - aesStart;
+            int32_t res;
+
+            if (((T_DRM_Dcf_Node *)(s->infoStruct))->bAesBackupBuf) {
+                memcpy(buf, ((T_DRM_Dcf_Node *)(s->infoStruct))->aesBackupBuf, DRM_ONE_AES_BLOCK_LEN);
+                res = s->readInputDataFunc(s->inputHandle, buf + DRM_ONE_AES_BLOCK_LEN, DRM_ONE_AES_BLOCK_LEN);
+                if (0 == res || -1 == res)
+                    return -1;
+
+                res += DRM_ONE_AES_BLOCK_LEN;
+            } else {
+                memcpy(buf, s->rawContent + aesStart, point);
+                res = s->readInputDataFunc(s->inputHandle, buf + point, bufLen - point);
+                if (0 == res || -1 == res)
+                    return -1;
+
+                res += point;
+            }
+
+            memcpy(((T_DRM_Dcf_Node *)(s->infoStruct))->aesBackupBuf, buf + DRM_ONE_AES_BLOCK_LEN, DRM_ONE_AES_BLOCK_LEN);
+            ((T_DRM_Dcf_Node *)(s->infoStruct))->bAesBackupBuf = TRUE;
+
+            return res;
+        }
+    } else { /* read from InputStream */
+        int32_t res;
+
+        memcpy(buf, ((T_DRM_Dcf_Node *)(s->infoStruct))->aesBackupBuf, DRM_ONE_AES_BLOCK_LEN);
+        res = s->readInputDataFunc(s->inputHandle, buf + DRM_ONE_AES_BLOCK_LEN, DRM_ONE_AES_BLOCK_LEN);
+
+        if (0 == res || -1 == res)
+            return -1;
+
+        memcpy(((T_DRM_Dcf_Node *)(s->infoStruct))->aesBackupBuf, buf + DRM_ONE_AES_BLOCK_LEN, DRM_ONE_AES_BLOCK_LEN);
+
+        return DRM_ONE_AES_BLOCK_LEN + res;
+    }
+}
+
+static int32_t drm_readContentFromBuf(T_DRM_Session_Node* s, int32_t offset, uint8_t* mediaBuf, int32_t mediaBufLen)
+{
+    int32_t readBytes;
+
+    if (offset > s->contentLength)
+        return DRM_FAILURE;
+
+    if (offset == s->contentLength)
+        return DRM_MEDIA_EOF;
+
+    if (offset + mediaBufLen > s->contentLength)
+        readBytes = s->contentLength - offset;
+    else
+        readBytes = mediaBufLen;
+
+    if (DRM_MESSAGE_CODING_BASE64 == s->transferEncoding)
+        memcpy(mediaBuf, s->rawContent + offset, readBytes);
+    else
+        memcpy(mediaBuf, s->rawContent + s->contentOffset + offset, readBytes);
+
+    return readBytes;
+}
+
+static int32_t drm_readB64ContentFromInputStream(T_DRM_Session_Node* s, int32_t offset, uint8_t* mediaBuf, int32_t mediaBufLen)
+{
+    uint8_t encBuf[DRM_B64_ENC_BLOCK], decBuf[DRM_B64_DEC_BLOCK];
+    int32_t encLen, decLen;
+    int32_t i, j, piece, leftLen, firstBytes;
+    int32_t readBytes = 0;
+
+    if (offset < ((T_DRM_DM_Base64_Node *)(s->infoStruct))->b64DecodeDataLen) {
+        readBytes = ((T_DRM_DM_Base64_Node *)(s->infoStruct))->b64DecodeDataLen - offset;
+        memcpy(mediaBuf, s->rawContent + offset, readBytes);
+    } else {
+        if (s->bEndData)
+            return DRM_MEDIA_EOF;
+
+        firstBytes = offset % DRM_B64_DEC_BLOCK;
+        if (firstBytes > 0) {
+            if (DRM_B64_DEC_BLOCK - firstBytes >= mediaBufLen) {
+                readBytes = mediaBufLen;
+                memcpy(mediaBuf, ((T_DRM_DM_Base64_Node *)(s->infoStruct))->b64DecodeData + firstBytes, readBytes);
+                return readBytes;
+            }
+
+            readBytes = DRM_B64_DEC_BLOCK - firstBytes;
+            memcpy(mediaBuf, ((T_DRM_DM_Base64_Node *)(s->infoStruct))->b64DecodeData + firstBytes, readBytes);
+        }
+    }
+
+    leftLen = mediaBufLen - readBytes;
+    encLen = (leftLen - 1) / DRM_B64_DEC_BLOCK * DRM_B64_ENC_BLOCK + DRM_B64_ENC_BLOCK;
+    piece = encLen / DRM_B64_ENC_BLOCK;
+
+    for (i = 0; i < piece; i++) {
+        j = 0;
+        while (j < DRM_B64_ENC_BLOCK) {
+            if (NULL != s->readBuf && s->readBufLen > 0) { /* read from backup buffer */
+                *(encBuf + j) = s->readBuf[s->readBufOff];
+                s->readBufOff++;
+                s->readBufLen--;
+            } else { /* read from InputStream */
+                if (0 == s->readInputDataFunc(s->inputHandle, encBuf + j, 1))
+                    return DRM_MEDIA_DATA_INVALID;
+            }
+
+            if ('\r' == *(encBuf + j) || '\n' == *(encBuf + j))
+                continue; /* skip CRLF */
+
+            if ('-' == *(encBuf + j)) {
+                int32_t k, len;
+
+                /* invalid base64 data, it comes to end boundary */
+                if (0 != j)
+                    return DRM_MEDIA_DATA_INVALID;
+
+                /* check whether it is really the boundary */
+                len = strlen((char *)((T_DRM_DM_Base64_Node *)(s->infoStruct))->boundary);
+                if (NULL == s->readBuf) {
+                    s->readBuf = (uint8_t *)malloc(len);
+                    if (NULL == s->readBuf)
+                        return DRM_FAILURE;
+                }
+
+                s->readBuf[0] = '-';
+                for (k = 0; k < len - 1; k++) {
+                    if (NULL != s->readBuf && s->readBufLen > 0) { /* read from backup buffer */
+                        *(s->readBuf + k + 1) = s->readBuf[s->readBufOff];
+                        s->readBufOff++;
+                        s->readBufLen--;
+                    } else { /* read from InputStream */
+                        if (-1 == s->readInputDataFunc(s->inputHandle, s->readBuf + k + 1, 1))
+                            return DRM_MEDIA_DATA_INVALID;
+                    }
+                }
+                if (0 == memcmp(s->readBuf, ((T_DRM_DM_Base64_Node *)(s->infoStruct))->boundary, len))
+                    s->bEndData = TRUE;
+                else
+                    return DRM_MEDIA_DATA_INVALID;
+
+                break;
+            }
+            j++;
+        }
+
+        if (TRUE == s->bEndData) { /* it means come to the end of base64 data */
+            if (0 == readBytes)
+                return DRM_MEDIA_EOF;
+
+            break;
+        }
+
+        encLen = DRM_B64_ENC_BLOCK;
+        decLen = DRM_B64_DEC_BLOCK;
+        if (-1 == (decLen = drm_decodeBase64(decBuf, decLen, encBuf, &encLen)))
+            return DRM_MEDIA_DATA_INVALID;
+
+        if (leftLen >= decLen) {
+            memcpy(mediaBuf + readBytes, decBuf, decLen);
+            readBytes += decLen;
+            leftLen -= decLen;
+        } else {
+            if (leftLen > 0) {
+                memcpy(mediaBuf + readBytes, decBuf, leftLen);
+                readBytes += leftLen;
+            }
+            break;
+        }
+    }
+    memcpy(((T_DRM_DM_Base64_Node *)(s->infoStruct))->b64DecodeData, decBuf, DRM_B64_DEC_BLOCK);
+
+    return readBytes;
+}
+
+static int32_t drm_readBase64Content(T_DRM_Session_Node* s, int32_t offset, uint8_t* mediaBuf, int32_t mediaBufLen)
+{
+    int32_t readBytes;
+
+    /* when the content length has been well-known */
+    if (s->contentLength >= 0)
+        readBytes = drm_readContentFromBuf(s, offset, mediaBuf, mediaBufLen);
+    else /* else when the content length has not been well-known yet */
+        if (offset < ((T_DRM_DM_Base64_Node *)(s->infoStruct))->b64DecodeDataLen)
+            if (offset + mediaBufLen <= ((T_DRM_DM_Base64_Node *)(s->infoStruct))->b64DecodeDataLen) {
+                readBytes = mediaBufLen;
+                memcpy(mediaBuf, s->rawContent + offset, readBytes);
+            } else
+                readBytes = drm_readB64ContentFromInputStream(s, offset, mediaBuf, mediaBufLen);
+        else
+            readBytes = drm_readB64ContentFromInputStream(s, offset, mediaBuf, mediaBufLen);
+
+    return readBytes;
+}
+
+static int32_t drm_readBinaryContentFromInputStream(T_DRM_Session_Node* s, int32_t offset, uint8_t* mediaBuf, int32_t mediaBufLen)
+{
+    int32_t res = 0, readBytes = 0;
+    int32_t leftLen;
+
+    if (s->contentOffset + offset < DRM_MAX_MALLOC_LEN) {
+        readBytes = DRM_MAX_MALLOC_LEN - s->contentOffset - offset;
+        memcpy(mediaBuf, s->rawContent + s->contentOffset + offset, readBytes);
+    } else
+        if (s->bEndData)
+            return DRM_MEDIA_EOF;
+
+    leftLen = mediaBufLen - readBytes;
+
+    if (NULL != s->readBuf && s->readBufLen > 0) { /* read from backup buffer */
+        if (leftLen <= s->readBufLen) {
+            memcpy(mediaBuf, s->readBuf + s->readBufOff, leftLen);
+            s->readBufOff += leftLen;
+            s->readBufLen -= leftLen;
+            readBytes += leftLen;
+            leftLen = 0;
+        } else {
+            memcpy(mediaBuf, s->readBuf + s->readBufOff, s->readBufLen);
+            s->readBufOff += s->readBufLen;
+            leftLen -= s->readBufLen;
+            readBytes += s->readBufLen;
+            s->readBufLen = 0;
+        }
+    }
+
+    if (leftLen > 0) {
+        res = s->readInputDataFunc(s->inputHandle, mediaBuf + readBytes, mediaBufLen - readBytes);
+        if (-1 == res)
+            return DRM_MEDIA_DATA_INVALID;
+    }
+
+    readBytes += res;
+    res = drm_scanEndBoundary(mediaBuf, readBytes, ((T_DRM_DM_Binary_Node *)(s->infoStruct))->boundary);
+    if (-1 == res)
+        return DRM_MEDIA_DATA_INVALID;
+    if (-2 == res) { /* may be the boundary is split */
+        int32_t boundaryLen, len, off, k;
+        char* pTmp = memrchr(mediaBuf, '\r', readBytes);
+
+        if (NULL == pTmp)
+            return DRM_FAILURE; /* conflict */
+
+        boundaryLen = strlen((char *)((T_DRM_DM_Binary_Node *)(s->infoStruct))->boundary) + 2; /* 2 means: '\r''\n' */
+        if (NULL == s->readBuf) {
+            s->readBuf = (uint8_t *)malloc(boundaryLen);
+            if (NULL == s->readBuf)
+                return DRM_FAILURE;
+        }
+
+        off = readBytes - ((uint8_t *)pTmp - mediaBuf);
+        len = boundaryLen - off;
+        memcpy(s->readBuf, pTmp, off);
+        for (k = 0; k < boundaryLen - off; k++) {
+            if (NULL != s->readBuf && s->readBufLen > 0) { /* read from backup buffer */
+                *(s->readBuf + k + off) = s->readBuf[s->readBufOff];
+                s->readBufOff++;
+                s->readBufLen--;
+            } else { /* read from InputStream */
+                if (-1 == s->readInputDataFunc(s->inputHandle, s->readBuf + k + off, 1))
+                    return DRM_MEDIA_DATA_INVALID;
+            }
+        }
+        s->readBufOff = off;
+        s->readBufLen = len;
+
+        if (0 == drm_scanEndBoundary(s->readBuf, boundaryLen, ((T_DRM_DM_Binary_Node *)(s->infoStruct))->boundary)) {
+            readBytes = (uint8_t *)pTmp - mediaBuf; /* yes, it is the end boundary */
+            s->bEndData = TRUE;
+        }
+    } else {
+        if (res >= 0 && res < readBytes) {
+            readBytes = res;
+            s->bEndData = TRUE;
+        }
+    }
+
+    if (s->bEndData) {
+        if (0 == readBytes)
+            return DRM_MEDIA_EOF;
+    }
+
+    return readBytes;
+}
+
+static int32_t drm_readBinaryContent(T_DRM_Session_Node* s, int32_t offset, uint8_t* mediaBuf, int32_t mediaBufLen)
+{
+    int32_t readBytes;
+
+    if (s->contentLength >= 0)
+        readBytes = drm_readContentFromBuf(s, offset, mediaBuf, mediaBufLen);
+    else /* else when the content length has not been well-known yet */
+        if (s->contentOffset + offset < DRM_MAX_MALLOC_LEN)
+            if (s->contentOffset + offset + mediaBufLen <= DRM_MAX_MALLOC_LEN) {
+                readBytes = mediaBufLen;
+                memcpy(mediaBuf, s->rawContent + s->contentOffset + offset, readBytes);
+            } else
+                readBytes = drm_readBinaryContentFromInputStream(s, offset, mediaBuf, mediaBufLen);
+        else
+            readBytes = drm_readBinaryContentFromInputStream(s, offset, mediaBuf, mediaBufLen);
+
+    return readBytes;
+}
+
+static int32_t drm_readAesContent(T_DRM_Session_Node* s, int32_t offset, uint8_t* mediaBuf, int32_t mediaBufLen)
+{
+    uint8_t keyValue[DRM_KEY_LEN];
+    uint8_t buf[DRM_TWO_AES_BLOCK_LEN];
+    int32_t readBytes = 0;
+    int32_t bufLen, piece, i, copyBytes, leftBytes;
+    int32_t aesStart, mediaStart, mediaBufOff;
+    aes_decrypt_ctx ctx[1];
+
+    if (FALSE == drm_getKey(s->contentID, keyValue))
+        return DRM_NO_RIGHTS;
+
+    /* when the content length has been well-known */
+    if (s->contentLength > 0) {
+        if (offset > s->contentLength)
+            return DRM_FAILURE;
+
+        if (offset == s->contentLength)
+            return DRM_MEDIA_EOF;
+
+        if (offset + mediaBufLen > s->contentLength)
+            readBytes = s->contentLength - offset;
+        else
+            readBytes = mediaBufLen;
+
+        aesStart = s->contentOffset + (offset / DRM_ONE_AES_BLOCK_LEN * DRM_ONE_AES_BLOCK_LEN);
+        piece = (offset + readBytes - 1) / DRM_ONE_AES_BLOCK_LEN - offset / DRM_ONE_AES_BLOCK_LEN + 2;
+        mediaStart = offset % DRM_ONE_AES_BLOCK_LEN;
+
+        aes_decrypt_key128(keyValue, ctx);
+        mediaBufOff = 0;
+        leftBytes = readBytes;
+
+        for (i = 0; i < piece - 1; i++) {
+            memcpy(buf, s->rawContent + aesStart + i * DRM_ONE_AES_BLOCK_LEN, DRM_TWO_AES_BLOCK_LEN);
+            bufLen = DRM_TWO_AES_BLOCK_LEN;
+
+            if (drm_aesDecBuffer(buf, &bufLen, ctx) < 0)
+                return DRM_MEDIA_DATA_INVALID;
+
+            if (0 != i)
+                mediaStart = 0;
+
+            if (bufLen - mediaStart <= leftBytes)
+                copyBytes = bufLen - mediaStart;
+            else
+                copyBytes = leftBytes;
+
+            memcpy(mediaBuf + mediaBufOff, buf + mediaStart, copyBytes);
+            leftBytes -= copyBytes;
+            mediaBufOff += copyBytes;
+        }
+    } else {
+        int32_t res;
+
+        if (s->bEndData)
+            return DRM_MEDIA_EOF;
+
+        if (((T_DRM_Dcf_Node *)(s->infoStruct))->aesDecDataLen > ((T_DRM_Dcf_Node *)(s->infoStruct))->aesDecDataOff) {
+            if (mediaBufLen < ((T_DRM_Dcf_Node *)(s->infoStruct))->aesDecDataLen - ((T_DRM_Dcf_Node *)(s->infoStruct))->aesDecDataOff)
+                copyBytes = mediaBufLen;
+            else
+                copyBytes = ((T_DRM_Dcf_Node *)(s->infoStruct))->aesDecDataLen - ((T_DRM_Dcf_Node *)(s->infoStruct))->aesDecDataOff;
+
+            memcpy(mediaBuf, ((T_DRM_Dcf_Node *)(s->infoStruct))->aesDecData + ((T_DRM_Dcf_Node *)(s->infoStruct))->aesDecDataOff, copyBytes);
+            ((T_DRM_Dcf_Node *)(s->infoStruct))->aesDecDataOff += copyBytes;
+            readBytes += copyBytes;
+        }
+
+        leftBytes = mediaBufLen - readBytes;
+        if (0 == leftBytes)
+            return readBytes;
+        if (leftBytes < 0)
+            return DRM_FAILURE;
+
+        offset += readBytes;
+        aesStart = s->contentOffset + (offset / DRM_ONE_AES_BLOCK_LEN * DRM_ONE_AES_BLOCK_LEN);
+        piece = (offset + leftBytes - 1) / DRM_ONE_AES_BLOCK_LEN - offset / DRM_ONE_AES_BLOCK_LEN + 2;
+        mediaBufOff = readBytes;
+
+        aes_decrypt_key128(keyValue, ctx);
+
+        for (i = 0; i < piece - 1; i++) {
+            if (-1 == (res = drm_readAesData(buf, s, aesStart, DRM_TWO_AES_BLOCK_LEN)))
+                return DRM_MEDIA_DATA_INVALID;
+
+            if (-2 == res)
+                break;
+
+            bufLen = DRM_TWO_AES_BLOCK_LEN;
+            aesStart += DRM_ONE_AES_BLOCK_LEN;
+
+            if (drm_aesDecBuffer(buf, &bufLen, ctx) < 0)
+                return DRM_MEDIA_DATA_INVALID;
+
+            drm_discardPaddingByte(buf, &bufLen);
+
+            if (bufLen <= leftBytes)
+                copyBytes = bufLen;
+            else
+                copyBytes = leftBytes;
+
+            memcpy(mediaBuf + mediaBufOff, buf, copyBytes);
+            leftBytes -= copyBytes;
+            mediaBufOff += copyBytes;
+            readBytes += copyBytes;
+        }
+
+        memcpy(((T_DRM_Dcf_Node *)(s->infoStruct))->aesDecData, buf, DRM_ONE_AES_BLOCK_LEN);
+        ((T_DRM_Dcf_Node *)(s->infoStruct))->aesDecDataLen = bufLen;
+        ((T_DRM_Dcf_Node *)(s->infoStruct))->aesDecDataOff = copyBytes;
+
+        if (aesStart - s->contentOffset > ((T_DRM_Dcf_Node *)(s->infoStruct))->encContentLength - DRM_TWO_AES_BLOCK_LEN && ((T_DRM_Dcf_Node *)(s->infoStruct))->aesDecDataOff == ((T_DRM_Dcf_Node *)(s->infoStruct))->aesDecDataLen) {
+            s->bEndData = TRUE;
+            if (0 == readBytes)
+                return DRM_MEDIA_EOF;
+        }
+    }
+
+    return readBytes;
+}
+
+/* see svc_drm.h */
+int32_t SVC_drm_getContent(int32_t session, int32_t offset, uint8_t* mediaBuf, int32_t mediaBufLen)
+{
+    T_DRM_Session_Node* s;
+    int32_t readBytes;
+
+    if (session < 0 || offset < 0 || NULL == mediaBuf || mediaBufLen <= 0)
+        return DRM_FAILURE;
+
+    s = getSession(session);
+    if (NULL == s)
+        return DRM_SESSION_NOT_OPENED;
+
+    if (0 >= s->getInputDataLengthFunc(s->inputHandle))
+        return DRM_MEDIA_DATA_INVALID;
+
+    switch(s->deliveryMethod) {
+    case FORWARD_LOCK:
+    case COMBINED_DELIVERY:
+        if (DRM_MESSAGE_CODING_BASE64 == s->transferEncoding)
+            readBytes = drm_readBase64Content(s, offset, mediaBuf, mediaBufLen);
+        else /* binary */
+            readBytes = drm_readBinaryContent(s, offset, mediaBuf, mediaBufLen);
+        break;
+    case SEPARATE_DELIVERY:
+    case SEPARATE_DELIVERY_FL:
+        readBytes = drm_readAesContent(s, offset, mediaBuf, mediaBufLen);
+        break;
+    default:
+        return DRM_FAILURE;
+    }
+
+    return readBytes;
+}
+
+/* see svc_drm.h */
+int32_t SVC_drm_getRightsIssuer(int32_t session, uint8_t* rightsIssuer)
+{
+    T_DRM_Session_Node* s;
+
+    if (session < 0 || NULL == rightsIssuer)
+        return DRM_FAILURE;
+
+    s = getSession(session);
+    if (NULL == s)
+        return DRM_SESSION_NOT_OPENED;
+
+    if (SEPARATE_DELIVERY == s->deliveryMethod || SEPARATE_DELIVERY_FL == s->deliveryMethod) {
+        strcpy((char *)rightsIssuer, (char *)((T_DRM_Dcf_Node *)(s->infoStruct))->rightsIssuer);
+        return DRM_SUCCESS;
+    }
+
+    return DRM_NOT_SD_METHOD;
+}
+
+/* see svc_drm.h */
+int32_t SVC_drm_getRightsInfo(int32_t session, T_DRM_Rights_Info* rights)
+{
+    T_DRM_Session_Node* s;
+    T_DRM_Rights rightsInfo;
+    int32_t roAmount, id;
+
+    if (session < 0 || NULL == rights)
+        return DRM_FAILURE;
+
+    s = getSession(session);
+    if (NULL == s)
+        return DRM_SESSION_NOT_OPENED;
+
+    if (FORWARD_LOCK == s->deliveryMethod) {
+        strcpy((char *)rights->roId, "ForwardLock");
+        rights->displayRights.indicator = DRM_NO_CONSTRAINT;
+        rights->playRights.indicator = DRM_NO_CONSTRAINT;
+        rights->executeRights.indicator = DRM_NO_CONSTRAINT;
+        rights->printRights.indicator = DRM_NO_CONSTRAINT;
+        return DRM_SUCCESS;
+    }
+
+    if (FALSE == drm_readFromUidTxt(s->contentID, &id, GET_ID))
+        return DRM_NO_RIGHTS;
+
+    if (FALSE == drm_writeOrReadInfo(id, NULL, &roAmount, GET_ROAMOUNT))
+        return DRM_FAILURE;
+
+    if (roAmount < 0)
+        return DRM_NO_RIGHTS;
+
+    /* some rights has been installed, but now there is no valid rights */
+    if (0 == roAmount) {
+        strcpy((char *)rights->roId, s->contentID);
+        rights->displayRights.indicator = DRM_NO_PERMISSION;
+        rights->playRights.indicator = DRM_NO_PERMISSION;
+        rights->executeRights.indicator = DRM_NO_PERMISSION;
+        rights->printRights.indicator = DRM_NO_PERMISSION;
+        return DRM_SUCCESS;
+    }
+
+    roAmount = 1;
+    memset(&rightsInfo, 0, sizeof(T_DRM_Rights));
+    if (FALSE == drm_writeOrReadInfo(id, &rightsInfo, &roAmount, GET_A_RO))
+        return DRM_FAILURE;
+
+    memset(rights, 0, sizeof(T_DRM_Rights_Info));
+    drm_getLicenseInfo(&rightsInfo, rights);
+    return DRM_SUCCESS;
+}
+
+/* see svc_drm.h */
+int32_t SVC_drm_closeSession(int32_t session)
+{
+    if (session < 0)
+        return DRM_FAILURE;
+
+    if (NULL == getSession(session))
+        return DRM_SESSION_NOT_OPENED;
+
+    removeSession(session);
+
+    return DRM_SUCCESS;
+}
+
+/* see svc_drm.h */
+int32_t SVC_drm_updateRights(uint8_t* contentID, int32_t permission)
+{
+    int32_t id;
+
+    if (NULL == contentID)
+        return DRM_FAILURE;
+
+    if (FALSE == drm_readFromUidTxt(contentID, &id, GET_ID))
+        return DRM_FAILURE;
+
+    return drm_checkRoAndUpdate(id, permission);
+}
+
+/* see svc_drm.h */
+int32_t SVC_drm_viewAllRights(T_DRM_Rights_Info_Node **ppRightsInfo)
+{
+    T_DRM_Rights_Info_Node rightsNode;
+    int32_t maxId, id, roAmount, j;
+    T_DRM_Rights rights;
+
+    memset(&rights, 0, sizeof(T_DRM_Rights));
+
+    if (NULL == ppRightsInfo)
+        return DRM_FAILURE;
+
+    *ppRightsInfo = NULL;
+
+    maxId = drm_getMaxIdFromUidTxt();
+    if (-1 == maxId)
+        return DRM_FAILURE;
+
+    for (id = 1; id <= maxId; id++) {
+        drm_writeOrReadInfo(id, NULL, &roAmount, GET_ROAMOUNT);
+        if (roAmount <= 0) /* this means there is not any rights */
+            continue;
+
+        for (j = 1; j <= roAmount; j++) {
+            if (FALSE == drm_writeOrReadInfo(id, &rights, &j, GET_A_RO))
+                continue;
+
+            memset(&rightsNode, 0, sizeof(T_DRM_Rights_Info_Node));
+
+            drm_getLicenseInfo(&rights, &(rightsNode.roInfo));
+
+            if (FALSE == drm_addRightsNodeToList(ppRightsInfo, &rightsNode))
+                continue;
+        }
+    }
+    return DRM_SUCCESS;
+}
+
+/* see svc_drm.h */
+int32_t SVC_drm_freeRightsInfoList(T_DRM_Rights_Info_Node *pRightsHeader)
+{
+    T_DRM_Rights_Info_Node *pNode, *pTmp;
+
+    if (NULL == pRightsHeader)
+        return DRM_FAILURE;
+
+    pNode = pRightsHeader;
+
+    while (NULL != pNode) {
+        pTmp = pNode;
+        pNode = pNode->next;
+        free(pTmp);
+    }
+    return DRM_SUCCESS;
+}
+
+/* see svc_drm.h */
+int32_t SVC_drm_deleteRights(uint8_t* roId)
+{
+    int32_t maxId, id, roAmount, j;
+    T_DRM_Rights rights;
+
+    memset(&rights, 0, sizeof(T_DRM_Rights));
+
+    if (NULL == roId)
+        return DRM_FAILURE;
+
+    maxId = drm_getMaxIdFromUidTxt();
+    if (-1 == maxId)
+        return DRM_NO_RIGHTS;
+
+    for (id = 1; id <= maxId; id++) {
+        drm_writeOrReadInfo(id, NULL, &roAmount, GET_ROAMOUNT);
+        if (roAmount <= 0) /* this means there is not any rights */
+            continue;
+
+        for (j = 1; j <= roAmount; j++) {
+            if (FALSE == drm_writeOrReadInfo(id, &rights, &j, GET_A_RO))
+                continue;
+
+            /* here find the RO which will be deleted */
+            if (0 == strcmp((char *)rights.uid, (char *)roId)) {
+                T_DRM_Rights *pAllRights;
+
+                pAllRights = (T_DRM_Rights *)malloc(roAmount * sizeof(T_DRM_Rights));
+                if (NULL == pAllRights)
+                    return DRM_FAILURE;
+
+                drm_writeOrReadInfo(id, pAllRights, &roAmount, GET_ALL_RO);
+                roAmount--;
+                if (0 == roAmount) { /* this means it is the last one rights */
+                    drm_removeIdInfoFile(id); /* delete the id.info file first */
+                    drm_updateUidTxtWhenDelete(id); /* update uid.txt file */
+                    free(pAllRights);
+                    return DRM_SUCCESS;
+                } else /* using the last one rights instead of the deleted one */
+                    memcpy(pAllRights + (j - 1), pAllRights + roAmount, sizeof(T_DRM_Rights));
+
+                /* delete the id.info file first */
+//                drm_removeIdInfoFile(id);
+
+                if (FALSE == drm_writeOrReadInfo(id, pAllRights, &roAmount, SAVE_ALL_RO)) {
+                    free(pAllRights);
+                    return DRM_FAILURE;
+                }
+
+                free(pAllRights);
+                return DRM_SUCCESS;
+            }
+        }
+    }
+
+    return DRM_FAILURE;
+}
diff --git a/media/libdrm/mobile1/src/objmng/drm_decoder.c b/media/libdrm/mobile1/src/objmng/drm_decoder.c
new file mode 100644
index 0000000..82c7efb
--- /dev/null
+++ b/media/libdrm/mobile1/src/objmng/drm_decoder.c
@@ -0,0 +1,96 @@
+/*
+ * 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.
+ */
+
+#include <objmng/drm_decoder.h>
+
+/* global variables */
+static const uint8_t * base64_alphabet = (const uint8_t *)"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+#define SKIP_CRLF(p) while('\r' == *(p) || '\n' == *(p)) \
+                         p++
+
+static int8_t get_alphabet_index(int8_t ch)
+{
+    uint8_t * tmp;
+
+    if ('=' == ch)
+        return 64;
+
+    tmp = (uint8_t *)strchr((const char *)base64_alphabet, ch);
+    if (NULL == tmp)
+        return -1;
+
+    return (int8_t)(tmp - base64_alphabet);
+}
+
+/* See drm_decoder.h */
+int32_t drm_decodeBase64(uint8_t * dest, int32_t destLen, uint8_t * src, int32_t * srcLen)
+{
+    int32_t maxDestSize, i, maxGroup;
+    uint8_t *pDest, *pSrc;
+    int8_t tpChar;
+
+    if (NULL == src || NULL == srcLen || *srcLen <= 0 || destLen < 0)
+        return -1;
+
+    maxDestSize = (*srcLen) * 3/4;
+    if (NULL == dest || 0 == destLen)
+        return maxDestSize;
+
+    if (destLen < maxDestSize)
+        maxDestSize = destLen;
+    maxGroup = maxDestSize/3;
+
+    pDest = dest;   /* start to decode src to dest */
+    pSrc = src;
+    for (i = 0; i < maxGroup && *srcLen - (pSrc - src) >= 4; i++) {
+        SKIP_CRLF(pSrc);
+        if (pSrc - src >= *srcLen)
+            break;
+        tpChar = get_alphabet_index(*pSrc);       /* to first byte */
+        if (-1 == tpChar || 64 == tpChar)
+            return -1;
+        pDest[0] = tpChar << 2;
+        pSrc++;
+        SKIP_CRLF(pSrc);
+        tpChar = get_alphabet_index(*pSrc);
+        if (-1 == tpChar || 64 == tpChar)
+            return -1;
+        pDest[0] |= (tpChar >> 4);
+        pDest[1] = tpChar << 4;                     /* to second byte */
+        pSrc++;
+        SKIP_CRLF(pSrc);
+        tpChar = get_alphabet_index(*pSrc);
+        if (-1 == tpChar)
+            return -1;
+        if (64 == tpChar)           /* end */
+            return pDest - dest + 1;
+        pDest[1] |= (tpChar >> 2);
+        pDest[2] = tpChar << 6;                     /* to third byte */
+        pSrc++;
+        SKIP_CRLF(pSrc);
+        tpChar = get_alphabet_index(*pSrc);
+        if (-1 == tpChar)
+            return -1;
+        if (64 == tpChar)           /* end */
+            return pDest - dest + 2;
+        pDest[2] |= tpChar;
+        pDest += 3;
+        pSrc++;
+    }
+    *srcLen = pSrc - src;
+    return pDest - dest;
+}
diff --git a/media/libdrm/mobile1/src/objmng/drm_file.c b/media/libdrm/mobile1/src/objmng/drm_file.c
new file mode 100644
index 0000000..e6c303e
--- /dev/null
+++ b/media/libdrm/mobile1/src/objmng/drm_file.c
@@ -0,0 +1,694 @@
+/*
+ * 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.
+ */
+
+#include <objmng/drm_file.h>
+
+#include <unistd.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <errno.h>
+#include <string.h>
+
+/**
+ * Fails on zaurus?
+ #define DEVICE_FILESYSTEM
+*/
+#define DEFAULT_TOTAL_SPACE (4L * 1024L * 1024L) /* 4 Meg. */
+
+#ifndef DEVICE_FILESYSTEM
+/* Store the total space on FS VM can use. */
+static int32_t totalSpace;
+/* how many remain space can VM use. */
+static int32_t availableSize;
+#endif
+
+extern char* getStorageRoot(void);
+
+static char tmpPathBuf1[MAX_FILENAME_LEN];
+static char tmpPathBuf2[MAX_FILENAME_LEN];
+
+static int32_t
+convertFilename(const uint16_t *strData, int32_t strLength, char *buffer);
+
+static int calcDirSize(char *path, int len, uint8_t includeSubdirs);
+
+#ifndef DEVICE_FILESYSTEM
+static void initFsVariables(void);
+#endif
+
+/**
+ * Convert a Java string into a nul terminated ascii string to pass to posix
+ * @param strData    first character of name
+ * @param strLength  number of characters in name
+ * @param buffer Buffer to store terminated string in (at least MAXPATHLEN)
+ * @return Length of filename in characters (excl. nul), or -1 on failure.
+ */
+static int32_t
+convertFilename(const uint16_t *strData, int32_t strLength, char *buffer)
+{
+    int idx;
+
+    if (strLength >= (MAXPATHLEN-1))
+    {
+        Trace("convertFilename '%.*S' too long", strLength, strData);
+        return -1;
+    }
+
+    for (idx = 0; idx < strLength; ++idx)
+        *buffer++ = (char)*strData++;
+
+    *buffer = 0;
+    return strLength;
+}
+
+
+/**
+ * Perform a stat() call on the given filename.
+ * Helper for getFileLength and exists
+ * @param name unicode name
+ * @param nameLen number of unicode characters in name
+ * @param sbuf stat buffer
+ * @return TRUE on success, FALSE on failure
+ */
+static int32_t
+getFileStat(const uint16_t *name, int32_t nameLen, struct stat *sbuf)
+{
+    Trace("getFileStat: %.*S", nameLen, name);
+
+    if (convertFilename(name, nameLen, tmpPathBuf1) <= 0)
+    {
+        Trace("getFileStat: bad filename");
+    }
+    else if (stat(tmpPathBuf1, sbuf) != 0)
+    {
+        Trace("getFileStat %s: stat() errno=%d", tmpPathBuf1, errno);
+    }
+    else /* Successful */
+    {
+        return TRUE;
+    }
+
+    return FALSE;
+}
+
+#ifndef DEVICE_FILESYSTEM
+/**
+ * initial the variables like totalSpace, availableSize...
+ */
+static void initFsVariables(void)
+{
+    totalSpace = DEFAULT_TOTAL_SPACE;
+
+    availableSize = totalSpace;
+}
+#endif /* DEVICE_FILESYSTEM */
+
+/**
+ * calculate the size of everything inside path pointed directory
+ * this function will use path pointed buffer to store some extra info
+ * so param len is needed.
+ * @param path    the directory path need to calculate
+ * @param len   length of the path buffer, not the path string length
+ * @param includeSubdirs  also calculate all the subdirs in path holds?
+ * @return the calculated size, DRM_FILE_FAILURE on failure.
+ */
+static int calcDirSize(char *path, int len, uint8_t includeSubdirs)
+{
+    struct dirent *ent;
+    struct stat stat_buf;
+
+    DIR *dir = NULL;
+    int size = 0;
+    int exists = -1;
+    int dirPathLen = strlen(path);
+
+    /* Ensure space for wildcard */
+    if((dirPathLen + 2) >= MAXPATHLEN || (dirPathLen + 2) >= len)
+    {
+        return DRM_FILE_FAILURE;
+    }
+
+    if(path[dirPathLen - 1] != '/')
+    {
+        path[dirPathLen++] = '/';
+        path[dirPathLen] = '\0';
+    }
+
+    dir = opendir(path);
+    if (dir == NULL)
+    {
+        return DRM_FILE_FAILURE;
+    }
+
+    while ((ent = readdir(dir)) != NULL )
+    {
+        if (strcmp(ent->d_name, ".") == 0 ||
+                strcmp(ent->d_name, "..") == 0)
+        {
+            continue;
+        }
+
+        path[dirPathLen] = '\0';
+        if ((int)(strlen(ent->d_name) + dirPathLen + 1) < len)
+        {
+            strcat(path, ent->d_name);
+        }
+        else
+        {
+            continue;
+        }
+
+        exists = stat(path, &stat_buf);
+        if (exists != -1)
+        {
+            /* exclude the storage occupied by directory itself */
+            if (stat_buf.st_mode & S_IFDIR)
+            {
+                if(includeSubdirs)
+                {
+                    /* calculate the size recursively */
+                    int ret;
+                    ret = calcDirSize(path, len, includeSubdirs);
+                    /* ignore failure in subdirs */
+                    if( DRM_FILE_FAILURE != ret )
+                    {
+                        size += ret;
+                    }
+                }
+            }
+            else
+            {
+                size += stat_buf.st_size;
+            }
+        }
+    }
+
+    closedir(dir);
+    return size;
+}
+
+/* see drm_file.h */
+int32_t DRM_file_startup(void)
+{
+    Trace("DRM_file_startup");
+
+#ifndef DEVICE_FILESYSTEM
+    availableSize = -1;
+
+    initFsVariables();
+#endif
+
+    return DRM_FILE_SUCCESS;    /* Nothing to do */
+}
+
+/* see drm_file.h */
+int32_t
+DRM_file_listOpen(const uint16_t *prefix,
+                    int32_t prefixLen,
+                    int32_t* session,
+                    int32_t* iteration)
+{
+    Trace("DRM_file_listOpen: %.*S", prefixLen, prefix);
+
+    if (convertFilename(prefix, prefixLen, tmpPathBuf1) <= 0)
+    {
+        Trace("DRM_file_listOpen: bad filename");
+    }
+    else
+    {
+        DIR *dir;
+
+        /* find the last /, and store the offset to the leaf prefix in
+         * *iteration
+         */
+
+        char *sep = strrchr(tmpPathBuf1, '/');
+        /* Root "/" is a leaf */
+        if (sep == NULL || ((sep != NULL) && (sep == tmpPathBuf1)))
+        {
+            *iteration = prefixLen;
+
+#ifdef TRACE_ON
+            sep = " <empty>"; /* trace will show sep+1 */
+#endif
+        }
+        else
+        {
+            *iteration = sep - tmpPathBuf1 + 1;
+            *sep = 0;
+        }
+
+        dir = opendir(tmpPathBuf1);
+
+        if (dir == NULL)
+        {
+            Trace("DRM_file_listOpen: opendir %s: errno=%d", tmpPathBuf1, errno);
+        }
+        else
+        {
+            Trace("DRM_file_listOpen: dir %s, filter %s", tmpPathBuf1, sep+1);
+            *session = (int32_t)dir;
+            return DRM_FILE_SUCCESS;
+        }
+    }
+
+    return DRM_FILE_FAILURE;
+}
+
+/* see drm_file.h */
+int32_t
+DRM_file_listNextEntry(const uint16_t *prefix, int32_t prefixLen,
+                       uint16_t* entry, int32_t entrySize,
+                       int32_t *session, int32_t* iteration)
+{
+    struct dirent *ent;
+
+    /* We stored the offset of the leaf part of the prefix (if any)
+     * in *iteration
+     */
+    const uint16_t* strData   = prefix + *iteration;
+    int32_t   strLength = prefixLen - *iteration;
+
+    /* entrySize is bytes for some reason. Convert to ucs chars */
+    entrySize /= 2;
+
+    /* Now we want to filter for files which start with the (possibly empty)
+     * sequence at strData. We have to return fully-qualified filenames,
+     * which means *iteration characters from prefix, plus the
+     * leaf name.
+     */
+
+    while ( (ent = readdir((DIR *)*session)) != NULL)
+    {
+        int len = strlen(ent->d_name);
+
+        if ( (len + *iteration) > entrySize)
+        {
+            Trace("DRM_file_listNextEntry: %s too long", ent->d_name);
+        }
+        else if (strcmp(ent->d_name, ".") != 0 &&
+                 strcmp(ent->d_name, "..") != 0)
+        {
+            int idx;
+            struct stat sinfo;
+
+            /* check against the filter */
+
+            for (idx = 0; idx < strLength; ++idx)
+            {
+                if (ent->d_name[idx] != strData[idx])
+                    goto next_name;
+            }
+
+            Trace("DRM_file_listNextEntry: matched %s", ent->d_name);
+
+            /* Now generate the fully-qualified name */
+
+            for (idx = 0; idx < *iteration; ++idx)
+                entry[idx] = prefix[idx];
+
+            for (idx = 0; idx < len; ++idx)
+                entry[*iteration + idx] = (unsigned char)ent->d_name[idx];
+
+            /*add "/" at the end of a DIR file entry*/
+            if (getFileStat(entry, idx + *iteration, &sinfo)){
+                if (S_ISDIR(sinfo.st_mode) &&
+                        (idx + 1 + *iteration) < entrySize) {
+                    entry[*iteration + idx] = '/';
+                    ++idx;
+                }
+            }
+            else
+            {
+                Trace("DRM_file_listNextEntry: stat FAILURE on %.*S",
+                      idx + *iteration, entry);
+            }
+            Trace("DRM_file_listNextEntry: got %.*S", idx + *iteration, entry);
+
+            return idx + *iteration;
+        }
+
+    next_name:
+        Trace("DRM_file_listNextEntry: rejected %s", ent->d_name);
+    }
+
+    Trace("DRM_file_listNextEntry: end of list");
+    return 0;
+}
+
+/* see drm_file.h */
+int32_t
+DRM_file_listClose(int32_t session, int32_t iteration)
+{
+    closedir( (DIR *)session);
+    return DRM_FILE_SUCCESS;
+}
+
+/* see drm_file.h */
+int32_t
+DRM_file_getFileLength(const uint16_t *name, int32_t nameLen)
+{
+    struct stat sbuf;
+
+    if (getFileStat(name, nameLen, &sbuf))
+    {
+        if (sbuf.st_size >= INT32_MAX)
+        {
+            Trace("DRM_file_getFileLength: file too big");
+        }
+        else /* Successful */
+        {
+            Trace("DRM_file_getFileLength: %.*S -> %d",
+                                         nameLen, name, (int32_t)sbuf.st_size);
+            return (int32_t)sbuf.st_size;
+        }
+    }
+
+    return DRM_FILE_FAILURE;
+}
+
+/* see drm_file.h */
+int32_t
+DRM_file_delete(const uint16_t *name, int32_t nameLen)
+{
+    Trace("DRM_file_delete: %.*S", nameLen, name);
+
+    if (convertFilename(name, nameLen, tmpPathBuf1) <= 0)
+    {
+        Trace("DRM_file_delete: bad filename");
+        return DRM_FILE_FAILURE;
+    }
+    else
+    {
+       struct stat sinfo;
+       if (stat(tmpPathBuf1, &sinfo) != 0){
+           Trace("DRM_file_delete: stat failed, errno=%d", errno);
+           return DRM_FILE_FAILURE;
+       }
+#ifndef DEVICE_FILESYSTEM
+       if (S_ISDIR(sinfo.st_mode)){
+            /* it's a dir */
+            if (rmdir(tmpPathBuf1) != 0){
+                Trace("DRM_file_delete: dir remove failed, errno=%d", errno);
+                return DRM_FILE_FAILURE;
+            }
+            else
+            {
+                return DRM_FILE_SUCCESS;
+            }
+        }
+#endif
+        /* it's a file */
+        if (unlink(tmpPathBuf1) != 0)
+        {
+            Trace("DRM_file_delete: file remove failed, errno=%d", errno);
+            return DRM_FILE_FAILURE;
+        }
+        else
+        {
+#ifndef DEVICE_FILESYSTEM
+            availableSize += sinfo.st_size;
+#endif
+            return DRM_FILE_SUCCESS;
+        }
+    }
+    return DRM_FILE_FAILURE;
+}
+
+/* see drm_file.h */
+int32_t
+DRM_file_rename(const uint16_t *oldName, int32_t oldNameLen,
+                const uint16_t *newName, int32_t newNameLen)
+{
+    Trace("DRM_file_rename %.*S -> %.*S",
+                                    oldNameLen, oldName, newNameLen, newName);
+    if (DRM_file_exists(newName, newNameLen) != DRM_FILE_FAILURE)
+    {
+        Trace("DRM_file_rename: filename:%s exist",newName);
+        return DRM_FILE_FAILURE;
+    }
+
+    if (convertFilename(oldName, oldNameLen, tmpPathBuf1) <= 0 ||
+        convertFilename(newName, newNameLen, tmpPathBuf2) <= 0)
+    {
+        Trace("DRM_file_rename: bad filename");
+    }
+    else if (rename(tmpPathBuf1, tmpPathBuf2) != 0)
+    {
+         Trace("DRM_file_rename: failed errno=%d", errno);
+    }
+    else /* Success */
+    {
+        return DRM_FILE_SUCCESS;
+    }
+
+    return DRM_FILE_FAILURE;
+}
+
+/* see drm_file.h */
+int32_t
+DRM_file_exists(const uint16_t *name, int32_t nameLen)
+{
+    struct stat sbuf;
+
+    Trace("DRM_file_exists: %.*S", nameLen, name);
+
+    /*remove trailing "/" separators, except the first "/" standing for root*/
+    while ((nameLen > 1) && (name[nameLen -1] == '/'))
+       --nameLen;
+
+    if (getFileStat(name, nameLen, &sbuf))
+    {
+        Trace("DRM_file_exists: stat returns mode 0x%x", sbuf.st_mode);
+
+        if (S_ISDIR(sbuf.st_mode))
+            return DRM_FILE_ISDIR;
+        if (S_ISREG(sbuf.st_mode))
+            return DRM_FILE_ISREG;
+    }
+
+    return DRM_FILE_FAILURE;
+}
+
+/* see drm_file.h */
+int32_t
+DRM_file_open(const uint16_t *name, int32_t nameLen, int32_t mode,
+                      int32_t* handle)
+{
+    int res;
+
+#if DRM_FILE_MODE_READ != 1 || DRM_FILE_MODE_WRITE != 2
+#error constants changed
+#endif
+
+    /* Convert DRM file modes to posix modes */
+    static const int modes[4] =
+    { 0,
+      O_RDONLY,
+      O_WRONLY | O_CREAT,
+      O_RDWR | O_CREAT
+    };
+
+    Trace("DRM_file_open %.*S mode 0x%x", nameLen, name, mode);
+
+    assert((mode & ~(DRM_FILE_MODE_READ|DRM_FILE_MODE_WRITE)) == 0);
+
+    if (convertFilename(name, nameLen, tmpPathBuf1) <= 0)
+    {
+        Trace("DRM_file_open: bad filename");
+        return DRM_FILE_FAILURE;
+    }
+
+    if ((res = open(tmpPathBuf1, modes[mode], 0777)) == -1)
+    {
+        Trace("DRM_file_open: open failed errno=%d", errno);
+        return DRM_FILE_FAILURE;
+    }
+
+    Trace("DRM_file_open: open '%s; returned %d", tmpPathBuf1, res);
+    *handle = res;
+
+    return DRM_FILE_SUCCESS;
+}
+
+/* see drm_file.h */
+int32_t
+DRM_file_read(int32_t handle, uint8_t* dst, int32_t length)
+{
+    int n;
+
+    assert(length > 0);
+
+    /* TODO: Make dst a void *? */
+
+    n = read((int)handle, dst, (size_t)length);
+    if (n > 0)
+    {
+        Trace("DRM_file_read handle=%d read %d bytes", handle, n);
+        return n;
+    }
+    else if (n == 0)
+    {
+        Trace("DRM_file_read read EOF: handle=%d", handle);
+        return DRM_FILE_EOF;
+    }
+    else
+    {
+        Trace("DRM_file_read failed handle=%d, errno=%d", handle, errno);
+        return DRM_FILE_FAILURE;
+    }
+}
+
+/* see drm_file.h */
+int32_t
+DRM_file_write(int32_t handle, const uint8_t* src, int32_t length)
+{
+    /* TODO: Make dst a void *? */
+    int n;
+#ifndef DEVICE_FILESYSTEM
+    int delta;
+    off_t prevPos;
+    struct stat sbuf;
+    int prevFileSize;
+#endif
+
+    assert(length >= 0);
+
+#ifndef DEVICE_FILESYSTEM
+    if ( -1 == fstat((int)handle, &sbuf) )
+    {
+        Trace("DRM_file_write: fstat error %d", errno);
+        return DRM_FILE_FAILURE;
+    }
+    prevFileSize = (int)(sbuf.st_size);
+    prevPos = lseek( (int)handle, 0, SEEK_CUR);
+    if ( (off_t)-1 == prevPos )
+    {
+        Trace("DRM_file_write: get current pos error %d", errno);
+        return DRM_FILE_FAILURE;
+    }
+    delta = (int)prevPos + length - prevFileSize;
+    if (delta > availableSize)
+    {
+        Trace("DRM_file_write: not enough size!");
+        return DRM_FILE_FAILURE;
+    }
+#endif
+    n = write((int)handle, src, (size_t)length);
+    if (n < 0)
+    {
+        Trace("DRM_file_write failed errno=%d", errno);
+        return DRM_FILE_FAILURE;
+    }
+#ifndef DEVICE_FILESYSTEM
+    delta = prevPos + n - prevFileSize;
+
+    if ( delta > 0 )
+    {
+        availableSize -= delta;
+    }
+#endif
+    Trace("DRM_file_write handle=%d wrote %d/%d bytes", handle, n, length);
+
+    return n;
+}
+
+/* see drm_file.h */
+int32_t DRM_file_close(int32_t handle)
+{
+    if (close((int)handle) == 0)
+    {
+        Trace("DRM_file_close handle=%d success", handle);
+        return DRM_FILE_SUCCESS;
+    }
+
+    Trace("DRM_file_close handle=%d failed", handle);
+    return DRM_FILE_FAILURE;
+}
+
+/* see drm_file.h */
+int32_t
+DRM_file_setPosition(int32_t handle, int32_t value)
+{
+#ifndef DEVICE_FILESYSTEM
+    struct stat sbuf;
+#endif
+    off_t newPos;
+
+    if (value < 0)
+    {
+        Trace("DRM_file_setPosition: handle=%d negative value (%d)",
+            handle, value);
+        return DRM_FILE_FAILURE;
+    }
+
+#ifndef DEVICE_FILESYSTEM
+    if ( fstat((int)handle, &sbuf) == -1 )
+    {
+        Trace("DRM_file_setPosition: fstat fail errno=%d", errno);
+        return DRM_FILE_FAILURE;
+    }
+
+    if ( ((off_t)value > sbuf.st_size) &&
+         (availableSize < (value - (int)(sbuf.st_size))) )
+    {
+        Trace("DRM_file_setPosition: not enough space");
+        return DRM_FILE_FAILURE;
+    }
+#endif
+
+    newPos = lseek( (int)handle, (off_t)value, SEEK_SET);
+    if ( newPos == (off_t)-1 )
+    {
+        Trace("DRM_file_setPosition: seek failed: errno=%d", errno);
+    }
+    else
+    {
+#ifndef DEVICE_FILESYSTEM
+        if ( newPos > sbuf.st_size )
+        {
+            availableSize -= (int)(newPos - sbuf.st_size);
+        }
+#endif
+        return DRM_FILE_SUCCESS;
+    }
+
+    return DRM_FILE_FAILURE;
+}
+
+/* see drm_file.h */
+int32_t
+DRM_file_mkdir(const uint16_t* name, int32_t nameChars)
+{
+    Trace("DRM_file_mkdir started!..");
+
+    if (convertFilename(name, nameChars, tmpPathBuf1) <= 0)
+    {
+        Trace("DRM_file_mkdir: bad filename");
+        return DRM_FILE_FAILURE;
+    }
+
+    if (mkdir(tmpPathBuf1,0777) != 0)
+    {
+        Trace("DRM_file_mkdir failed!errno=%d",errno);
+        return DRM_FILE_FAILURE;
+    }
+
+    return DRM_FILE_SUCCESS;
+}
diff --git a/media/libdrm/mobile1/src/objmng/drm_i18n.c b/media/libdrm/mobile1/src/objmng/drm_i18n.c
new file mode 100644
index 0000000..b1118a9
--- /dev/null
+++ b/media/libdrm/mobile1/src/objmng/drm_i18n.c
@@ -0,0 +1,444 @@
+/*
+ * 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.
+ */
+
+#include <objmng/drm_i18n.h>
+
+#define IS_GB2312_HIGH_BYTE(c)  ((c) >= 0xA1 && (c) <= 0xF7)
+#define IS_GB2312_LOW_BYTE(c)   ((c) >= 0xA1 && (c) <= 0xFE)
+#define IS_GBK_HIGH_BYTE(c)     ((c) >= 0x81 && (c) <= 0xFE)
+#define IS_GBK_LOW_BYTE(c)      ((c) >= 0x40 && (c) <= 0xFE && (c) != 0x7F)
+#define IS_BIG5_HIGH_BYTE(c)    ((c) >= 0xA1 && (c) <= 0xF9)
+#define IS_BIG5_LOW_BYTE(c)     (((c) >= 0x40 && (c) <= 0x7E) \
+                                 || ((c) >= 0xA1 && (c) <= 0xFE))
+#define IS_ASCII(c)             ((c) <= 127)
+
+#define INVALID_UNICODE         0xFFFD
+
+#define I18N_LATIN1_SUPPORT
+#define I18N_UTF8_UTF16_SUPPORT
+
+
+/**
+ * Simply convert ISO 8859-1 (latin1) to unicode
+ */
+static int32_t latin1ToWcs(const uint8_t *mbs, int32_t mbsLen,
+        uint16_t *wcsBuf, int32_t bufSizeInWideChar,
+        int32_t *bytesConsumed);
+
+/**
+ * Convert one unicode char to ISO 8859-1 (latin1) byte
+ */
+static int32_t wcToLatin1(uint16_t wc, uint8_t * mbs, int32_t bufSize);
+
+/**
+ * Convert UTF-8 to unicode
+ */
+static int32_t utf8ToWcs(const uint8_t *mbs, int32_t mbsLen,
+        uint16_t *wcsBuf, int32_t bufSizeInWideChar,
+        int32_t *bytesConsumed);
+
+/**
+ * Convert one unicode char to UTF-8 bytes
+ */
+static int32_t wcToUtf8(uint16_t wc, uint8_t * mbs, int32_t bufSize);
+
+/**
+ * Convert UTF-16 BE to unicode
+ */
+static int32_t utf16beToWcs(const uint8_t *mbs, int32_t mbsLen,
+        uint16_t *wcsBuf, int32_t bufSizeInWideChar,
+        int32_t *bytesConsumed);
+
+/**
+ * Convert one unicode char to UTF-16 BE bytes
+ */
+static int32_t wcToUtf16be(uint16_t wc, uint8_t * mbs, int32_t bufSize);
+
+/**
+ * Convert UTF-16 LE to unicode
+ */
+static int32_t utf16leToWcs(const uint8_t *mbs, int32_t mbsLen,
+        uint16_t *wcsBuf, int32_t bufSizeInWideChar,
+        int32_t *bytesConsumed);
+
+/**
+ * Convert one unicode char to UTF-16 LE bytes
+ */
+static int32_t wcToUtf16le(uint16_t wc, uint8_t * mbs, int32_t bufSize);
+
+/*
+ * see drm_i18n.h
+ */
+int32_t DRM_i18n_mbsToWcs(DRM_Charset_t charset,
+        const uint8_t *mbs, int32_t mbsLen,
+        uint16_t *wcsBuf, int32_t bufSizeInWideChar,
+        int32_t *bytesConsumed)
+{
+    switch (charset)
+    {
+#ifdef I18N_GB2312_SUPPORT
+        case DRM_CHARSET_GB2312:
+            return gb2312ToWcs(mbs, mbsLen, wcsBuf, bufSizeInWideChar, bytesConsumed);
+#endif
+#ifdef I18N_GBK_SUPPORT
+        case DRM_CHARSET_GBK:
+            return gbkToWcs(mbs, mbsLen, wcsBuf, bufSizeInWideChar, bytesConsumed);
+#endif
+#ifdef I18N_BIG5_SUPPORT
+        case DRM_CHARSET_BIG5:
+            return big5ToWcs(mbs, mbsLen, wcsBuf, bufSizeInWideChar, bytesConsumed);
+#endif
+#ifdef I18N_LATIN1_SUPPORT
+        case DRM_CHARSET_LATIN1:
+            return latin1ToWcs(mbs, mbsLen, wcsBuf, bufSizeInWideChar, bytesConsumed);
+#endif
+#ifdef I18N_ISO8859X_SUPPORT
+        case DRM_CHARSET_LATIN2:
+        case DRM_CHARSET_LATIN3:
+        case DRM_CHARSET_LATIN4:
+        case DRM_CHARSET_CYRILLIC:
+        case DRM_CHARSET_ARABIC:
+        case DRM_CHARSET_GREEK:
+        case DRM_CHARSET_HEBREW:
+        case DRM_CHARSET_LATIN5:
+        case DRM_CHARSET_LATIN6:
+        case DRM_CHARSET_THAI:
+        case DRM_CHARSET_LATIN7:
+        case DRM_CHARSET_LATIN8:
+        case DRM_CHARSET_LATIN9:
+        case DRM_CHARSET_LATIN10:
+            return iso8859xToWcs(charset, mbs, mbsLen, wcsBuf, bufSizeInWideChar, bytesConsumed);
+#endif
+#ifdef I18N_UTF8_UTF16_SUPPORT
+        case DRM_CHARSET_UTF8:
+            return utf8ToWcs(mbs, mbsLen, wcsBuf, bufSizeInWideChar, bytesConsumed);
+        case DRM_CHARSET_UTF16BE:
+            return utf16beToWcs(mbs, mbsLen, wcsBuf, bufSizeInWideChar, bytesConsumed);
+        case DRM_CHARSET_UTF16LE:
+            return utf16leToWcs(mbs, mbsLen, wcsBuf, bufSizeInWideChar, bytesConsumed);
+#endif
+        default:
+            return -1;
+    }
+}
+
+/*
+ * see drm_i18n.h
+ */
+int32_t DRM_i18n_wcsToMbs(DRM_Charset_t charset,
+        const uint16_t *wcs, int32_t wcsLen,
+        uint8_t *mbsBuf, int32_t bufSizeInByte)
+{
+    int32_t (* wcToMbFunc)(uint16_t, uint8_t *, int32_t);
+    int32_t charIndex = 0;
+    int32_t numMultiBytes = 0;
+
+    switch (charset)
+    {
+#ifdef I18N_LATIN1_SUPPORT
+        case DRM_CHARSET_LATIN1:
+            wcToMbFunc = wcToLatin1;
+            break;
+#endif
+#ifdef I18N_UTF8_UTF16_SUPPORT
+        case DRM_CHARSET_UTF8:
+            wcToMbFunc = wcToUtf8;
+            break;
+        case DRM_CHARSET_UTF16BE:
+            wcToMbFunc = wcToUtf16be;
+            break;
+        case DRM_CHARSET_UTF16LE:
+            wcToMbFunc = wcToUtf16le;
+            break;
+#endif
+#ifdef I18N_ISO8859X_SUPPORT
+        case DRM_CHARSET_LATIN2:
+        case DRM_CHARSET_LATIN3:
+        case DRM_CHARSET_LATIN4:
+        case DRM_CHARSET_CYRILLIC:
+        case DRM_CHARSET_ARABIC:
+        case DRM_CHARSET_GREEK:
+        case DRM_CHARSET_HEBREW:
+        case DRM_CHARSET_LATIN5:
+        case DRM_CHARSET_LATIN6:
+        case DRM_CHARSET_THAI:
+        case DRM_CHARSET_LATIN7:
+        case DRM_CHARSET_LATIN8:
+        case DRM_CHARSET_LATIN9:
+        case DRM_CHARSET_LATIN10:
+            return wcsToIso8859x(charset, wcs, wcsLen, mbsBuf, bufSizeInByte);
+#endif
+        default:
+            return -1;
+    }
+
+    if (mbsBuf) {
+        while (numMultiBytes < bufSizeInByte && charIndex < wcsLen) {
+            /* TODO: handle surrogate pair values here */
+            int32_t mbLen = wcToMbFunc(wcs[charIndex],
+                    &mbsBuf[numMultiBytes], bufSizeInByte - numMultiBytes);
+
+            if (numMultiBytes + mbLen > bufSizeInByte) {
+                /* Insufficient buffer. Don't update numMultiBytes */
+                break;
+            }
+            charIndex++;
+            numMultiBytes += mbLen;
+        }
+    } else {
+        while (charIndex < wcsLen) {
+            /* TODO: handle surrogate pair values here */
+            numMultiBytes += wcToMbFunc(wcs[charIndex], NULL, 0);
+            charIndex++;
+        }
+    }
+
+    return numMultiBytes;
+}
+
+
+#ifdef I18N_LATIN1_SUPPORT
+
+int32_t latin1ToWcs(const uint8_t *mbs, int32_t mbsLen,
+        uint16_t *wcsBuf, int32_t bufSizeInWideChar,
+        int32_t *bytesConsumed)
+{
+    int32_t charsToConvert;
+    int32_t len;
+
+    if (wcsBuf == NULL) {
+        return mbsLen;
+    }
+
+    len = charsToConvert = mbsLen > bufSizeInWideChar ? bufSizeInWideChar : mbsLen;
+    if (len < 0)
+        return 0;
+    while (len--) {
+        *wcsBuf++ = *mbs++;
+    }
+
+    if (bytesConsumed)
+        *bytesConsumed = charsToConvert;
+
+    return charsToConvert;
+}
+
+int32_t wcToLatin1(uint16_t wc, uint8_t * mbs, int32_t bufSize)
+{
+    uint8_t ch;
+
+    if (wc < 0x100) {
+        ch = (uint8_t)(wc & 0xff);
+    } else {
+        ch = '?';
+    }
+    if (mbs && bufSize > 0)
+        *mbs = ch;
+    return 1;
+}
+
+#endif /* I18N_LATIN1_SUPPORT */
+
+#ifdef I18N_UTF8_UTF16_SUPPORT
+
+int32_t utf8ToWcs(const uint8_t *mbs, int32_t mbsLen,
+        uint16_t *wcsBuf, int32_t bufSizeInWideChar,
+        int32_t *bytesConsumed)
+{
+    int32_t charsConverted = 0;
+    int32_t i = 0;
+    int32_t wideChar;
+
+    if (wcsBuf == NULL) {
+        /* No conversion but we're still going to calculate bytesConsumed */
+        bufSizeInWideChar = mbsLen * 2;
+    }
+
+    while((i < mbsLen) && (charsConverted < bufSizeInWideChar)) {
+        uint8_t ch = mbs[i];
+        uint8_t ch2, ch3, ch4;
+
+        wideChar = -1;
+
+        if(IS_ASCII(ch)) {
+            wideChar = ch;
+            i++;
+        } else if ((ch & 0xc0) == 0xc0) {
+            int utfStart = i;
+            if ((ch & 0xe0) == 0xc0) {
+                /* 2 byte sequence */
+                if (i + 1 < mbsLen && ((ch2 = mbs[i + 1]) & 0xc0) == 0x80) {
+                    wideChar = (uint16_t)(((ch & 0x1F) << 6) | (ch2 & 0x3F));
+                    i += 2;
+                } else {
+                    /* skip incomplete sequence */
+                    i++;
+                }
+            } else if ((ch & 0xf0) == 0xe0) {
+                /* 3 byte sequence */
+                if (i + 2 < mbsLen
+                        && ((ch2 = mbs[i + 1]) & 0xc0) == 0x80
+                        && ((ch3 = mbs[i + 2]) & 0xc0) == 0x80) {
+                    wideChar = (uint16_t)(((ch & 0x0F) << 12) | ((ch2 & 0x3F) << 6) | (ch3 & 0x3F));
+                    i += 3;
+                } else {
+                    /* skip incomplete sequence (up to 2 bytes) */
+                    i++;
+                    if (i < mbsLen && (mbs[i] & 0xc0) == 0x80)
+                        i++;
+                }
+            } else if ((ch & 0xf8) == 0xf0) {
+                /* 4 byte sequence */
+                if (i + 3 < mbsLen
+                        && ((ch2 = mbs[i + 1]) & 0xc0) == 0x80
+                        && ((ch3 = mbs[i + 2]) & 0xc0) == 0x80
+                        && ((ch4 = mbs[i + 3]) & 0xc0) == 0x80) {
+                    /* FIXME: we do NOT support U+10000 - U+10FFFF for now.
+                     *        leave it as 0xFFFD. */
+                    wideChar = INVALID_UNICODE;
+                    i += 4;
+                } else {
+                    /* skip incomplete sequence (up to 3 bytes) */
+                    i++;
+                    if (i < mbsLen && (mbs[i] & 0xc0) == 0x80) {
+                        i++;
+                        if (i < mbsLen && (mbs[i] & 0xc0) == 0x80) {
+                            i++;
+                        }
+                    }
+                }
+            } else {
+                /* invalid */
+                i++;
+            }
+            if (i >= mbsLen && wideChar == -1) {
+                /* Possible incomplete UTF-8 sequence at the end of mbs.
+                 * Leave it to the caller.
+                 */
+                i = utfStart;
+                break;
+            }
+        } else {
+            /* invalid */
+            i++;
+        }
+        if(wcsBuf) {
+            if (wideChar == -1)
+                wideChar = INVALID_UNICODE;
+            wcsBuf[charsConverted] = (uint16_t)wideChar;
+        }
+        charsConverted++;
+    }
+
+    if (bytesConsumed)
+        *bytesConsumed = i;
+
+    return charsConverted;
+}
+
+int32_t wcToUtf8(uint16_t wc, uint8_t * mbs, int32_t bufSize)
+{
+    if (wc <= 0x7f) {
+        if (mbs && (bufSize >= 1)) {
+            *mbs = (uint8_t)wc;
+        }
+        return 1;
+    } else if (wc <= 0x7ff) {
+        if (mbs && (bufSize >= 2)) {
+            *mbs++ = (uint8_t)((wc >> 6) | 0xc0);
+            *mbs = (uint8_t)((wc & 0x3f) | 0x80);
+        }
+        return 2;
+    } else {
+        if (mbs && (bufSize >= 3)) {
+            *mbs++ = (uint8_t)((wc >> 12) | 0xe0);
+            *mbs++ = (uint8_t)(((wc >> 6) & 0x3f)| 0x80);
+            *mbs = (uint8_t)((wc & 0x3f) | 0x80);
+        }
+        return 3;
+    }
+}
+
+int32_t utf16beToWcs(const uint8_t *mbs, int32_t mbsLen,
+        uint16_t *wcsBuf, int32_t bufSizeInWideChar,
+        int32_t *bytesConsumed)
+{
+    int32_t charsToConvert;
+    int32_t len;
+
+    if (wcsBuf == NULL) {
+        return mbsLen / 2;
+    }
+
+    len = charsToConvert = (mbsLen / 2) > bufSizeInWideChar ? bufSizeInWideChar : (mbsLen / 2);
+    while (len--) {
+        /* TODO: handle surrogate pair values */
+        *wcsBuf++ = (uint16_t)((*mbs << 8) | *(mbs + 1));
+        mbs += 2;
+    }
+
+    if (bytesConsumed)
+        *bytesConsumed = charsToConvert * 2;
+
+    return charsToConvert;
+}
+
+int32_t wcToUtf16be(uint16_t wc, uint8_t * mbs, int32_t bufSize)
+{
+    if (mbs && bufSize >= 2) {
+        /* TODO: handle surrogate pair values */
+        *mbs = (uint8_t)(wc >> 8);
+        *(mbs + 1) = (uint8_t)(wc & 0xff);
+    }
+    return 2;
+}
+
+int32_t utf16leToWcs(const uint8_t *mbs, int32_t mbsLen,
+        uint16_t *wcsBuf, int32_t bufSizeInWideChar,
+        int32_t *bytesConsumed)
+{
+    int32_t charsToConvert;
+    int32_t len;
+
+    if (wcsBuf == NULL) {
+        return mbsLen / 2;
+    }
+
+    len = charsToConvert = (mbsLen / 2) > bufSizeInWideChar ? bufSizeInWideChar : (mbsLen / 2);
+    while (len--) {
+        /* TODO: handle surrogate pair values */
+        *wcsBuf++ = (uint16_t)(*mbs | (*(mbs + 1) << 8));
+        mbs += 2;
+    }
+
+    if (bytesConsumed)
+        *bytesConsumed = charsToConvert * 2;
+
+    return charsToConvert;
+}
+
+int32_t wcToUtf16le(uint16_t wc, uint8_t * mbs, int32_t bufSize)
+{
+    if (mbs && bufSize >= 2) {
+        /* TODO: handle surrogate pair values */
+        *mbs = (uint8_t)(wc & 0xff);
+        *(mbs + 1) = (uint8_t)(wc >> 8);
+    }
+    return 2;
+}
+
+#endif /* I18N_UTF8_UTF16_SUPPORT */
+
diff --git a/media/libdrm/mobile1/src/objmng/drm_rights_manager.c b/media/libdrm/mobile1/src/objmng/drm_rights_manager.c
new file mode 100644
index 0000000..80901f5
--- /dev/null
+++ b/media/libdrm/mobile1/src/objmng/drm_rights_manager.c
@@ -0,0 +1,688 @@
+/*
+ * 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.
+ */
+
+#include <drm_rights_manager.h>
+#include <drm_inner.h>
+#include <drm_file.h>
+#include <drm_i18n.h>
+
+static int32_t drm_getString(uint8_t* string, int32_t len, int32_t handle)
+{
+    int32_t i;
+
+    for (i = 0; i < len; i++) {
+        if (DRM_FILE_FAILURE == DRM_file_read(handle, &string[i], 1))
+            return FALSE;
+        if (string[i] == '\n') {
+            string[i + 1] = '\0';
+            break;
+        }
+    }
+    return TRUE;
+}
+
+static int32_t drm_putString(uint8_t* string, int32_t handle)
+{
+    int32_t i = 0;
+
+    for (i = 0;; i++) {
+        if (string[i] == '\0')
+            break;
+        if (DRM_FILE_FAILURE == DRM_file_write(handle, &string[i], 1))
+            return FALSE;
+    }
+    return TRUE;
+}
+
+static int32_t drm_writeToUidTxt(uint8_t* Uid, int32_t* id)
+{
+    int32_t length;
+    int32_t i;
+    uint8_t idStr[8];
+    int32_t idMax;
+    uint8_t(*uidStr)[256];
+    uint16_t nameUcs2[MAX_FILENAME_LEN];
+    int32_t nameLen;
+    int32_t bytesConsumed;
+    int32_t handle;
+    int32_t fileRes;
+
+    if (*id < 1)
+        return FALSE;
+
+    /* convert in ucs2 */
+    nameLen = strlen(DRM_UID_FILE_PATH);
+    nameLen = DRM_i18n_mbsToWcs(DRM_CHARSET_UTF8,
+                        (uint8_t *)DRM_UID_FILE_PATH,
+                        nameLen,
+                        nameUcs2,
+                        MAX_FILENAME_LEN,
+                        &bytesConsumed);
+    fileRes = DRM_file_open(nameUcs2,
+                        nameLen,
+                        DRM_FILE_MODE_READ,
+                        &handle);
+    if (DRM_FILE_SUCCESS != fileRes) {
+        DRM_file_open(nameUcs2,
+                        nameLen,
+                        DRM_FILE_MODE_WRITE,
+                        &handle);
+        DRM_file_write(handle, (uint8_t *)"0\n", 2);
+        DRM_file_close(handle);
+        DRM_file_open(nameUcs2,
+                        nameLen,
+                        DRM_FILE_MODE_READ,
+                        &handle);
+    }
+
+    if (!drm_getString(idStr, 8, handle)) {
+        DRM_file_close(handle);
+        return FALSE;
+    }
+    idMax = atoi((char *)idStr);
+
+    if (idMax < *id)
+        uidStr = malloc((idMax + 1) * 256);
+    else
+        uidStr = malloc(idMax * 256);
+
+    for (i = 0; i < idMax; i++) {
+        if (!drm_getString(uidStr[i], 256, handle)) {
+            DRM_file_close(handle);
+            free(uidStr);
+            return FALSE;
+        }
+    }
+    length = strlen((char *)Uid);
+    strcpy((char *)uidStr[*id - 1], (char *)Uid);
+    uidStr[*id - 1][length] = '\n';
+    uidStr[*id - 1][length + 1] = '\0';
+    if (idMax < (*id))
+        idMax++;
+    DRM_file_close(handle);
+
+    DRM_file_open(nameUcs2,
+                    nameLen,
+                    DRM_FILE_MODE_WRITE,
+                    &handle);
+    sprintf((char *)idStr, "%d", idMax);
+
+    if (!drm_putString(idStr, handle)) {
+        DRM_file_close(handle);
+        free(uidStr);
+        return FALSE;
+    }
+    if (DRM_FILE_FAILURE == DRM_file_write(handle, (uint8_t *)"\n", 1)) {
+        DRM_file_close(handle);
+        free(uidStr);
+        return FALSE;
+    }
+    for (i = 0; i < idMax; i++) {
+        if (!drm_putString(uidStr[i], handle)) {
+            DRM_file_close(handle);
+            free(uidStr);
+            return FALSE;
+        }
+    }
+    if (DRM_FILE_FAILURE == DRM_file_write(handle, (uint8_t *)"\n", 1)) {
+        DRM_file_close(handle);
+        free(uidStr);
+        return FALSE;
+    }
+    DRM_file_close(handle);
+    free(uidStr);
+    return TRUE;
+}
+
+/* See objmng_files.h */
+int32_t drm_readFromUidTxt(uint8_t* Uid, int32_t* id, int32_t option)
+{
+    int32_t i;
+    uint8_t p[256] = { 0 };
+    uint8_t idStr[8];
+    int32_t idMax = 0;
+    uint16_t nameUcs2[MAX_FILENAME_LEN];
+    int32_t nameLen = 0;
+    int32_t bytesConsumed;
+    int32_t handle;
+    int32_t fileRes;
+
+    if (NULL == id || NULL == Uid)
+        return FALSE;
+
+    DRM_file_startup();
+
+    /* convert in ucs2 */
+    nameLen = strlen(DRM_UID_FILE_PATH);
+    nameLen = DRM_i18n_mbsToWcs(DRM_CHARSET_UTF8,
+                        (uint8_t *)DRM_UID_FILE_PATH,
+                        nameLen,
+                        nameUcs2,
+                        MAX_FILENAME_LEN,
+                        &bytesConsumed);
+    fileRes = DRM_file_open(nameUcs2,
+                        nameLen,
+                        DRM_FILE_MODE_READ,
+                        &handle);
+    if (DRM_FILE_SUCCESS != fileRes) {
+        DRM_file_open(nameUcs2,
+                        nameLen,
+                        DRM_FILE_MODE_WRITE,
+                        &handle);
+        DRM_file_write(handle, (uint8_t *)"0\n", 2);
+        DRM_file_close(handle);
+        DRM_file_open(nameUcs2,
+                        nameLen,
+                        DRM_FILE_MODE_READ,
+                        &handle);
+    }
+
+    if (!drm_getString(idStr, 8, handle)) {
+        DRM_file_close(handle);
+        return FALSE;
+    }
+    idMax = atoi((char *)idStr);
+
+    if (option == GET_UID) {
+        if (*id < 1 || *id > idMax) {
+            DRM_file_close(handle);
+            return FALSE;
+        }
+        for (i = 1; i <= *id; i++) {
+            if (!drm_getString(Uid, 256, handle)) {
+                DRM_file_close(handle);
+                return FALSE;
+            }
+        }
+        DRM_file_close(handle);
+        return TRUE;
+    }
+    if (option == GET_ID) {
+        *id = -1;
+        for (i = 1; i <= idMax; i++) {
+            if (!drm_getString(p, 256, handle)) {
+                DRM_file_close(handle);
+                return FALSE;
+            }
+            if (strstr((char *)p, (char *)Uid) != NULL
+                && strlen((char *)p) == strlen((char *)Uid) + 1) {
+                *id = i;
+                DRM_file_close(handle);
+                return TRUE;
+            }
+            if ((*id == -1) && (strlen((char *)p) < 3))
+                *id = i;
+        }
+        if (*id != -1) {
+            DRM_file_close(handle);
+            return FALSE;
+        }
+        *id = idMax + 1;
+        DRM_file_close(handle);
+        return FALSE;
+    }
+    DRM_file_close(handle);
+    return FALSE;
+}
+
+static int32_t drm_acquireId(uint8_t* uid, int32_t* id)
+{
+    if (TRUE == drm_readFromUidTxt(uid, id, GET_ID))
+        return TRUE;
+
+    drm_writeToUidTxt(uid, id);
+
+    return FALSE; /* The Uid is not exit, then return FALSE indicate it */
+}
+
+int32_t drm_writeOrReadInfo(int32_t id, T_DRM_Rights* Ro, int32_t* RoAmount, int32_t option)
+{
+    uint8_t fullname[MAX_FILENAME_LEN] = {0};
+    int32_t tmpRoAmount;
+    uint16_t nameUcs2[MAX_FILENAME_LEN];
+    int32_t nameLen = 0;
+    int32_t bytesConsumed;
+    int32_t handle;
+    int32_t fileRes;
+
+    sprintf((char *)fullname, ANDROID_DRM_CORE_PATH"%d"EXTENSION_NAME_INFO, id);
+
+    /* convert in ucs2 */
+    nameLen = strlen((char *)fullname);
+    nameLen = DRM_i18n_mbsToWcs(DRM_CHARSET_UTF8,
+                        fullname,
+                        nameLen,
+                        nameUcs2,
+                        MAX_FILENAME_LEN,
+                        &bytesConsumed);
+    fileRes = DRM_file_open(nameUcs2,
+                            nameLen,
+                            DRM_FILE_MODE_READ,
+                            &handle);
+    if (DRM_FILE_SUCCESS != fileRes) {
+        if (GET_ALL_RO == option || GET_A_RO == option)
+            return FALSE;
+
+        if (GET_ROAMOUNT == option) {
+            *RoAmount = -1;
+            return TRUE;
+        }
+    }
+
+    DRM_file_close(handle);
+    DRM_file_open(nameUcs2,
+                nameLen,
+                DRM_FILE_MODE_READ | DRM_FILE_MODE_WRITE,
+                &handle);
+
+    switch(option) {
+    case GET_ROAMOUNT:
+        if (DRM_FILE_FAILURE == DRM_file_read(handle, (uint8_t*)RoAmount, sizeof(int32_t))) {
+            DRM_file_close(handle);
+            return FALSE;
+        }
+        break;
+    case GET_ALL_RO:
+        DRM_file_setPosition(handle, sizeof(int32_t));
+
+        if (DRM_FILE_FAILURE == DRM_file_read(handle, (uint8_t*)Ro, (*RoAmount) * sizeof(T_DRM_Rights))) {
+            DRM_file_close(handle);
+            return FALSE;
+        }
+        break;
+    case SAVE_ALL_RO:
+        if (DRM_FILE_FAILURE == DRM_file_write(handle, (uint8_t*)RoAmount, sizeof(int32_t))) {
+            DRM_file_close(handle);
+            return FALSE;
+        }
+
+        if (NULL != Ro && *RoAmount >= 1) {
+            if (DRM_FILE_FAILURE == DRM_file_write(handle, (uint8_t*) Ro, (*RoAmount) * sizeof(T_DRM_Rights))) {
+                DRM_file_close(handle);
+                return FALSE;
+            }
+        }
+        break;
+    case GET_A_RO:
+        DRM_file_setPosition(handle, sizeof(int32_t) + (*RoAmount - 1) * sizeof(T_DRM_Rights));
+
+        if (DRM_FILE_FAILURE == DRM_file_read(handle, (uint8_t*)Ro, sizeof(T_DRM_Rights))) {
+            DRM_file_close(handle);
+            return FALSE;
+        }
+        break;
+    case SAVE_A_RO:
+        DRM_file_setPosition(handle, sizeof(int32_t) + (*RoAmount - 1) * sizeof(T_DRM_Rights));
+
+        if (DRM_FILE_FAILURE == DRM_file_write(handle, (uint8_t*)Ro, sizeof(T_DRM_Rights))) {
+            DRM_file_close(handle);
+            return FALSE;
+        }
+
+        DRM_file_setPosition(handle, 0);
+        if (DRM_FILE_FAILURE == DRM_file_read(handle, (uint8_t*)&tmpRoAmount, sizeof(int32_t))) {
+            DRM_file_close(handle);
+            return FALSE;
+        }
+        if (tmpRoAmount < *RoAmount) {
+            DRM_file_setPosition(handle, 0);
+            DRM_file_write(handle, (uint8_t*)RoAmount, sizeof(int32_t));
+        }
+        break;
+    default:
+        DRM_file_close(handle);
+        return FALSE;
+    }
+
+    DRM_file_close(handle);
+    return TRUE;
+}
+
+int32_t drm_appendRightsInfo(T_DRM_Rights* rights)
+{
+    int32_t id;
+    int32_t roAmount;
+
+    if (NULL == rights)
+        return FALSE;
+
+    drm_acquireId(rights->uid, &id);
+
+    if (FALSE == drm_writeOrReadInfo(id, NULL, &roAmount, GET_ROAMOUNT))
+        return FALSE;
+
+    if (-1 == roAmount)
+        roAmount = 0;
+
+    /* The RO amount increase */
+    roAmount++;
+
+    /* Save the rights information */
+    if (FALSE == drm_writeOrReadInfo(id, rights, &roAmount, SAVE_A_RO))
+        return FALSE;
+
+    return TRUE;
+}
+
+int32_t drm_getMaxIdFromUidTxt()
+{
+    uint8_t idStr[8];
+    int32_t idMax = 0;
+    uint16_t nameUcs2[MAX_FILENAME_LEN] = {0};
+    int32_t nameLen = 0;
+    int32_t bytesConsumed;
+    int32_t handle;
+    int32_t fileRes;
+
+    /* convert in ucs2 */
+    nameLen = strlen(DRM_UID_FILE_PATH);
+    nameLen = DRM_i18n_mbsToWcs(DRM_CHARSET_UTF8,
+                        (uint8_t *)DRM_UID_FILE_PATH,
+                        nameLen,
+                        nameUcs2,
+                        MAX_FILENAME_LEN,
+                        &bytesConsumed);
+    fileRes = DRM_file_open(nameUcs2,
+                        nameLen,
+                        DRM_FILE_MODE_READ,
+                        &handle);
+
+    /* this means the uid.txt file is not exist, so there is not any DRM object */
+    if (DRM_FILE_SUCCESS != fileRes)
+        return 0;
+
+    if (!drm_getString(idStr, 8, handle)) {
+        DRM_file_close(handle);
+        return -1;
+    }
+    DRM_file_close(handle);
+
+    idMax = atoi((char *)idStr);
+    return idMax;
+}
+
+int32_t drm_removeIdInfoFile(int32_t id)
+{
+    uint8_t filename[MAX_FILENAME_LEN] = {0};
+    uint16_t nameUcs2[MAX_FILENAME_LEN];
+    int32_t nameLen = 0;
+    int32_t bytesConsumed;
+
+    if (id <= 0)
+        return FALSE;
+
+    sprintf((char *)filename, ANDROID_DRM_CORE_PATH"%d"EXTENSION_NAME_INFO, id);
+
+    /* convert in ucs2 */
+    nameLen = strlen((char *)filename);
+    nameLen = DRM_i18n_mbsToWcs(DRM_CHARSET_UTF8,
+                        filename,
+                        nameLen,
+                        nameUcs2,
+                        MAX_FILENAME_LEN,
+                        &bytesConsumed);
+    if (DRM_FILE_SUCCESS != DRM_file_delete(nameUcs2, nameLen))
+        return FALSE;
+
+    return TRUE;
+}
+
+int32_t drm_updateUidTxtWhenDelete(int32_t id)
+{
+    uint16_t nameUcs2[MAX_FILENAME_LEN];
+    int32_t nameLen = 0;
+    int32_t bytesConsumed;
+    int32_t handle;
+    int32_t fileRes;
+    int32_t bufferLen;
+    uint8_t *buffer;
+    uint8_t idStr[8];
+    int32_t idMax;
+
+    if (id <= 0)
+        return FALSE;
+
+    nameLen = strlen(DRM_UID_FILE_PATH);
+    nameLen = DRM_i18n_mbsToWcs(DRM_CHARSET_UTF8,
+                        (uint8_t *)DRM_UID_FILE_PATH,
+                        nameLen,
+                        nameUcs2,
+                        MAX_FILENAME_LEN,
+                        &bytesConsumed);
+    bufferLen = DRM_file_getFileLength(nameUcs2, nameLen);
+    if (bufferLen <= 0)
+        return FALSE;
+
+    buffer = (uint8_t *)malloc(bufferLen);
+    if (NULL == buffer)
+        return FALSE;
+
+    fileRes = DRM_file_open(nameUcs2,
+                            nameLen,
+                            DRM_FILE_MODE_READ,
+                            &handle);
+    if (DRM_FILE_SUCCESS != fileRes) {
+        free(buffer);
+        return FALSE;
+    }
+
+    drm_getString(idStr, 8, handle);
+    idMax = atoi((char *)idStr);
+
+    bufferLen -= strlen((char *)idStr);
+    fileRes = DRM_file_read(handle, buffer, bufferLen);
+    buffer[bufferLen] = '\0';
+    DRM_file_close(handle);
+
+    /* handle this buffer */
+    {
+        uint8_t *pStart, *pEnd;
+        int32_t i, movLen;
+
+        pStart = buffer;
+        pEnd = pStart;
+        for (i = 0; i < id; i++) {
+            if (pEnd != pStart)
+                pStart = ++pEnd;
+            while ('\n' != *pEnd)
+                pEnd++;
+            if (pStart == pEnd)
+                pStart--;
+        }
+        movLen = bufferLen - (pEnd - buffer);
+        memmove(pStart, pEnd, movLen);
+        bufferLen -= (pEnd - pStart);
+    }
+
+    if (DRM_FILE_SUCCESS != DRM_file_delete(nameUcs2, nameLen)) {
+        free(buffer);
+        return FALSE;
+    }
+
+    fileRes = DRM_file_open(nameUcs2,
+        nameLen,
+        DRM_FILE_MODE_WRITE,
+        &handle);
+    if (DRM_FILE_SUCCESS != fileRes) {
+        free(buffer);
+        return FALSE;
+    }
+    sprintf((char *)idStr, "%d", idMax);
+    drm_putString(idStr, handle);
+    DRM_file_write(handle, (uint8_t*)"\n", 1);
+    DRM_file_write(handle, buffer, bufferLen);
+    free(buffer);
+    DRM_file_close(handle);
+    return TRUE;
+}
+
+int32_t drm_getKey(uint8_t* uid, uint8_t* KeyValue)
+{
+    T_DRM_Rights ro;
+    int32_t id, roAmount;
+
+    if (NULL == uid || NULL == KeyValue)
+        return FALSE;
+
+    if (FALSE == drm_readFromUidTxt(uid, &id, GET_ID))
+        return FALSE;
+
+    if (FALSE == drm_writeOrReadInfo(id, NULL, &roAmount, GET_ROAMOUNT))
+        return FALSE;
+
+    if (roAmount <= 0)
+        return FALSE;
+
+    memset(&ro, 0, sizeof(T_DRM_Rights));
+    roAmount = 1;
+    if (FALSE == drm_writeOrReadInfo(id, &ro, &roAmount, GET_A_RO))
+        return FALSE;
+
+    memcpy(KeyValue, ro.KeyValue, DRM_KEY_LEN);
+    return TRUE;
+}
+
+void drm_discardPaddingByte(uint8_t *decryptedBuf, int32_t *decryptedBufLen)
+{
+    int32_t tmpLen = *decryptedBufLen;
+    int32_t i;
+
+    if (NULL == decryptedBuf || *decryptedBufLen < 0)
+        return;
+
+    /* Check whether the last several bytes are padding or not */
+    for (i = 1; i < decryptedBuf[tmpLen - 1]; i++) {
+        if (decryptedBuf[tmpLen - 1 - i] != decryptedBuf[tmpLen - 1])
+            break; /* Not the padding bytes */
+    }
+    if (i == decryptedBuf[tmpLen - 1]) /* They are padding bytes */
+        *decryptedBufLen = tmpLen - i;
+    return;
+}
+
+int32_t drm_aesDecBuffer(uint8_t * Buffer, int32_t * BufferLen, aes_decrypt_ctx ctx[1])
+{
+    uint8_t dbuf[3 * DRM_ONE_AES_BLOCK_LEN], buf[DRM_ONE_AES_BLOCK_LEN];
+    uint64_t i, len, wlen = DRM_ONE_AES_BLOCK_LEN, curLen, restLen;
+    uint8_t *pTarget, *pTargetHead;
+
+    pTargetHead = Buffer;
+    pTarget = Buffer;
+    curLen = 0;
+    restLen = *BufferLen;
+
+    if (restLen > 2 * DRM_ONE_AES_BLOCK_LEN) {
+        len = 2 * DRM_ONE_AES_BLOCK_LEN;
+    } else {
+        len = restLen;
+    }
+    memcpy(dbuf, Buffer, (size_t)len);
+    restLen -= len;
+    Buffer += len;
+
+    if (len < 2 * DRM_ONE_AES_BLOCK_LEN) { /* The original file is less than one block in length */
+        len -= DRM_ONE_AES_BLOCK_LEN;
+        /* Decrypt from position len to position len + DRM_ONE_AES_BLOCK_LEN */
+        aes_decrypt((dbuf + len), (dbuf + len), ctx);
+
+        /* Undo the CBC chaining */
+        for (i = 0; i < len; ++i)
+            dbuf[i] ^= dbuf[i + DRM_ONE_AES_BLOCK_LEN];
+
+        /* Output the decrypted bytes */
+        memcpy(pTarget, dbuf, (size_t)len);
+        pTarget += len;
+    } else {
+        uint8_t *b1 = dbuf, *b2 = b1 + DRM_ONE_AES_BLOCK_LEN, *b3 = b2 + DRM_ONE_AES_BLOCK_LEN, *bt;
+
+        for (;;) { /* While some ciphertext remains, prepare to decrypt block b2 */
+            /* Read in the next block to see if ciphertext stealing is needed */
+            b3 = Buffer;
+            if (restLen > DRM_ONE_AES_BLOCK_LEN) {
+                len = DRM_ONE_AES_BLOCK_LEN;
+            } else {
+                len = restLen;
+            }
+            restLen -= len;
+            Buffer += len;
+
+            /* Decrypt the b2 block */
+            aes_decrypt((uint8_t *)b2, buf, ctx);
+
+            if (len == 0 || len == DRM_ONE_AES_BLOCK_LEN) { /* No ciphertext stealing */
+                /* Unchain CBC using the previous ciphertext block in b1 */
+                for (i = 0; i < DRM_ONE_AES_BLOCK_LEN; ++i)
+                    buf[i] ^= b1[i];
+            } else { /* Partial last block - use ciphertext stealing */
+                wlen = len;
+                /* Produce last 'len' bytes of plaintext by xoring with */
+                /* The lowest 'len' bytes of next block b3 - C[N-1] */
+                for (i = 0; i < len; ++i)
+                    buf[i] ^= b3[i];
+
+                /* Reconstruct the C[N-1] block in b3 by adding in the */
+                /* Last (DRM_ONE_AES_BLOCK_LEN - len) bytes of C[N-2] in b2 */
+                for (i = len; i < DRM_ONE_AES_BLOCK_LEN; ++i)
+                    b3[i] = buf[i];
+
+                /* Decrypt the C[N-1] block in b3 */
+                aes_decrypt((uint8_t *)b3, (uint8_t *)b3, ctx);
+
+                /* Produce the last but one plaintext block by xoring with */
+                /* The last but two ciphertext block */
+                for (i = 0; i < DRM_ONE_AES_BLOCK_LEN; ++i)
+                    b3[i] ^= b1[i];
+
+                /* Write decrypted plaintext blocks */
+                memcpy(pTarget, b3, DRM_ONE_AES_BLOCK_LEN);
+                pTarget += DRM_ONE_AES_BLOCK_LEN;
+            }
+
+            /* Write the decrypted plaintext block */
+            memcpy(pTarget, buf, (size_t)wlen);
+            pTarget += wlen;
+
+            if (len != DRM_ONE_AES_BLOCK_LEN) {
+                *BufferLen = pTarget - pTargetHead;
+                return 0;
+            }
+
+            /* Advance the buffer pointers */
+            bt = b1, b1 = b2, b2 = b3, b3 = bt;
+        }
+    }
+    return 0;
+}
+
+int32_t drm_updateDcfDataLen(uint8_t* pDcfLastData, uint8_t* keyValue, int32_t* moreBytes)
+{
+    aes_decrypt_ctx ctx[1];
+    int32_t len = DRM_TWO_AES_BLOCK_LEN;
+
+    if (NULL == pDcfLastData || NULL == keyValue)
+        return FALSE;
+
+    aes_decrypt_key128(keyValue, ctx);
+
+    if (drm_aesDecBuffer(pDcfLastData, &len, ctx) < 0)
+        return FALSE;
+
+    drm_discardPaddingByte(pDcfLastData, &len);
+
+    *moreBytes = DRM_TWO_AES_BLOCK_LEN - len;
+
+    return TRUE;
+}
diff --git a/media/libdrm/mobile1/src/objmng/drm_time.c b/media/libdrm/mobile1/src/objmng/drm_time.c
new file mode 100644
index 0000000..fceb4952
--- /dev/null
+++ b/media/libdrm/mobile1/src/objmng/drm_time.c
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+
+/**
+ * @file
+ * DRM 1.0 Reference Port: linux implementation of drm_time.c.
+ */
+
+#include <objmng/drm_time.h>
+#include <unistd.h>
+
+/* See drm_time.h */
+uint32_t DRM_time_getElapsedSecondsFrom1970(void)
+{
+    return time(NULL);
+}
+
+/* See drm_time.h */
+void DRM_time_sleep(uint32_t ms)
+{
+    usleep(ms * 1000);
+}
+
+/* See drm_time.h */
+void DRM_time_getSysTime(T_DB_TIME_SysTime *time_ptr)
+{
+    time_t t;
+    struct tm *tm_t;
+
+    time(&t);
+    tm_t = gmtime(&t);
+
+    time_ptr->year = tm_t->tm_year + 1900;
+    time_ptr->month = tm_t->tm_mon + 1;
+    time_ptr->day = tm_t->tm_mday;
+    time_ptr->hour = tm_t->tm_hour;
+    time_ptr->min = tm_t->tm_min;
+    time_ptr->sec = tm_t->tm_sec;
+}
diff --git a/media/libdrm/mobile1/src/parser/parser_dcf.c b/media/libdrm/mobile1/src/parser/parser_dcf.c
new file mode 100644
index 0000000..06aa830
--- /dev/null
+++ b/media/libdrm/mobile1/src/parser/parser_dcf.c
@@ -0,0 +1,125 @@
+/*
+ * 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.
+ */
+
+#include <parser_dcf.h>
+#include <svc_drm.h>
+
+static int32_t drm_parseUintVar(uint8_t * buffer, uint8_t * len)
+{
+    int32_t i;
+    int32_t byteLen;
+    int32_t sum;
+
+    if (NULL == buffer)
+        return DRM_UINT_VAR_ERR;
+
+    byteLen = 0;
+    while ((buffer[byteLen] & UINT_VAR_FLAG) > 0 && byteLen < MAX_UINT_VAR_BYTE) /* UINT_VAR_FLAG == 0x80 */
+        byteLen++;
+
+    if (byteLen >= MAX_UINT_VAR_BYTE) /* MAX_UINT_VAR_BYTE == 5 */
+        return DRM_UINT_VAR_ERR; /* The var int is too large, and that is impossible */
+
+    *len = (uint8_t)(byteLen + 1);
+    sum = buffer[byteLen];
+    for (i = byteLen - 1; i >= 0; i--)
+        sum += ((buffer[i] & UINT_VAR_DATA) << 7 * (byteLen - i)); /* UINT_VAR_DATA == 0x7F */
+
+    return sum;
+}
+
+/* See parser_dcf.h */
+int32_t drm_dcfParser(uint8_t *buffer, int32_t bufferLen, T_DRM_DCF_Info *pDcfInfo,
+                      uint8_t **ppEncryptedData)
+{
+    uint8_t *tmpBuf;
+    uint8_t *pStart, *pEnd;
+    uint8_t *pHeader, *pData;
+    uint8_t varLen;
+
+    if (NULL == buffer || bufferLen <= 0 || NULL == pDcfInfo)
+        return FALSE;
+
+    tmpBuf = buffer;
+    /* 1. Parse the version, content-type and content-url */
+    pDcfInfo->Version = *(tmpBuf++);
+    if (0x01 != pDcfInfo->Version) /* Because it is OMA DRM v1.0, the vension must be 1 */
+        return FALSE;
+    pDcfInfo->ContentTypeLen = *(tmpBuf++);
+    pDcfInfo->ContentURILen = *(tmpBuf++);
+    strncpy((char *)pDcfInfo->ContentType, (char *)tmpBuf, pDcfInfo->ContentTypeLen);
+    tmpBuf += pDcfInfo->ContentTypeLen;
+    strncpy((char *)pDcfInfo->ContentURI, (char *)tmpBuf, pDcfInfo->ContentURILen);
+    tmpBuf += pDcfInfo->ContentURILen;
+
+    /* 2. Get the headers length and data length */
+    pDcfInfo->HeadersLen = drm_parseUintVar(tmpBuf, &varLen);
+    if (DRM_UINT_VAR_ERR == pDcfInfo->HeadersLen)
+        return FALSE;
+    tmpBuf += varLen;
+    pDcfInfo->DecryptedDataLen = DRM_UNKNOWN_DATA_LEN;
+    pDcfInfo->EncryptedDataLen = drm_parseUintVar(tmpBuf, &varLen);
+    if (DRM_UINT_VAR_ERR == pDcfInfo->EncryptedDataLen)
+        return FALSE;
+    tmpBuf += varLen;
+    pHeader = tmpBuf;
+    tmpBuf += pDcfInfo->HeadersLen;
+    pData = tmpBuf;
+
+    /* 3. Parse the headers */
+    pStart = pHeader;
+    while (pStart < pData) {
+        pEnd = pStart;
+        while ('\r' != *pEnd && pEnd < pData)
+            pEnd++;
+
+        if (0 == strncmp((char *)pStart, HEADER_ENCRYPTION_METHOD, HEADER_ENCRYPTION_METHOD_LEN))
+            strncpy((char *)pDcfInfo->Encryption_Method,
+                         (char *)(pStart + HEADER_ENCRYPTION_METHOD_LEN),
+                         pEnd - pStart - HEADER_ENCRYPTION_METHOD_LEN);
+        else if (0 == strncmp((char *)pStart, HEADER_RIGHTS_ISSUER, HEADER_RIGHTS_ISSUER_LEN))
+            strncpy((char *)pDcfInfo->Rights_Issuer,
+                         (char *)(pStart + HEADER_RIGHTS_ISSUER_LEN),
+                         pEnd - pStart - HEADER_RIGHTS_ISSUER_LEN);
+        else if (0 == strncmp((char *)pStart, HEADER_CONTENT_NAME, HEADER_CONTENT_NAME_LEN))
+            strncpy((char *)pDcfInfo->Content_Name,
+                         (char *)(pStart + HEADER_CONTENT_NAME_LEN),
+                         pEnd - pStart - HEADER_CONTENT_NAME_LEN);
+        else if (0 == strncmp((char *)pStart, HEADER_CONTENT_DESCRIPTION, HEADER_CONTENT_DESCRIPTION_LEN))
+            strncpy((char *)pDcfInfo->ContentDescription,
+                         (char *)(pStart + HEADER_CONTENT_DESCRIPTION_LEN),
+                         pEnd - pStart - HEADER_CONTENT_DESCRIPTION_LEN);
+        else if (0 == strncmp((char *)pStart, HEADER_CONTENT_VENDOR, HEADER_CONTENT_VENDOR_LEN))
+            strncpy((char *)pDcfInfo->ContentVendor,
+                         (char *)(pStart + HEADER_CONTENT_VENDOR_LEN),
+                         pEnd - pStart - HEADER_CONTENT_VENDOR_LEN);
+        else if (0 == strncmp((char *)pStart, HEADER_ICON_URI, HEADER_ICON_URI_LEN))
+            strncpy((char *)pDcfInfo->Icon_URI,
+                         (char *)(pStart + HEADER_ICON_URI_LEN),
+                         pEnd - pStart - HEADER_ICON_URI_LEN);
+
+        if ('\n' == *(pEnd + 1))
+            pStart = pEnd + 2;  /* Two bytes: a '\r' and a '\n' */
+        else
+            pStart = pEnd + 1;
+    }
+
+    /* 4. Give out the location of encrypted data */
+    if (NULL != ppEncryptedData)
+        *ppEncryptedData = pData;
+
+    return TRUE;
+}
diff --git a/media/libdrm/mobile1/src/parser/parser_dm.c b/media/libdrm/mobile1/src/parser/parser_dm.c
new file mode 100644
index 0000000..567e650
--- /dev/null
+++ b/media/libdrm/mobile1/src/parser/parser_dm.c
@@ -0,0 +1,271 @@
+/*
+ * 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.
+ */
+
+#include <parser_dm.h>
+#include <parser_dcf.h>
+#include <svc_drm.h>
+#include "log.h"
+
+#define DRM_SKIP_SPACE_TAB(p) while( (*(p) == ' ') || (*(p) == '\t') ) \
+                                  p++
+
+typedef enum _DM_PARSE_STATUS {
+    DM_PARSE_START,
+    DM_PARSING_RIGHTS,
+    DM_PARSING_CONTENT,
+    DM_PARSE_END
+} DM_PARSE_STATUS;
+
+static int drm_strnicmp(const uint8_t* s1, const uint8_t* s2, int32_t n)
+{
+    if (n < 0 || NULL == s1 || NULL == s2)
+        return -1;
+
+    if (n == 0)
+        return 0;
+
+    while (n-- != 0 && tolower(*s1) == tolower(*s2))
+    {
+        if (n == 0 || *s1 == '\0' || *s2 == '\0')
+            break;
+        s1++;
+        s2++;
+    }
+
+    return tolower(*s1) - tolower(*s2);
+}
+
+const uint8_t * drm_strnstr(const uint8_t * str, const uint8_t * strSearch, int32_t len)
+{
+    int32_t i, stringLen;
+
+    if (NULL == str || NULL == strSearch || len <= 0)
+        return NULL;
+
+    stringLen = strlen((char *)strSearch);
+    for (i = 0; i < len - stringLen + 1; i++) {
+        if (str[i] == *strSearch && 0 == memcmp(str + i, strSearch, stringLen))
+            return str + i;
+    }
+    return NULL;
+}
+
+/* See parser_dm.h */
+int32_t drm_parseDM(const uint8_t *buffer, int32_t bufferLen, T_DRM_DM_Info *pDmInfo)
+{
+    const uint8_t *pStart = NULL, *pEnd = NULL;
+    const uint8_t *pBufferEnd;
+    int32_t contentLen, leftLen;
+    DM_PARSE_STATUS status = DM_PARSE_START;
+    int32_t boundaryLen;
+
+    if (NULL == buffer || bufferLen <= 0 || NULL == pDmInfo)
+        return FALSE;
+
+    /* Find the end of the input buffer */
+    pBufferEnd = buffer + bufferLen;
+    leftLen = bufferLen;
+
+    /* Find out the boundary */
+    pStart = drm_strnstr(buffer, (uint8_t *)"--", bufferLen);
+    if (NULL == pStart)
+        return FALSE; /* No boundary error */
+    pEnd = pStart;
+
+    /* Record the boundary */
+    pEnd = drm_strnstr(pStart, (uint8_t *)DRM_NEW_LINE_CRLF, leftLen);
+    /* if can not find the CRLF, return FALSE */
+    if (NULL == pEnd)
+        return FALSE;
+    strncpy((char *)pDmInfo->boundary, (char *)pStart, pEnd - pStart);
+    boundaryLen = strlen((char *)pDmInfo->boundary) + 2; /* 2 means: '\r' and '\n' */
+
+    pEnd += 2; /* skip the '\r' and '\n' */
+    pStart = pEnd;
+    leftLen = pBufferEnd - pStart;
+    do {
+        pDmInfo->transferEncoding = DRM_MESSAGE_CODING_7BIT; /* According RFC2045 chapter 6.1, the default value should be 7bit.*/
+        strcpy((char *)pDmInfo->contentType, "text/plain");  /* According RFC2045 chapter 5.2, the default value should be "text/plain". */
+
+        /* Deal the header information */
+        while ((('\r' != *pStart) || ('\n' != *(pStart + 1))) && pStart < pBufferEnd) {
+            pEnd = drm_strnstr(pStart, (uint8_t *)DRM_NEW_LINE_CRLF, leftLen);
+            if (NULL == pEnd)
+                return FALSE;
+
+            if (0 != pDmInfo->deliveryType) { /* This means the delivery type has been confirmed */
+                if (0 == strncmp((char *)pStart, HEADERS_TRANSFER_CODING, HEADERS_TRANSFER_CODING_LEN)) {
+                    pStart += HEADERS_TRANSFER_CODING_LEN;
+                    DRM_SKIP_SPACE_TAB(pStart);
+
+                    if (0 == strncmp((char *)pStart, TRANSFER_CODING_TYPE_7BIT, pEnd - pStart))
+                        pDmInfo->transferEncoding = DRM_MESSAGE_CODING_7BIT;
+                    else if (0 == strncmp((char *)pStart, TRANSFER_CODING_TYPE_8BIT, pEnd - pStart))
+                        pDmInfo->transferEncoding = DRM_MESSAGE_CODING_8BIT;
+                    else if (0 == strncmp((char *)pStart, TRANSFER_CODING_TYPE_BINARY, pEnd - pStart))
+                        pDmInfo->transferEncoding = DRM_MESSAGE_CODING_BINARY;
+                    else if (0 == strncmp((char *)pStart, TRANSFER_CODING_TYPE_BASE64, pEnd - pStart))
+                        pDmInfo->transferEncoding = DRM_MESSAGE_CODING_BASE64;
+                    else
+                        return FALSE; /* Unknown transferCoding error */
+                } else if (0 == drm_strnicmp(pStart, (uint8_t *)HEADERS_CONTENT_TYPE, HEADERS_CONTENT_TYPE_LEN)) {
+                    pStart += HEADERS_CONTENT_TYPE_LEN;
+                    DRM_SKIP_SPACE_TAB(pStart);
+
+                    if (pEnd - pStart > 0) {
+                        strncpy((char *)pDmInfo->contentType, (char *)pStart, pEnd - pStart);
+                        pDmInfo->contentType[pEnd - pStart] = '\0';
+                    }
+                } else if (0 == drm_strnicmp(pStart, (uint8_t *)HEADERS_CONTENT_ID, HEADERS_CONTENT_ID_LEN)) {
+                    uint8_t tmpBuf[MAX_CONTENT_ID] = {0};
+                    uint8_t *pTmp;
+
+                    pStart += HEADERS_CONTENT_ID_LEN;
+                    DRM_SKIP_SPACE_TAB(pStart);
+
+                    /* error: more than one content id */
+                    if(drm_strnstr(pStart, (uint8_t*)HEADERS_CONTENT_ID, pBufferEnd - pStart)){
+                        LOGD("drm_dmParser: error: more than one content id\r\n");
+                        return FALSE;
+                    }
+
+                    status = DM_PARSING_CONTENT; /* can go here means that the rights object has been parsed. */
+
+                    /* Change the format from <...> to cid:... */
+                    if (NULL != (pTmp = (uint8_t *)memchr((char *)pStart, '<', pEnd - pStart))) {
+                        strncpy((char *)tmpBuf, (char *)(pTmp + 1), pEnd - pTmp - 1);
+
+                        if (NULL != (pTmp = (uint8_t *)memchr((char *)tmpBuf, '>', pEnd - pTmp - 1))) {
+                            *pTmp = '\0';
+
+                            memset(pDmInfo->contentID, 0, MAX_CONTENT_ID);
+                            sprintf((char *)pDmInfo->contentID, "%s%s", "cid:", (int8_t *)tmpBuf);
+                        }
+                    }
+                }
+            } else { /* First confirm delivery type, Forward_Lock, Combined Delivery or Separate Delivery */
+                if (0 == drm_strnicmp(pStart, (uint8_t *)HEADERS_CONTENT_TYPE, HEADERS_CONTENT_TYPE_LEN)) {
+                    pStart += HEADERS_CONTENT_TYPE_LEN;
+                    DRM_SKIP_SPACE_TAB(pStart);
+
+                    if (pEnd - pStart > 0) {
+                        strncpy((char *)pDmInfo->contentType, (char *)pStart, pEnd - pStart);
+                        pDmInfo->contentType[pEnd - pStart] = '\0';
+                    }
+
+                    if (0 == strcmp((char *)pDmInfo->contentType, DRM_MIME_TYPE_RIGHTS_XML)) {
+                        pDmInfo->deliveryType = COMBINED_DELIVERY;
+                        status = DM_PARSING_RIGHTS;
+                    }
+                    else if (0 == strcmp((char *)pDmInfo->contentType, DRM_MIME_TYPE_CONTENT)) {
+                        pDmInfo->deliveryType = SEPARATE_DELIVERY_FL;
+                        status = DM_PARSING_CONTENT;
+                    }
+                    else if (0 == pDmInfo->deliveryType) {
+                        pDmInfo->deliveryType = FORWARD_LOCK;
+                        status = DM_PARSING_CONTENT;
+                    }
+                }
+            }
+            pEnd += 2; /* skip the '\r' and '\n' */
+            pStart = pEnd;
+            leftLen = pBufferEnd - pStart;
+        }
+        pStart += 2; /* skip the second CRLF: "\r\n" */
+        pEnd = pStart;
+
+        /* Deal the content part, including rel or real content */
+        while (leftLen > 0) {
+            if (NULL == (pEnd = memchr(pEnd, '\r', leftLen))) {
+                pEnd = pBufferEnd;
+                break; /* no boundary found */
+            }
+
+            leftLen = pBufferEnd - pEnd;
+            if (leftLen < boundaryLen) {
+                pEnd = pBufferEnd;
+                break; /* here means may be the boundary has been split */
+            }
+
+            if (('\n' == *(pEnd + 1)) && (0 == memcmp(pEnd + 2, pDmInfo->boundary, strlen((char *)pDmInfo->boundary))))
+                break; /* find the boundary here */
+
+            pEnd++;
+            leftLen--;
+        }
+
+        if (pEnd >= pBufferEnd)
+            contentLen = DRM_UNKNOWN_DATA_LEN;
+        else
+            contentLen = pEnd - pStart;
+
+        switch(pDmInfo->deliveryType) {
+        case FORWARD_LOCK:
+            pDmInfo->contentLen = contentLen;
+            pDmInfo->contentOffset = pStart - buffer;
+            status = DM_PARSE_END;
+            break;
+        case COMBINED_DELIVERY:
+            if (DM_PARSING_RIGHTS == status) {
+                pDmInfo->rightsLen = contentLen;
+                pDmInfo->rightsOffset = pStart - buffer;
+            } else {
+                pDmInfo->contentLen = contentLen;
+                pDmInfo->contentOffset = pStart - buffer;
+                status = DM_PARSE_END;
+            }
+            break;
+        case SEPARATE_DELIVERY_FL:
+            {
+                T_DRM_DCF_Info dcfInfo;
+                uint8_t* pEncData = NULL;
+
+                memset(&dcfInfo, 0, sizeof(T_DRM_DCF_Info));
+                if (DRM_UNKNOWN_DATA_LEN == contentLen)
+                    contentLen = pEnd - pStart;
+                if (FALSE == drm_dcfParser(pStart, contentLen, &dcfInfo, &pEncData))
+                    return FALSE;
+
+                pDmInfo->contentLen = dcfInfo.EncryptedDataLen;
+                pDmInfo->contentOffset = pEncData - buffer;
+                strcpy((char *)pDmInfo->contentType, (char *)dcfInfo.ContentType);
+                strcpy((char *)pDmInfo->contentID, (char *)dcfInfo.ContentURI);
+                strcpy((char *)pDmInfo->rightsIssuer, (char *)dcfInfo.Rights_Issuer);
+                status = DM_PARSE_END;
+            }
+            break;
+        default:
+            return FALSE;
+        }
+
+        if (DM_PARSING_RIGHTS == status) {
+            /* Here means the rights object data has been completed, boundary must exist */
+            leftLen = pBufferEnd - pEnd;
+            pStart = drm_strnstr(pEnd, pDmInfo->boundary, leftLen);
+            if (NULL == pStart)
+                return FALSE;
+            leftLen = pBufferEnd - pStart;
+            pEnd = drm_strnstr(pStart, (uint8_t *)DRM_NEW_LINE_CRLF, leftLen);
+            if (NULL == pEnd)
+                return FALSE; /* only rights object, no media object, error */
+
+            pEnd += 2; /* skip the "\r\n" */
+            pStart = pEnd;
+        }
+    } while (DM_PARSE_END != status);
+
+    return TRUE;
+}
diff --git a/media/libdrm/mobile1/src/parser/parser_rel.c b/media/libdrm/mobile1/src/parser/parser_rel.c
new file mode 100644
index 0000000..537fa9ce
--- /dev/null
+++ b/media/libdrm/mobile1/src/parser/parser_rel.c
@@ -0,0 +1,663 @@
+/*
+ * 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.
+ */
+
+#include <parser_rel.h>
+#include <parser_dm.h>
+#include <xml_tinyParser.h>
+#include <wbxml_tinyparser.h>
+#include <drm_decoder.h>
+#include <svc_drm.h>
+
+/* See parser_rel.h */
+int32_t drm_monthDays(int32_t year, int32_t month)
+{
+    switch (month) {
+    case 1:
+    case 3:
+    case 5:
+    case 7:
+    case 8:
+    case 10:
+    case 12:
+        return 31;
+    case 4:
+    case 6:
+    case 9:
+    case 11:
+        return 30;
+    case 2:
+        if (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0))
+            return 29;
+        else
+            return 28;
+    default:
+        return -1;
+    }
+}
+
+int32_t drm_checkDate(int32_t year, int32_t month, int32_t day,
+                      int32_t hour, int32_t min, int32_t sec)
+{
+    if (month >= 1 && month <= 12 &&
+        day >= 1 && day <= drm_monthDays(year, month) &&
+        hour >= 0 && hour <= 23 &&
+        min >= 0 && min <= 59 && sec >= 0 && sec <= 59)
+        return 0;
+    else
+        return -1;
+}
+
+static int32_t drm_getStartEndTime(uint8_t * pValue, int32_t valueLen,
+                                   T_DRM_DATETIME * dateTime)
+{
+    int32_t year, mon, day, hour, min, sec;
+    uint8_t pTmp[64] = {0};
+
+    strncpy((char *)pTmp, (char *)pValue, valueLen);
+    {
+        uint8_t * pHead = pTmp;
+        uint8_t * pEnd = NULL;
+        uint8_t tmpByte;
+
+        /** get year */
+        pEnd = (uint8_t *)strstr((char *)pHead, "-");
+        if(NULL == pEnd)
+            return FALSE;
+        tmpByte = *pEnd;
+        *pEnd = '\0';
+        year = atoi((char *)pHead);
+        pHead = pEnd + 1;
+        *pEnd = tmpByte;
+
+        /** get month */
+        pEnd = (uint8_t *)strstr((char *)pHead, "-");
+        if(NULL == pEnd)
+            return FALSE;
+        tmpByte = *pEnd;
+        *pEnd = '\0';
+        mon = atoi((char *)pHead);
+        pHead = pEnd + 1;
+        *pEnd = tmpByte;
+
+        /** get day */
+        pEnd = (uint8_t *)strstr((char *)pHead, "T");
+        if(NULL == pEnd)
+            return FALSE;
+        tmpByte = *pEnd;
+        *pEnd = '\0';
+        day = atoi((char *)pHead);
+        pHead = pEnd + 1;
+        *pEnd = tmpByte;
+
+        /** get hour */
+        pEnd = (uint8_t *)strstr((char *)pHead, ":");
+        if(NULL == pEnd)
+            return FALSE;
+        tmpByte = *pEnd;
+        *pEnd = '\0';
+        hour = atoi((char *)pHead);
+        pHead = pEnd + 1;
+        *pEnd = tmpByte;
+
+        /** get minute */
+        pEnd = (uint8_t *)strstr((char *)pHead, ":");
+        if(NULL == pEnd)
+            return FALSE;
+        tmpByte = *pEnd;
+        *pEnd = '\0';
+        min = atoi((char *)pHead);
+        pHead = pEnd + 1;
+        *pEnd = tmpByte;
+
+        /** get second */
+        sec = atoi((char *)pHead);
+    }
+    if (0 != drm_checkDate(year, mon, day, hour, min, sec))
+        return FALSE;
+
+    YMD_HMS_2_INT(year, mon, day, dateTime->date, hour, min, sec,
+                  dateTime->time);
+    return TRUE;
+}
+
+static int32_t drm_checkWhetherHasUnknowConstraint(uint8_t* drm_constrain)
+{
+    char* begin_constrain = "<o-ex:constraint>";
+    char* end_constrain = "</o-ex:constraint>";
+    char* constrain_begin = strstr((char*)drm_constrain,begin_constrain);
+    char* constrain_end = strstr((char*)drm_constrain,end_constrain);
+    uint32_t constrain_len = 0;
+
+    if(NULL == constrain_begin)
+        return FALSE;
+
+    if(NULL == constrain_end)
+        return TRUE;
+
+    /* compute valid characters length */
+    {
+        uint32_t constrain_begin_len = strlen(begin_constrain);
+        char* cur_pos = constrain_begin + constrain_begin_len;
+
+        constrain_len = (constrain_end - constrain_begin) - constrain_begin_len;
+
+        while(cur_pos < constrain_end){
+            if(isspace(*cur_pos))
+                constrain_len--;
+
+            cur_pos++;
+        }
+    }
+
+    /* check all constraints */
+    {
+        #define DRM_ALL_CONSTRAINT_COUNT 5
+
+        int32_t i = 0;
+        int32_t has_datetime = FALSE;
+        int32_t has_start_or_end = FALSE;
+
+        char* all_vaild_constraints[DRM_ALL_CONSTRAINT_COUNT][2] = {
+            {"<o-dd:count>","</o-dd:count>"},
+            {"<o-dd:interval>","</o-dd:interval>"},
+            {"<o-dd:datetime>","</o-dd:datetime>"},
+            {"<o-dd:start>","</o-dd:start>"},
+            {"<o-dd:end>","</o-dd:end>"}
+        };
+
+        for(i = 0; i < DRM_ALL_CONSTRAINT_COUNT; i++){
+            char*start = strstr((char*)drm_constrain,all_vaild_constraints[i][0]);
+
+            if(start && (start < constrain_end)){
+                char* end = strstr((char*)drm_constrain,all_vaild_constraints[i][1]);
+
+                if(end && (end < constrain_end)){
+                    if(0 == strncmp(all_vaild_constraints[i][0],"<o-dd:datetime>",strlen("<o-dd:datetime>"))){
+                        constrain_len -= strlen(all_vaild_constraints[i][0]);
+                        constrain_len -= strlen(all_vaild_constraints[i][1]);
+
+                        if(0 == constrain_len)
+                            return TRUE;
+
+                        has_datetime = TRUE;
+                        continue;
+                    }
+
+                    if((0 == strncmp(all_vaild_constraints[i][0],"<o-dd:start>",strlen("<o-dd:start>")))
+                        || (0 == strncmp(all_vaild_constraints[i][0],"<o-dd:end>",strlen("<o-dd:end>")))){
+                        if(FALSE == has_datetime)
+                            return TRUE;
+                        else
+                            has_start_or_end = TRUE;
+                    }
+
+                    constrain_len -= (end - start);
+                    constrain_len -= strlen(all_vaild_constraints[i][1]);
+
+                    if(0 == constrain_len)
+                        if(has_datetime != has_start_or_end)
+                            return TRUE;
+                        else
+                            return FALSE;
+                }
+                else
+                    return TRUE;
+            }
+        }
+
+        if(has_datetime != has_start_or_end)
+            return TRUE;
+
+        if(constrain_len)
+            return TRUE;
+        else
+            return FALSE;
+    }
+}
+
+static int32_t drm_getRightValue(uint8_t * buffer, int32_t bufferLen,
+                                 T_DRM_Rights * ro, uint8_t * operation,
+                                 uint8_t oper_char)
+{
+    uint8_t *pBuf, *pValue;
+    uint8_t sProperty[256];
+    int32_t valueLen;
+    int32_t year, mon, day, hour, min, sec;
+    T_DRM_Rights_Constraint *pConstraint;
+    int32_t *bIsAble;
+    uint8_t *ret = NULL;
+    int32_t flag = 0;
+
+    if (operation == NULL) {
+        switch (oper_char) {
+        case REL_TAG_PLAY:
+            pConstraint = &(ro->PlayConstraint);
+            bIsAble = &(ro->bIsPlayable);
+            break;
+        case REL_TAG_DISPLAY:
+            pConstraint = &(ro->DisplayConstraint);
+            bIsAble = &(ro->bIsDisplayable);
+            break;
+        case REL_TAG_EXECUTE:
+            pConstraint = &(ro->ExecuteConstraint);
+            bIsAble = &(ro->bIsExecuteable);
+            break;
+        case REL_TAG_PRINT:
+            pConstraint = &(ro->PrintConstraint);
+            bIsAble = &(ro->bIsPrintable);
+            break;
+        default:
+            return FALSE; /* The input parm is err */
+        }
+    } else {
+        if (strcmp((char *)operation, "play") == 0) {
+            pConstraint = &(ro->PlayConstraint);
+            bIsAble = &(ro->bIsPlayable);
+        } else if (strcmp((char *)operation, "display") == 0) {
+            pConstraint = &(ro->DisplayConstraint);
+            bIsAble = &(ro->bIsDisplayable);
+        } else if (strcmp((char *)operation, "execute") == 0) {
+            pConstraint = &(ro->ExecuteConstraint);
+            bIsAble = &(ro->bIsExecuteable);
+        } else if (strcmp((char *)operation, "print") == 0) {
+            pConstraint = &(ro->PrintConstraint);
+            bIsAble = &(ro->bIsPrintable);
+        } else
+            return FALSE; /* The input parm is err */
+    }
+
+    if (operation == NULL) {
+        sprintf((char *)sProperty, "%c%c%c%c", REL_TAG_RIGHTS,
+                     REL_TAG_AGREEMENT, REL_TAG_PERMISSION, oper_char);
+        ret = WBXML_DOM_getNode(buffer, bufferLen, sProperty);
+    } else {
+        sprintf((char *)sProperty,
+                     "o-ex:rights\\o-ex:agreement\\o-ex:permission\\o-dd:%s",
+                     operation);
+        ret = XML_DOM_getNode(buffer, sProperty);
+    }
+    CHECK_VALIDITY(ret);
+    if (NULL == ret)
+        return TRUE;
+    WRITE_RO_FLAG(*bIsAble, 1, pConstraint->Indicator, DRM_NO_CONSTRAINT); /* If exit first assume have utter rights */
+    flag = 1;
+
+    if (operation == NULL) { /* If father element node is not exit then return */
+        sprintf((char *)sProperty, "%c%c%c%c%c", REL_TAG_RIGHTS,
+                     REL_TAG_AGREEMENT, REL_TAG_PERMISSION, oper_char,
+                     REL_TAG_CONSTRAINT);
+        ret = WBXML_DOM_getNode(buffer, bufferLen, sProperty);
+    } else {
+        sprintf((char *)sProperty,
+                     "o-ex:rights\\o-ex:agreement\\o-ex:permission\\o-dd:%s\\o-ex:constraint",
+                     operation);
+        ret = XML_DOM_getNode(buffer, sProperty);
+    }
+
+    CHECK_VALIDITY(ret);
+    if (ret == NULL)
+        return TRUE;
+
+    if(TRUE == drm_checkWhetherHasUnknowConstraint(ret))
+        return FALSE;
+
+    *bIsAble = 0;
+    pConstraint->Indicator = DRM_NO_PERMISSION; /* If exit constraint assume have no rights */
+    flag = 2;
+
+    if (operation == NULL) {
+        sprintf((char *)sProperty, "%c%c%c%c%c%c", REL_TAG_RIGHTS,
+                     REL_TAG_AGREEMENT, REL_TAG_PERMISSION, oper_char,
+                     REL_TAG_CONSTRAINT, REL_TAG_INTERVAL);
+        pBuf =
+            WBXML_DOM_getNodeValue(buffer, bufferLen, sProperty, (uint8_t **)&pValue,
+                                   &valueLen);
+    } else {
+        sprintf((char *)sProperty,
+                     "o-ex:rights\\o-ex:agreement\\o-ex:permission\\o-dd:%s\\o-ex:constraint\\o-dd:interval",
+                     operation);
+        pBuf = XML_DOM_getNodeValue(buffer, sProperty, &pValue, &valueLen);
+    }
+    CHECK_VALIDITY(pBuf);
+    if (pBuf) { /* If interval element exit then get the value */
+        uint8_t pTmp[64] = {0};
+
+        strncpy((char *)pTmp, (char *)pValue, valueLen);
+        {
+            uint8_t * pHead = pTmp + 1;
+            uint8_t * pEnd = NULL;
+            uint8_t tmpChar;
+
+            /** get year */
+            pEnd = (uint8_t *)strstr((char *)pHead, "Y");
+            if(NULL == pEnd)
+                return FALSE;
+            tmpChar = *pEnd;
+            *pEnd = '\0';
+            year = atoi((char *)pHead);
+            pHead = pEnd + 1;
+            *pEnd = tmpChar;
+
+            /** get month */
+            pEnd = (uint8_t *)strstr((char *)pHead, "M");
+            if(NULL == pEnd)
+                return FALSE;
+            tmpChar = *pEnd;
+            *pEnd = '\0';
+            mon = atoi((char *)pHead);
+            pHead = pEnd + 1;
+            *pEnd = tmpChar;
+
+            /** get day */
+            pEnd = (uint8_t *)strstr((char *)pHead, "D");
+            if(NULL == pEnd)
+                return FALSE;
+            tmpChar = *pEnd;
+            *pEnd = '\0';
+            day = atoi((char *)pHead);
+            pHead = pEnd + 2;
+            *pEnd = tmpChar;
+
+            /** get hour */
+            pEnd = (uint8_t *)strstr((char *)pHead, "H");
+            if(NULL == pEnd)
+                return FALSE;
+            tmpChar = *pEnd;
+            *pEnd = '\0';
+            hour = atoi((char *)pHead);
+            pHead = pEnd + 1;
+            *pEnd = tmpChar;
+
+            /** get minute */
+            pEnd = (uint8_t *)strstr((char *)pHead, "M");
+            if(NULL == pEnd)
+                return FALSE;
+            tmpChar = *pEnd;
+            *pEnd = '\0';
+            min = atoi((char *)pHead);
+            pHead = pEnd + 1;
+            *pEnd = tmpChar;
+
+            /** get second */
+            pEnd = (uint8_t *)strstr((char *)pHead, "S");
+            if(NULL == pEnd)
+                return FALSE;
+            tmpChar = *pEnd;
+            *pEnd = '\0';
+            sec = atoi((char *)pHead);
+            pHead = pEnd + 1;
+            *pEnd = tmpChar;
+        }
+
+        if (year < 0 || mon < 0 || day < 0 || hour < 0
+            || min < 0 || sec < 0)
+            return FALSE;
+        YMD_HMS_2_INT(year, mon, day, pConstraint->Interval.date, hour,
+                      min, sec, pConstraint->Interval.time);
+        WRITE_RO_FLAG(*bIsAble, 1, pConstraint->Indicator,
+                      DRM_INTERVAL_CONSTRAINT);
+        flag = 3;
+    }
+
+    if (operation == NULL) {
+        sprintf((char *)sProperty, "%c%c%c%c%c%c", REL_TAG_RIGHTS,
+                     REL_TAG_AGREEMENT, REL_TAG_PERMISSION, oper_char,
+                     REL_TAG_CONSTRAINT, REL_TAG_COUNT);
+        pBuf =
+            WBXML_DOM_getNodeValue(buffer, bufferLen, sProperty, (uint8_t **)&pValue,
+                                   &valueLen);
+    } else {
+        sprintf((char *)sProperty,
+                     "o-ex:rights\\o-ex:agreement\\o-ex:permission\\o-dd:%s\\o-ex:constraint\\o-dd:count",
+                     operation);
+        pBuf = XML_DOM_getNodeValue(buffer, sProperty, &pValue, &valueLen);
+    }
+    CHECK_VALIDITY(pBuf);
+    if (pBuf) { /* If count element exit the  get the value */
+        uint8_t pTmp[16] = {0};
+        int32_t i;
+
+        for (i = 0; i < valueLen; i++) { /* Check the count format */
+            if (0 == isdigit(*(pValue + i)))
+                return FALSE;
+        }
+
+        strncpy((char *)pTmp, (char *)pValue, valueLen);
+        pConstraint->Count = atoi((char *)pTmp);
+
+    if(0 == pConstraint->Count)
+    {
+      WRITE_RO_FLAG(*bIsAble, 0, pConstraint->Indicator, DRM_NO_PERMISSION);
+    }
+    else if( pConstraint->Count > 0)
+    {
+      WRITE_RO_FLAG(*bIsAble, 1, pConstraint->Indicator, DRM_COUNT_CONSTRAINT);
+    }
+    else  /* < 0 */
+    {
+       return FALSE;
+    }
+
+        flag = 3;
+    }
+
+    if (operation == NULL) {
+        sprintf((char *)sProperty, "%c%c%c%c%c%c%c", REL_TAG_RIGHTS,
+                     REL_TAG_AGREEMENT, REL_TAG_PERMISSION, oper_char,
+                     REL_TAG_CONSTRAINT, REL_TAG_DATETIME, REL_TAG_START);
+        pBuf =
+            WBXML_DOM_getNodeValue(buffer, bufferLen, sProperty, (uint8_t **)&pValue,
+                                   &valueLen);
+    } else {
+        sprintf((char *)sProperty,
+                     "o-ex:rights\\o-ex:agreement\\o-ex:permission\\o-dd:%s\\o-ex:constraint\\o-dd:datetime\\o-dd:start",
+                     operation);
+        pBuf = XML_DOM_getNodeValue(buffer, sProperty, &pValue, &valueLen);
+    }
+    CHECK_VALIDITY(pBuf);
+    if (pBuf) { /* If start element exit then get the value */
+        if (FALSE ==
+            drm_getStartEndTime(pValue, valueLen, &pConstraint->StartTime))
+            return FALSE;
+        WRITE_RO_FLAG(*bIsAble, 1, pConstraint->Indicator, DRM_START_TIME_CONSTRAINT);
+        flag = 3;
+    }
+
+    if (operation == NULL) {
+        sprintf((char *)sProperty, "%c%c%c%c%c%c%c", REL_TAG_RIGHTS,
+                     REL_TAG_AGREEMENT, REL_TAG_PERMISSION, oper_char,
+                     REL_TAG_CONSTRAINT, REL_TAG_DATETIME, REL_TAG_END);
+        pBuf =
+            WBXML_DOM_getNodeValue(buffer, bufferLen, sProperty, (uint8_t **)&pValue,
+                                   &valueLen);
+    } else {
+        sprintf((char *)sProperty,
+                     "o-ex:rights\\o-ex:agreement\\o-ex:permission\\o-dd:%s\\o-ex:constraint\\o-dd:datetime\\o-dd:end",
+                     operation);
+        pBuf = XML_DOM_getNodeValue(buffer, sProperty, &pValue, &valueLen);
+    }
+    CHECK_VALIDITY(pBuf);
+    if (pBuf) {
+        if (FALSE ==
+            drm_getStartEndTime(pValue, valueLen, &pConstraint->EndTime))
+            return FALSE;
+        WRITE_RO_FLAG(*bIsAble, 1, pConstraint->Indicator, DRM_END_TIME_CONSTRAINT);
+        flag = 3;
+    }
+
+    if (2 == flag)
+        WRITE_RO_FLAG(*bIsAble, 1, pConstraint->Indicator, DRM_NO_CONSTRAINT); /* If exit first assume have utter rights */
+    return TRUE;
+}
+
+/* See parser_rel.h */
+int32_t drm_relParser(uint8_t* buffer, int32_t bufferLen, int32_t Format, T_DRM_Rights* pRights)
+{
+    uint8_t *pBuf, *pValue;
+    uint8_t sProperty[256];
+    int32_t valueLen;
+
+    if (TYPE_DRM_RIGHTS_WBXML != Format && TYPE_DRM_RIGHTS_XML != Format) /* It is not the support parse format */
+        return FALSE;
+
+    if (TYPE_DRM_RIGHTS_XML == Format) {
+        /* Check whether it is a CD, and parse it using TYPE_DRM_RIGHTS_XML */
+        if (NULL != drm_strnstr(buffer, (uint8_t *)HEADERS_CONTENT_ID, bufferLen))
+            return FALSE;
+
+        pBuf =
+            XML_DOM_getNodeValue(buffer,
+                                 (uint8_t *)"o-ex:rights\\o-ex:context\\o-dd:version",
+                                 &pValue, &valueLen);
+        CHECK_VALIDITY(pBuf);
+
+        if (pBuf) {
+            if (valueLen > 8) /* Check version lenth */
+                return FALSE;
+
+           /* error version */
+           if(strncmp(pValue,"1.0",valueLen))
+                return FALSE;
+
+            strncpy((char *)pRights->Version, (char *)pValue, valueLen);
+        } else
+            return FALSE;
+
+        /* this means there is more than one version label in rights */
+        if(strstr((char*)pBuf, "<o-dd:version>"))
+            return FALSE;
+
+        pBuf =
+            XML_DOM_getNodeValue(buffer,
+                                 (uint8_t *)"o-ex:rights\\o-ex:agreement\\o-ex:asset\\ds:KeyInfo\\ds:KeyValue",
+                                 &pValue, &valueLen);
+        CHECK_VALIDITY(pBuf);
+        if (pBuf) { /* Get keyvalue */
+            int32_t keyLen;
+
+            if (24 != valueLen)
+                return FALSE;
+
+            keyLen = drm_decodeBase64(NULL, 0, pValue, &valueLen);
+            if (keyLen < 0)
+                return FALSE;
+
+            if (DRM_KEY_LEN != drm_decodeBase64(pRights->KeyValue, keyLen, pValue, &valueLen))
+                return FALSE;
+        }
+
+        pBuf =
+            XML_DOM_getNodeValue(buffer,
+                                 (uint8_t *)"o-ex:rights\\o-ex:agreement\\o-ex:asset\\o-ex:context\\o-dd:uid",
+                                 &pValue, &valueLen);
+        CHECK_VALIDITY(pBuf);
+        if (pBuf) {
+            if (valueLen > DRM_UID_LEN)
+                return FALSE;
+            strncpy((char *)pRights->uid, (char *)pValue, valueLen);
+            pRights->uid[valueLen] = '\0';
+        } else
+            return FALSE;
+
+        /* this means there is more than one uid label in rights */
+        if(strstr((char*)pBuf, "<o-dd:uid>"))
+            return FALSE;
+
+        if (FALSE ==
+            drm_getRightValue(buffer, bufferLen, pRights, (uint8_t *)"play", 0))
+            return FALSE;
+
+        if (FALSE ==
+            drm_getRightValue(buffer, bufferLen, pRights, (uint8_t *)"display", 0))
+            return FALSE;
+
+        if (FALSE ==
+            drm_getRightValue(buffer, bufferLen, pRights, (uint8_t *)"execute", 0))
+            return FALSE;
+
+        if (FALSE ==
+            drm_getRightValue(buffer, bufferLen, pRights, (uint8_t *)"print", 0))
+            return FALSE;
+    } else if (TYPE_DRM_RIGHTS_WBXML == Format) {
+        if (!REL_CHECK_WBXML_HEADER(buffer))
+            return FALSE;
+
+        sprintf((char *)sProperty, "%c%c%c", REL_TAG_RIGHTS, REL_TAG_CONTEXT,
+                     REL_TAG_VERSION);
+        pBuf =
+            WBXML_DOM_getNodeValue(buffer, bufferLen, sProperty, (uint8_t **)&pValue,
+                                   &valueLen);
+        CHECK_VALIDITY(pBuf);
+
+        if (pBuf) {
+            if (valueLen > 8) /* Check version lenth */
+                return FALSE;
+            strncpy((char *)pRights->Version, (char *)pValue, valueLen);
+        } else
+            return FALSE;
+
+        sprintf((char *)sProperty, "%c%c%c%c%c",
+                     REL_TAG_RIGHTS, REL_TAG_AGREEMENT, REL_TAG_ASSET,
+                     REL_TAG_KEYINFO, REL_TAG_KEYVALUE);
+        pBuf =
+            WBXML_DOM_getNodeValue(buffer, bufferLen, sProperty, (uint8_t **)&pValue,
+                                   &valueLen);
+        CHECK_VALIDITY(pBuf);
+        if (pBuf) {
+            if (DRM_KEY_LEN != valueLen)
+                return FALSE;
+            memcpy(pRights->KeyValue, pValue, DRM_KEY_LEN);
+            memset(pValue, 0, DRM_KEY_LEN); /* Clean the KeyValue */
+        }
+
+        sprintf((char *)sProperty, "%c%c%c%c%c",
+                     REL_TAG_RIGHTS, REL_TAG_AGREEMENT, REL_TAG_ASSET,
+                     REL_TAG_CONTEXT, REL_TAG_UID);
+        pBuf =
+            WBXML_DOM_getNodeValue(buffer, bufferLen, sProperty, (uint8_t **)&pValue,
+                                   &valueLen);
+        CHECK_VALIDITY(pBuf);
+        if (pBuf) {
+            if (valueLen > DRM_UID_LEN)
+                return FALSE;
+            strncpy((char *)pRights->uid, (char *)pValue, valueLen);
+            pRights->uid[valueLen] = '\0';
+        } else
+            return FALSE;
+
+        if (FALSE ==
+            drm_getRightValue(buffer, bufferLen, pRights, NULL,
+                              REL_TAG_PLAY))
+            return FALSE;
+
+        if (FALSE ==
+            drm_getRightValue(buffer, bufferLen, pRights, NULL,
+                              REL_TAG_DISPLAY))
+            return FALSE;
+
+        if (FALSE ==
+            drm_getRightValue(buffer, bufferLen, pRights, NULL,
+                              REL_TAG_EXECUTE))
+            return FALSE;
+
+        if (FALSE ==
+            drm_getRightValue(buffer, bufferLen, pRights, NULL,
+                              REL_TAG_PRINT))
+            return FALSE;
+    }
+
+    return TRUE;
+}
diff --git a/media/libdrm/mobile1/src/xml/xml_tinyparser.c b/media/libdrm/mobile1/src/xml/xml_tinyparser.c
new file mode 100644
index 0000000..7580312
--- /dev/null
+++ b/media/libdrm/mobile1/src/xml/xml_tinyparser.c
@@ -0,0 +1,834 @@
+/*
+ * 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.
+ */
+
+#include <xml/xml_tinyParser.h>
+
+int32_t xml_errno;
+
+#ifdef XML_DOM_PARSER
+
+#define XML_IS_WHITESPACE(x) ((x) == '\t' || (x) == '\n' || (x) == ' ' || (x) == '\r')
+#define XML_IS_NAMECHAR(ch) (isalpha(ch) || isdigit(ch) || ch ==':' || \
+                             ch == '_' || ch == '-' || ch =='.')
+
+static uint8_t *xml_ignore_blank(uint8_t *buffer)
+{
+    if (NULL == buffer)
+        return NULL;
+
+    while (XML_IS_WHITESPACE(*buffer))
+        buffer++;
+
+    return buffer;
+}
+
+static uint8_t *xml_goto_tagend(uint8_t *buffer)
+{
+    int32_t nameLen, valueLen;
+    uint8_t *name, *value;
+
+    if (NULL == buffer)
+        return NULL;
+
+    /* Ignore the start-tag */
+    if (*buffer == '<') {
+        buffer++;
+        while (buffer != NULL && XML_IS_NAMECHAR(*buffer))
+            buffer++;
+        if (NULL == buffer)
+            return NULL;
+    }
+
+    do {
+        if (NULL == (buffer = xml_ignore_blank(buffer)))
+            return NULL;
+
+        if (*buffer == '>' || (*buffer == '/' && *(buffer + 1) == '>'))
+            return buffer;
+
+        if (NULL ==
+            XML_DOM_getAttr(buffer, &name, &nameLen, &value, &valueLen))
+            return NULL;
+
+        buffer = value + valueLen + 1;
+    } while (*buffer != '\0');
+
+    return NULL;
+}
+
+static uint8_t *xml_match_tag(uint8_t *buffer)
+{
+    int32_t tagLen, tagType, bal;
+
+    if (NULL == buffer)
+        return NULL;
+
+    bal = 0;
+    do {
+        if (NULL == (buffer = XML_DOM_getTag(buffer, &tagLen, &tagType)))
+            return NULL;
+
+        switch (tagType) {
+        case XML_TAG_SELF:
+        case XML_TAG_START:
+            if (NULL == (buffer = xml_goto_tagend(buffer + tagLen + 1)))
+                return NULL;
+            if (strncmp((char *)buffer, "/>", 2) == 0) {
+                buffer += 2;
+            } else {
+                bal++;
+            }
+            break;
+
+        case XML_TAG_END:
+            if (bal <= 0)
+                return NULL;
+            buffer = buffer + tagLen + 2;
+            bal--;
+            break;
+        }
+    } while (bal != 0);
+
+    return buffer;
+}
+
+uint8_t *XML_DOM_getAttr(uint8_t *buffer, uint8_t **pName, int32_t *nameLen,
+                      uint8_t **pValue, int32_t *valueLen)
+{
+    uint8_t charQuoted;
+
+    if (NULL == buffer) {
+        XML_ERROR(XML_ERROR_BUFFER_NULL);
+        return NULL;
+    }
+
+    /* Ignore the tag */
+    if (*buffer == '<') {
+        buffer++;
+        /* Ignore the STag */
+        while (buffer != NULL && XML_IS_NAMECHAR(*buffer))
+            buffer++;
+        if (NULL == buffer)
+            return NULL;
+    }
+
+    if (NULL == (buffer = xml_ignore_blank(buffer))) {
+        XML_ERROR(XML_ERROR_BUFFER_NULL);
+        return NULL;
+    }
+
+    /* Name */
+    *pName = buffer;
+    while (buffer != NULL && XML_IS_NAMECHAR(*buffer))
+        buffer++;
+    if (NULL == buffer) {
+        XML_ERROR(XML_ERROR_ATTR_NAME);
+        return NULL;
+    }
+    *nameLen = buffer - *pName;
+    if (*nameLen <= 0) {
+        XML_ERROR(XML_ERROR_ATTR_NAME);
+        return NULL;
+    }
+
+    /* '=' */
+    buffer = xml_ignore_blank(buffer);
+    if (NULL == buffer || *buffer != '=') {
+        XML_ERROR(XML_ERROR_ATTR_MISSED_EQUAL);
+        return NULL;
+    }
+
+    /* Value */
+    buffer++;
+    buffer = xml_ignore_blank(buffer);
+    if (NULL == buffer || (*buffer != '"' && *buffer != '\'')) {
+        XML_ERROR(XML_ERROR_ATTR_VALUE);
+        return NULL;
+    }
+    charQuoted = *buffer++;
+    *pValue = buffer;
+    while (*buffer != '\0' && *buffer != charQuoted)
+        buffer++;
+    if (*buffer != charQuoted) {
+        XML_ERROR(XML_ERROR_ATTR_VALUE);
+        return NULL;
+    }
+    *valueLen = buffer - *pValue;
+
+    XML_ERROR(XML_ERROR_OK);
+
+    return buffer + 1;
+}
+
+uint8_t *XML_DOM_getValue(uint8_t *buffer, uint8_t **pValue, int32_t *valueLen)
+{
+    uint8_t *pEnd;
+
+    if (NULL == buffer) {
+        XML_ERROR(XML_ERROR_BUFFER_NULL);
+        return NULL;
+    }
+
+    /* Ignore the STag */
+    if (*buffer == '<') {
+        buffer++;
+        /* If it's an end_tag, no value should be returned */
+        if (*buffer == '/') {
+            *valueLen = 0;
+            XML_ERROR(XML_ERROR_NOVALUE);
+            return NULL;
+        }
+
+        while (buffer != NULL && XML_IS_NAMECHAR(*buffer))
+            buffer++;
+        if (NULL == buffer) {
+            XML_ERROR(XML_ERROR_BUFFER_NULL);
+            return NULL;
+        }
+
+        if (NULL == (buffer = xml_goto_tagend(buffer))) {
+            XML_ERROR(XML_ERROR_PROPERTY_END);
+            return NULL;
+        }
+    }
+
+    /* <test/> node found */
+    if (*buffer == '/') {
+        if (*(buffer + 1) != '>') {
+            XML_ERROR(XML_ERROR_PROPERTY_END);
+            return NULL;
+        }
+        XML_ERROR(XML_ERROR_OK);
+        *valueLen = 0;
+        return buffer;
+    }
+
+    if (*buffer == '>')
+        buffer++;
+
+    if (NULL == (buffer = xml_ignore_blank(buffer))) {
+        XML_ERROR(XML_ERROR_BUFFER_NULL);
+        return NULL;
+    }
+
+    /* the following is a tag instead of the value */
+    if (*buffer == '<') { /* nono value, such as <test></test> */
+        buffer++;
+        if (*buffer != '/') {
+            XML_ERROR(XML_ERROR_ENDTAG);
+            return NULL;
+        }
+        *valueLen = 0;
+        XML_ERROR(XML_ERROR_OK);
+        return NULL;
+    }
+
+    *pValue = buffer;
+    pEnd = NULL;
+    while (*buffer != '\0' && *buffer != '<') {
+        if (!XML_IS_WHITESPACE(*buffer))
+            pEnd = buffer;
+        buffer++;
+    }
+    if (*buffer != '<' || pEnd == NULL) {
+        XML_ERROR(XML_ERROR_VALUE);
+        return NULL;
+    }
+
+    *valueLen = pEnd - *pValue + 1;
+
+    buffer++;
+    if (*buffer != '/') {
+        XML_ERROR(XML_ERROR_ENDTAG);
+        return NULL;
+    }
+
+    XML_ERROR(XML_ERROR_OK);
+
+    return buffer - 1;
+}
+
+uint8_t *XML_DOM_getTag(uint8_t *buffer, int32_t *tagLen, int32_t *tagType)
+{
+    uint8_t *pStart;
+
+    /* WARNING: <!-- --> comment is not supported in this verison */
+    if (NULL == buffer) {
+        XML_ERROR(XML_ERROR_BUFFER_NULL);
+        return NULL;
+    }
+
+    do {
+        while (*buffer != '<') {
+            if (*buffer == '\0') {
+                XML_ERROR(XML_ERROR_BUFFER_NULL);
+                return NULL;
+            }
+
+            if (*buffer == '\"' || *buffer == '\'') {
+                uint8_t charQuoted = *buffer;
+                buffer++;
+                while (*buffer != '\0' && *buffer != charQuoted)
+                    buffer++;
+                if (*buffer == '\0') {
+                    XML_ERROR(XML_ERROR_BUFFER_NULL);
+                    return NULL;
+                }
+            }
+            buffer++;
+        }
+        buffer++;
+    } while (*buffer == '!' || *buffer == '?');
+
+    pStart = buffer - 1;
+
+    if (*buffer == '/') {
+        buffer++;
+        *tagType = XML_TAG_END;
+    } else {
+        /* check here if it is self-end-tag */
+        uint8_t *pCheck = xml_goto_tagend(pStart);
+        if (pCheck == NULL) {
+            XML_ERROR(XML_ERROR_PROPERTY_END);
+            return NULL;
+        }
+
+        if (*pCheck == '>')
+            *tagType = XML_TAG_START;
+        else if (strncmp((char *)pCheck, "/>", 2) == 0)
+            *tagType = XML_TAG_SELF;
+        else {
+            XML_ERROR(XML_ERROR_PROPERTY_END);
+            return NULL;
+        }
+    }
+
+    while (buffer != NULL && XML_IS_NAMECHAR(*buffer))
+        buffer++;
+    if (NULL == buffer) {
+        XML_ERROR(XML_ERROR_BUFFER_NULL);
+        return NULL;
+    }
+
+    if (*tagType == XML_TAG_END)
+        *tagLen = buffer - pStart - 2;
+    else
+        *tagLen = buffer - pStart - 1;
+
+    XML_ERROR(XML_ERROR_OK);
+
+    return pStart;
+}
+
+uint8_t *XML_DOM_getNode(uint8_t *buffer, const uint8_t *const node)
+{
+    uint8_t *pStart;
+    uint8_t buf[XML_MAX_PROPERTY_LEN + 2];
+    uint8_t *nodeStr = buf;
+    uint8_t *retPtr = NULL;
+    int32_t tagLen, tagType;
+    uint8_t *lastNode = (uint8_t *)"";
+
+    if (NULL == buffer) {
+        XML_ERROR(XML_ERROR_BUFFER_NULL);
+        return NULL;
+    }
+
+    strncpy((char *)nodeStr, (char *)node, XML_MAX_PROPERTY_LEN);
+    strcat((char *)nodeStr, "\\");
+    pStart = (uint8_t *)strchr((char *)nodeStr, '\\');
+
+    while (pStart != NULL) {
+        *pStart = '\0';
+
+        /* get the first start_tag from buffer */
+        if (NULL == (buffer = XML_DOM_getTag(buffer, &tagLen, &tagType))) {
+            XML_ERROR(XML_ERROR_NO_SUCH_NODE);
+            return NULL;
+        }
+
+        if (tagType == XML_TAG_END) {
+            if (0 ==
+                strncmp((char *)lastNode, (char *)(buffer + 2), strlen((char *)lastNode)))
+                XML_ERROR(XML_ERROR_NO_SUCH_NODE);
+            else
+                XML_ERROR(XML_ERROR_NO_START_TAG);
+            return NULL;
+        }
+
+        /* wrong node, contiue to fetch the next node */
+        if ((int32_t) strlen((char *)nodeStr) != tagLen
+            || strncmp((char *)nodeStr, (char *)(buffer + 1), tagLen) != 0) {
+            /* we should ignore all the middle code */
+            buffer = xml_match_tag(buffer);
+            continue;
+        }
+
+        retPtr = buffer;        /* retPtr starts with '<xxx>' */
+        buffer += (tagLen + 1);
+
+        if (tagType == XML_TAG_SELF) {
+            nodeStr = pStart + 1;
+            break;
+        }
+
+        lastNode = nodeStr;
+        nodeStr = pStart + 1;
+        pStart = (uint8_t *)strchr((char *)nodeStr, '\\');
+    }
+
+    /* Check 5: nodeStr should be empty here */
+    if (*nodeStr != '\0') {
+        XML_ERROR(XML_ERROR_NO_SUCH_NODE);
+        return NULL;
+    }
+
+    XML_ERROR(XML_ERROR_OK);
+
+    return retPtr;
+}
+
+uint8_t *XML_DOM_getNodeValue(uint8_t *buffer, uint8_t *node,
+                           uint8_t **value, int32_t *valueLen)
+{
+    uint8_t *pStart;
+    uint8_t *lastTag;
+
+    if (NULL == node || NULL == buffer) {
+        XML_ERROR(XML_ERROR_BUFFER_NULL);
+        return NULL;
+    }
+
+    lastTag = node + strlen((char *)node) - 1;
+    while (lastTag >= node && *lastTag != '\\')
+        lastTag--;
+    lastTag++;
+
+    if (NULL == (pStart = XML_DOM_getNode(buffer, node)))
+        return NULL;
+
+    pStart += (strlen((char *)lastTag) + 1);
+
+    if (NULL == (pStart = xml_goto_tagend(pStart))) {
+        XML_ERROR(XML_ERROR_PROPERTY_END);
+        return NULL;
+    }
+
+    if (NULL == (pStart = XML_DOM_getValue(pStart, value, valueLen)))
+        return NULL;
+
+    /* Check the end tag */
+#ifdef XML_DOM_CHECK_ENDTAG
+    if (strncmp((char *)pStart, "/>", 2) == 0) {
+
+    } else if (strncmp((char *)lastTag, (char *)(pStart + 2), strlen((char *)lastTag)) !=
+               0) {
+        XML_ERROR(XML_ERROR_ENDTAG);
+        return NULL;
+    }
+#endif
+
+    XML_ERROR(XML_ERROR_OK);
+
+    return *value;
+}
+
+uint8_t *XML_DOM_getNextNode(uint8_t *buffer, uint8_t **pNodeName, int32_t *nodenameLen)
+{
+    int32_t tagType;
+
+    if (NULL == buffer)
+        return NULL;
+
+    do {
+        if (NULL ==
+            (buffer = XML_DOM_getTag(buffer + 1, nodenameLen, &tagType))) {
+            XML_ERROR(XML_ERROR_NO_SUCH_NODE);
+            return NULL;
+        }
+    } while (tagType == XML_TAG_END);
+
+    *pNodeName = buffer + 1;
+
+    XML_ERROR(XML_ERROR_OK);
+
+    return buffer;
+}
+
+#endif /* XML_DOM_PARSER */
+
+#ifdef WBXML_DOM_PARSER
+
+#ifdef WBXML_OLD_VERSION
+uint8_t *WBXML_DOM_getNode(uint8_t *buffer, int32_t bufferLen,
+                                 uint8_t *node)
+{
+    int32_t i = 0, j = 0;
+
+    if (NULL == buffer || node == NULL) {
+        XML_ERROR(XML_ERROR_BUFFER_NULL);
+        return NULL;
+    }
+
+    while (i < bufferLen) {
+        if (WBXML_GET_TAG(buffer[i]) == WBXML_GET_TAG(node[j])) {
+            j++;
+            if (node[j] == '\0')
+                break;
+
+            /* Check if there is the content(it should have content) */
+            if (!WBXML_HAS_CONTENT(buffer[i])) {
+                /*XML_ERROR(WBXML_ERROR_MISSED_CONTENT); */
+                XML_ERROR(XML_ERROR_NO_SUCH_NODE);
+                return NULL;
+            }
+
+            /* Ignore the attrib filed */
+            if (WBXML_HAS_ATTR(buffer[i])) {
+                while (i < bufferLen && buffer[i] != WBXML_ATTR_END)
+                    i++;
+                if (i >= bufferLen)
+                    break;
+            }
+        }
+        i++;
+
+        /* Ignore the content filed */
+        if (buffer[i] == WBXML_STR_I) {
+            while (i < bufferLen && buffer[i] != WBXML_END)
+                i++;
+            if (i >= bufferLen)
+                break;
+            i++;
+        }
+    }
+
+    if (i >= bufferLen) {
+        XML_ERROR(XML_ERROR_NO_SUCH_NODE);
+        return NULL;
+    }
+
+    XML_ERROR(XML_ERROR_OK);
+
+    return buffer + i + 1;
+}
+
+uint8_t *WBXML_DOM_getNodeValue(uint8_t *buffer, int32_t bufferLen,
+                                      uint8_t *node,
+                                      uint8_t **value, int32_t *valueLen)
+{
+    int32_t i;
+    uint8_t *pEnd;
+
+    *value = NULL;
+    *valueLen = 0;
+
+    pEnd = buffer + bufferLen;
+    buffer = WBXML_DOM_getNode(buffer, bufferLen, node);
+    if (NULL == buffer) {
+        XML_ERROR(XML_ERROR_NO_SUCH_NODE);
+        return NULL;
+    }
+
+    if (*buffer == WBXML_OPAUE) {
+        buffer++;
+        *valueLen = WBXML_GetUintVar(buffer, &i);
+        if (*valueLen < 0) {
+            XML_ERROR(WBXML_ERROR_MBUINT32);
+            return NULL;
+        }
+        buffer += i;
+        *value = buffer;
+        return *value;
+    }
+
+    if (*buffer != WBXML_STR_I) {
+        XML_ERROR(WBXML_ERROR_MISSED_STARTTAG);
+        return NULL;
+    }
+
+    buffer++;
+
+    i = 0;
+    while ((buffer + i) < pEnd && buffer[i] != WBXML_END)
+        i++;
+
+    if (buffer[i] != WBXML_END) {
+        XML_ERROR(WBXML_ERROR_MISSED_ENDTAG);
+        return NULL;
+    }
+
+    *value = buffer;
+    *valueLen = i;
+    XML_ERROR(XML_ERROR_OK);
+
+    return *value;
+}
+#endif /* WBXML_OLD_VERSION */
+
+#define MAX_UINT_VAR_BYTE                                    4
+#define UINTVAR_INVALID                                      -1
+int32_t WBXML_GetUintVar(const uint8_t *const buffer, int32_t *len)
+{
+    int32_t i, byteLen;
+    int32_t sum;
+
+    byteLen = 0;
+    while ((buffer[byteLen] & 0x80) > 0 && byteLen < MAX_UINT_VAR_BYTE)
+        byteLen++;
+
+    if (byteLen > MAX_UINT_VAR_BYTE)
+        return UINTVAR_INVALID;
+
+    *len = byteLen + 1;
+    sum = buffer[byteLen];
+    for (i = byteLen - 1; i >= 0; i--)
+        sum += ((buffer[i] & 0x7F) << 7 * (byteLen - i));
+
+    return sum;
+}
+
+XML_BOOL WBXML_DOM_Init(WBXML * pWbxml, uint8_t *buffer,
+                        int32_t bufferLen)
+{
+    int32_t num, len;
+
+    pWbxml->End = buffer + bufferLen;
+    pWbxml->version = *buffer++;
+    if (UINTVAR_INVALID == (num = WBXML_GetUintVar(buffer, &len)))
+        return XML_FALSE;
+    buffer += len;
+    pWbxml->publicid = num;
+    if (UINTVAR_INVALID == (num = WBXML_GetUintVar(buffer, &len)))
+        return XML_FALSE;
+    buffer += len;
+    pWbxml->charset = num;
+    if (UINTVAR_INVALID == (num = WBXML_GetUintVar(buffer, &len)))
+        return XML_FALSE;
+    buffer += len;
+    pWbxml->strTable = buffer;
+    pWbxml->strTableLen = num;
+    buffer += num;
+    pWbxml->curPtr = pWbxml->Content = buffer;
+    pWbxml->depth = 0;
+
+    return XML_TRUE;
+}
+
+void WBXML_DOM_Rewind(WBXML * pWbxml)
+{
+    pWbxml->curPtr = pWbxml->Content;
+}
+
+XML_BOOL WBXML_DOM_Eof(WBXML * pWbxml)
+{
+    if (pWbxml->curPtr > pWbxml->End)
+        return XML_TRUE;
+
+    return XML_FALSE;
+}
+
+uint8_t WBXML_DOM_GetTag(WBXML * pWbxml)
+{
+    uint8_t tagChar;
+
+    if (pWbxml->curPtr > pWbxml->End)
+        return XML_EOF;
+
+    tagChar = *pWbxml->curPtr;
+    pWbxml->curPtr++;
+
+    if (WBXML_GET_TAG(tagChar) == WBXML_CONTENT_END)
+        pWbxml->depth--;
+    else
+        pWbxml->depth++;
+
+    return tagChar;
+}
+
+uint8_t WBXML_DOM_GetChar(WBXML * pWbxml)
+{
+    return *pWbxml->curPtr++;
+}
+
+void WBXML_DOM_Seek(WBXML * pWbxml, int32_t offset)
+{
+    pWbxml->curPtr += offset;
+}
+
+uint8_t WBXML_DOM_GetUIntVar(WBXML * pWbxml)
+{
+    int32_t num, len;
+
+    num = WBXML_GetUintVar(pWbxml->curPtr, &len);
+    pWbxml->curPtr += len;
+
+    return (uint8_t)num;
+}
+
+#ifdef XML_TREE_STRUCTURE
+
+#ifdef DEBUG_MODE
+static int32_t malloc_times = 0;
+static int32_t free_times = 0;
+void XML_PrintMallocInfo()
+{
+    printf("====XML_PrintMallocInfo====\n");
+    printf(" Total malloc times:%d\n", malloc_times);
+    printf(" Total free   times:%d\n", free_times);
+    printf("===========================\n");
+}
+#endif
+
+void *xml_malloc(int32_t size)
+{
+#ifdef DEBUG_MODE
+    malloc_times++;
+#endif
+    return malloc(size);
+}
+
+void xml_free(void *buffer)
+{
+#ifdef DEBUG_MODE
+    free_times++;
+#endif
+    free(buffer);
+}
+
+XML_TREE *xml_tree_fillnode(uint8_t **buf, int32_t tagLen)
+{
+    XML_TREE *Tree;
+    uint8_t *pAttr, *pName, *pValue;
+    int32_t nameLen, valueLen;
+    uint8_t *buffer = *buf;
+
+    if (NULL == (Tree = (XML_TREE *) xml_malloc(sizeof(XML_TREE))))
+        return NULL;
+    memset(Tree, 0, sizeof(XML_TREE));
+
+    strncpy((char *)Tree->tag, (char *)++buffer, tagLen);
+    buffer += tagLen;
+    pAttr = buffer;
+
+    /* attribute */
+    while (NULL !=
+           (pAttr =
+            XML_DOM_getAttr(pAttr, &pName, &nameLen, &pValue,
+                            &valueLen))) {
+        XML_TREE_ATTR *attr;
+        if (NULL ==
+            (attr = (XML_TREE_ATTR *) xml_malloc(sizeof(XML_TREE_ATTR))))
+            return NULL;
+        memset(attr, 0, sizeof(XML_TREE_ATTR));
+        strncpy((char *)attr->name, (char *)pName, nameLen);
+        strncpy((char *)attr->value, (char *)pValue, valueLen);
+        buffer = pValue + valueLen + 1;
+
+        if (NULL != Tree->attr) // no attribute now
+            Tree->last_attr->next = attr;
+        else
+            Tree->attr = attr;
+        Tree->last_attr = attr;
+    }
+
+    /* value */
+    pAttr = XML_DOM_getValue(buffer, &pValue, &valueLen);
+    if (pAttr != NULL && valueLen > 0) {
+        strncpy((char *)Tree->value, (char *)pValue, valueLen);
+        buffer = pValue + valueLen;
+    }
+
+    *buf = buffer;
+    return Tree;
+}
+
+XML_TREE *XML_makeTree(uint8_t **buf)
+{
+    uint8_t *pBuf;
+    int32_t valueLen, tagType;
+    uint8_t *buffer = *buf;
+    XML_TREE *TreeHead = NULL;
+
+    if (NULL == (buffer = XML_DOM_getTag(buffer, &valueLen, &tagType)))
+        return NULL;
+    if (XML_TAG_END == tagType)
+        return NULL;
+    if (NULL == (TreeHead = xml_tree_fillnode(&buffer, valueLen)))
+        return NULL;
+    if (XML_TAG_SELF == tagType) {
+        *buf = buffer;
+        return TreeHead;
+    }
+
+    do {
+        if (NULL == (pBuf = XML_DOM_getTag(buffer, &valueLen, &tagType)))
+            return NULL;
+
+        switch (tagType) {
+        case XML_TAG_SELF:
+        case XML_TAG_START:
+            if (NULL == TreeHead->child)
+                TreeHead->child = XML_makeTree(&buffer);
+            else if (NULL == TreeHead->child->last_brother) {
+                TreeHead->child->brother = XML_makeTree(&buffer);
+                TreeHead->child->last_brother = TreeHead->child->brother;
+            } else {
+                TreeHead->child->last_brother->brother =
+                    XML_makeTree(&buffer);
+                TreeHead->child->last_brother =
+                    TreeHead->child->last_brother->brother;
+            }
+            break;
+        case XML_TAG_END:
+            *buf = pBuf;
+            return TreeHead;
+        }
+        buffer++;
+    } while (1);
+}
+
+void XML_freeTree(XML_TREE * pTree)
+{
+    XML_TREE *p, *pNext;
+    XML_TREE_ATTR *pa, *lastpa;
+
+    if (NULL == pTree)
+        return;
+
+    p = pTree->brother;
+    while (NULL != p) {
+        pNext = p->brother;
+        p->brother = NULL;
+        XML_freeTree(p);
+        p = pNext;
+    }
+
+    if (NULL != pTree->child)
+        XML_freeTree(pTree->child);
+
+    pa = pTree->attr;
+    while (NULL != pa) {
+        lastpa = pa;
+        pa = pa->next;
+        xml_free(lastpa);
+    }
+    xml_free(pTree);
+}
+
+#endif /* XML_TREE_STRUCTURE */
+
+#endif /* WBXML_DOM_PARSER */
diff --git a/media/libdrm/mobile2/Android.mk b/media/libdrm/mobile2/Android.mk
new file mode 100644
index 0000000..e187139
--- /dev/null
+++ b/media/libdrm/mobile2/Android.mk
@@ -0,0 +1,79 @@
+LOCAL_PATH:= $(call my-dir)
+
+# ---------------------------------------
+# First project
+# 
+# Build DRM2 core library
+#
+# Output: libdrm2.so
+# ---------------------------------------
+include $(CLEAR_VARS)
+
+common_SRC_FILES := \
+    src/util/ustl-1.0/bktrace.cpp \
+    src/util/ustl-1.0/memblock.cpp \
+    src/util/ustl-1.0/ofstream.cpp \
+    src/util/ustl-1.0/ualgobase.cpp \
+    src/util/ustl-1.0/unew.cpp \
+    src/util/ustl-1.0/cmemlink.cpp \
+    src/util/ustl-1.0/memlink.cpp \
+    src/util/ustl-1.0/sistream.cpp \
+    src/util/ustl-1.0/ubitset.cpp \
+    src/util/ustl-1.0/ustdxept.cpp \
+    src/util/ustl-1.0/fstream.cpp \
+    src/util/ustl-1.0/mistream.cpp \
+    src/util/ustl-1.0/sostream.cpp \
+    src/util/ustl-1.0/uexception.cpp \
+    src/util/ustl-1.0/ustring.cpp \
+    src/util/xml/DomExpatAgent.cpp \
+    src/util/xml/ExpatWrapper.cpp \
+    src/util/xml/XMLDocumentImpl.cpp \
+    src/util/xml/XMLElementImpl.cpp \
+    src/util/domcore/CharacterDataImpl.cpp \
+    src/util/domcore/ElementImpl.cpp \
+    src/util/domcore/NodeListImpl.cpp \
+    src/util/domcore/DocumentImpl.cpp \
+    src/util/domcore/NodeImpl.cpp \
+    src/util/domcore/TextImpl.cpp \
+    src/util/domcore/DOMException.cpp \
+    src/util/domcore/NodeIterator.cpp \
+    src/util/crypto/DrmCrypto.cpp \
+    src/rights/RoManager.cpp \
+    src/rights/Asset.cpp \
+    src/rights/Ro.cpp \
+    src/rights/OperationPermission.cpp \
+    src/rights/Right.cpp \
+    src/rights/Constraint.cpp \
+    src/drmmanager/DrmManager.cpp \
+    src/dcf/DrmDcfCommon.cpp \
+    src/dcf/DrmDcfContainer.cpp \
+    src/dcf/DrmIStream.cpp \
+    src/dcf/DrmRawContent.cpp \
+    src/roap/RoapMessageHandler.cpp \
+    src/roap/Registration.cpp
+
+ifeq ($(TARGET_ARCH),arm)
+	LOCAL_CFLAGS += -fstrict-aliasing -fomit-frame-pointer
+endif
+
+common_CFLAGS := -W -g -DPLATFORM_ANDROID
+
+common_C_INCLUDES +=\
+    $(LOCAL_PATH)/include \
+    $(LOCAL_PATH)/src/util/ustl-1.0 \
+    external/expat/lib \
+    external/openssl    \
+    external/openssl/include
+
+LOCAL_SRC_FILES := $(common_SRC_FILES)
+LOCAL_CFLAGS += $(common_CFLAGS)
+LOCAL_C_INCLUDES += $(common_C_INCLUDES)
+
+LOCAL_SHARED_LIBRARIES := libexpat libcrypto
+LOCAL_MODULE := libdrm2 
+
+ifeq ($(TARGET_OS)-$(TARGET_ARCH),linux-x86)
+LOCAL_CFLAGS += -DUSTL_ANDROID_X86
+endif
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/media/libdrm/mobile2/include/Drm2CommonTypes.h b/media/libdrm/mobile2/include/Drm2CommonTypes.h
new file mode 100644
index 0000000..8ad3a731
--- /dev/null
+++ b/media/libdrm/mobile2/include/Drm2CommonTypes.h
@@ -0,0 +1,28 @@
+/*
+ * 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 _DRM2COMMONTYPES_H_
+#define _DRM2COMMONTYPES_H_
+#include <stdint.h>
+
+#ifdef DRM2_UT
+#define PROTECTED public
+#define PRIVATE public
+#else
+#define PROTECTED protected
+#define PRIVATE private
+#endif
+
+#endif
diff --git a/media/libdrm/mobile2/include/dcf/DrmDcfCommon.h b/media/libdrm/mobile2/include/dcf/DrmDcfCommon.h
new file mode 100644
index 0000000..9ca7b3f
--- /dev/null
+++ b/media/libdrm/mobile2/include/dcf/DrmDcfCommon.h
@@ -0,0 +1,192 @@
+/*
+ * 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 __DCF_COMM_H__
+#define __DCF_COMM_H__
+
+#include <Drm2CommonTypes.h>
+#include <arpa/inet.h>
+#include <mistream.h>
+#include <ustring.h>
+
+using namespace ustl;
+
+////DCF box type list
+const uint32_t DCF_CONTAINER_BOX = uint32_t('m' << 24 | 'r' << 16 | 'd' << 8 | 'o');
+const uint32_t DCF_USER_TYPE = uint32_t('d' << 24 | 'i' << 16 | 'u' << 8 | 'u');
+const uint32_t DCF_FILE_TYPE = uint32_t('p' << 24 | 'y' << 16 | 't' << 8 | 'f');
+const uint32_t DCF_FILE_BRAND = uint32_t('f' << 24 | 'c' << 16 | 'd' << 8 | 'o');
+
+
+/**
+ * The basic box class.
+ */
+class Box
+{
+public:
+    /**
+     * constructor for Box, used to parse Box
+     * \param box  Box data
+     */
+    Box(const uint8_t* box);
+
+    /**
+     * copy constructor for Box
+     * \param dcfBox  Box object used to init a new Box object
+     */
+    Box(const Box& dcfBox);
+
+    /**
+     * assignment operator for Box
+     * \param other  Box object used to assign to a exist Box object
+     */
+    Box& operator=(const Box& other);
+
+    /** Destructor for Box */
+    virtual ~Box();
+
+    /**
+     * get the size of Box
+     * \param none
+     * \return
+     *   the size
+     */
+    uint64_t getSize(void) const;
+
+    /**
+     * get the type of Box
+     * \param none
+     * \return
+     *   the type
+     */
+    uint32_t getType(void) const;
+
+    /**
+     * get the user type of Box
+     * \param none
+     * \return
+     *   the user type
+     */
+    const uint8_t* getUsertype(void) const;
+
+    /**
+     * get the length of Box
+     * \param none
+     * \return
+     *   the length
+     */
+    virtual uint32_t getLen(void) const;
+PRIVATE:
+    static const uint32_t USER_TYPE_LEN = 16;
+
+    uint32_t mSize;
+    uint32_t mType;
+    uint64_t mLargeSize;
+    uint8_t* mUserType;
+    uint32_t mBoxLength;
+};
+
+/**
+ * The fullBox class.
+ */
+class FullBox : public Box
+{
+public:
+    /**
+     * constructor for FullBox, used to parse FullBox
+     * \param fullBox  FullBox data
+     */
+    FullBox(const uint8_t* fullBox);
+
+    /** Destructor for FullBox */
+    virtual ~FullBox(){}
+
+    /**
+     * get the version of FullBox
+     * \param none
+     * \return
+     *   the version
+     */
+    uint8_t getVersion(void) const;
+
+    /**
+     * get the flag of FullBox
+     * \param none
+     * \return
+     *   the flag
+     */
+    const uint8_t* getFlag(void) const;
+
+    /**
+     * get the length of FullBox
+     * \param none
+     * \return
+     *   the length
+     */
+    virtual uint32_t getLen(void) const;
+PRIVATE:
+    static const uint32_t FLAG_LEN = 3;
+
+    uint8_t mVersion;
+    uint8_t mFlag[FLAG_LEN];
+    uint32_t mFullBoxLength;
+};
+
+////// textal header class
+class TextualHeader
+{
+public:
+    /** default constructor of DrmInStream */
+    TextualHeader(){};
+
+    /**
+     * constructor for TextualHeader, used to parse textal header
+     * \param inData  textal header data
+     */
+    TextualHeader(const string& inData);
+
+    /**
+     * get the name of textal header
+     * \param none
+     * \return
+     *   the name
+     */
+    string getName() const;
+
+    /**
+     * get the value of textal header
+     * \param none
+     * \return
+     *   the value
+     */
+    string getValue() const;
+
+    /**
+     * get the parameter of textal header
+     * \param none
+     * \return
+     *   the parameter
+     */
+    string getParam() const;
+PRIVATE:
+    string name;
+    string value;
+    string param;
+};
+
+extern int64_t ntoh_int64(int64_t in);
+
+#endif
diff --git a/media/libdrm/mobile2/include/dcf/DrmDcfContainer.h b/media/libdrm/mobile2/include/dcf/DrmDcfContainer.h
new file mode 100644
index 0000000..14da450
--- /dev/null
+++ b/media/libdrm/mobile2/include/dcf/DrmDcfContainer.h
@@ -0,0 +1,213 @@
+/*
+ * 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 __DCF_CONTAINER_H__
+#define __DCF_CONTAINER_H__
+
+#include <Drm2CommonTypes.h>
+#include <uvector.h>
+#include <dcf/DrmIStream.h>
+#include <dcf/DrmDcfCommon.h>
+
+class DrmInStream;
+
+/////////dcf container
+class DcfContainer : public FullBox
+{
+public:
+    friend class DrmInStream;
+
+    /** default constructor of DcfContainer */
+    DcfContainer(istream& inRawData):FullBox(NULL),mConStream(inRawData){}
+
+    /**
+     * constructor for DcfContainer, used to parse DCF container
+     * \param data  DCF container data
+     * \param len   DCF container data len
+     * \param off   the offset from the start of DCF container
+     */
+    DcfContainer(const uint8_t* data,istream& inRawData,uint64_t conOff);
+
+    /** Destructor for DcfContainer */
+    ~DcfContainer();
+
+    /**
+     * get the content type of one content
+     * \param none
+     * \return
+     *   the content type
+     */
+    string getContentType(void) const;
+
+    /**
+     * get the encryption method apply to content
+     * \param none
+     * \return
+     *   the encryption method
+     */
+    uint8_t getEncryptionMethod(void) const;
+
+    /**
+     * get the padding scheme apply to content
+     * \param none
+     * \return
+     *   the padding scheme
+     */
+    uint8_t getPaddingScheme(void) const;
+
+    /**
+     * get the length of plain content
+     * \param none
+     * \return
+     *   the length of plain content
+     */
+    uint64_t getPlaintextLength(void) const;
+
+    /**
+     * get the length of content ID
+     * \param none
+     * \return
+     *   the length of content ID
+     */
+    uint16_t getContentIDLength(void) const;
+
+    /**
+     * get the length of rights issuer URL
+     * \param none
+     * \return
+     *   the length of rights issuer URL
+     */
+    uint16_t getRightsIssuerURLLength(void) const;
+
+    /**
+     * get the length of textal header
+     * \param none
+     * \return
+     *   the length of textal header
+     */
+    uint16_t getTextualHeadersLength(void) const;
+
+    /**
+     * get the content ID of one content
+     * \param none
+     * \return
+     *   the content ID
+     */
+    string getContentID(void) const;
+
+    /**
+     * get the rights issuer URL
+     * \param none
+     * \return
+     *   the rights issuer URL
+     */
+    string getRightsIssuerURL(void) const;
+
+    /**
+     * get the preview method
+     * \param none
+     * \return
+     *   the preview method
+     */
+    string getPreviewMethod(void) const;
+
+    /**
+     * get the location of content
+     * \param none
+     * \return
+     *   the location of content
+     */
+    string getContentLocation(void) const;
+
+    /**
+     * get the URL of content
+     * \param none
+     * \return
+     *   the URL of content
+     */
+    string getContentURL(void) const;
+
+    /**
+     * get the customer head
+     * \param none
+     * \return
+     *   the customer head
+     */
+    vector<string> getCustomerHead(void) const;
+
+    /**
+     * get the preview element data
+     * \param none
+     * \return
+     *   the DRM Instream of preview element data
+     */
+    DrmInStream getPreviewElementData(void) const;
+
+    /**
+     * get the plain content
+     * \param none
+     * \return
+     *   the DRM Instream of plain content
+     */
+    DrmInStream getDecryptContent(uint8_t* decryptKey) const;
+
+    /**
+     * get the istream of DCF
+     * \param none
+     * \return
+     *   the istream of DCF
+     */
+    istream& getStream(void) const;
+
+PRIVATE:
+    static const uint32_t USER_DATA_FLAG = 0x01;
+
+    uint8_t mContentTypeLen;
+    string mContentType;
+    uint8_t mEncryptionMethod;
+    uint8_t mPaddingScheme;
+    uint64_t mPlaintextLength;
+    uint16_t mContentIDLength;
+    uint16_t mRightsIssuerURLLength;
+    uint16_t mTextualHeadersLength;
+    string mContentID;
+    string mRightsIssuerURL;
+    vector<TextualHeader*> mTextualHeaders;
+    bool mSilentFirst;
+    string mSlientMethod;
+    string mSilentRightsURL;
+    string mPreviewMethod;
+    string mPreviewElementURI;
+    string mPreviewRightsURL;
+    string mContentURL;
+    string mContentVersion;
+    string mContentLocation;
+    vector<string> mCustomHeader;
+    bool mHasUserData;
+    uint64_t mDataLen;
+    istream& mConStream;
+    uint64_t mDecOffset;
+
+PRIVATE:
+    // parse text header
+    bool parseTextualHeaders(const uint8_t* data, uint32_t len);
+    void copy(const DcfContainer& container);
+    DcfContainer(const DcfContainer& container):FullBox(NULL),mConStream(container.mConStream){}
+    DcfContainer& operator=(const DcfContainer& other){return *this;}
+};
+
+
+#endif
diff --git a/media/libdrm/mobile2/include/dcf/DrmIStream.h b/media/libdrm/mobile2/include/dcf/DrmIStream.h
new file mode 100644
index 0000000..10e264e
--- /dev/null
+++ b/media/libdrm/mobile2/include/dcf/DrmIStream.h
@@ -0,0 +1,77 @@
+/*
+ * 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 __DRM_ISTREAM_H__
+#define __DRM_ISTREAM_H__
+
+#include <Drm2CommonTypes.h>
+#include <util/crypto/DrmCrypto.h>
+#include <dcf/DrmDcfContainer.h>
+#include <ustring.h>
+
+using namespace ustl;
+
+class DcfContainer;
+
+class DrmInStream
+{
+public:
+    /** default constructor of DrmInStream */
+    DrmInStream():mDecryptPos(0){}
+
+    /**
+     * constructor for DrmInStream, used to read DCF content
+     * \param encFile  DCF container data
+     * \param len   DCF container data len
+     * \param off   the offset from the start of DCF container
+     */
+    DrmInStream(const DcfContainer* container,uint8_t* Key);
+
+    /**
+     * get the size of DRM Instream
+     * \param none
+     * \return
+     *   the size of DRM Instream
+     */
+    uint64_t size() const;
+
+    /**
+     * read data from DRM Instream
+     * \param  data  the buffer to store read data
+     * \param  len   how much data need to read
+     * \return
+     *   the actual len of read data
+     */
+    uint64_t read(uint8_t* data,uint64_t len);
+
+PRIVATE:
+    static const uint32_t AES_IV_LEN = 16;
+    static const uint32_t AES_KEY_LEN = 16;
+    static const uint32_t AES_BLOCK_LEN = 16;
+
+    const DcfContainer* mDcfCon;
+    uint64_t mDecryptPos;
+    uint8_t mAesKey[AES_KEY_LEN];
+};
+
+
+
+#endif
+
+
+
+
+
diff --git a/media/libdrm/mobile2/include/dcf/DrmRawContent.h b/media/libdrm/mobile2/include/dcf/DrmRawContent.h
new file mode 100644
index 0000000..2d433af
--- /dev/null
+++ b/media/libdrm/mobile2/include/dcf/DrmRawContent.h
@@ -0,0 +1,74 @@
+/*
+ * 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 __DRM_CONTENT_H__
+#define __DRM_CONTENT_H__
+
+#include <Drm2CommonTypes.h>
+#include <dcf/DrmDcfContainer.h>
+
+/////////////raw content
+class DrmRawContent
+{
+public:
+    /**
+     * constructor for DrmRawContent, used to parse DCF
+     * \param inRawData  input stream of raw data.
+     */
+    DrmRawContent(istream& inRawData);
+
+    /** Destructor for DrmRawContent */
+    ~DrmRawContent();
+
+    /**
+     * get DCF container
+     * \param none
+     * \return
+     *   the DCF container
+     */
+    vector<DcfContainer*> getContents(void) const;
+
+    /**
+     * get the length of DCF hash
+     * \param none
+     * \return
+     *   the length of DCF hash
+     */
+    uint32_t getDcfHashLen() const;
+
+    /**
+     * get DCF hash
+     * \param outDcfHash  the buffer to store DCF hash
+     * \return
+     *   none
+     */
+    void getDcfHash(uint8_t* outDcfHash) const;
+
+PRIVATE:
+    static const uint32_t DCF_HASH_LEN = 20;
+    static const uint32_t FIX_HEADER_LEN = 20;
+    static const uint32_t MAX_PIECE_LEN = (100 * 1024);
+
+    uint8_t mDcfHash[DCF_HASH_LEN];
+    vector<DcfContainer*> mContainer;
+
+PRIVATE:
+    bool parseDcfHeader(const uint8_t* dcfHead);
+    DrmRawContent(const DrmRawContent& rawContent){}
+    DrmRawContent& operator=(const DrmRawContent& other){return *this;}
+};
+
+#endif
diff --git a/media/libdrm/mobile2/include/drmmanager/DrmManager.h b/media/libdrm/mobile2/include/drmmanager/DrmManager.h
new file mode 100644
index 0000000..c8bfbc1
--- /dev/null
+++ b/media/libdrm/mobile2/include/drmmanager/DrmManager.h
@@ -0,0 +1,107 @@
+/*
+ * 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 _DRMMANAGER_
+#define _DRMMANAGER_
+
+#include <Drm2CommonTypes.h>
+#include <ofstream.h>
+#include <sostream.h>
+#include <ustring.h>
+#include <sistream.h>
+#include <uvector.h>
+
+using namespace ustl;
+
+/** It should be removed after real DcfContainer is ready */
+#define DcfContainer string
+static const int16_t DRM_OK = 1;
+
+class DrmManager
+{
+public:
+    /**
+     * Error definition
+     */
+     static const int16_t DRM_MANAGER_BASE = 100;
+     static const int16_t ERR_DCFSTREAM_NOT_INITIALIZED = DRM_MANAGER_BASE+1;
+     static const int16_t ERR_WRONG_DCFDATA = DRM_MANAGER_BASE+2;
+     static const int16_t ERR_WRONG_RIGHTS = DRM_MANAGER_BASE+3;
+
+    /**
+     * Constructor for DrmManager,used to open local dcf file.
+     * @param inRawData input stream of raw data.
+     */
+    DrmManager(istream *inRawData);
+
+    /**
+     * Constructor for DrmManager,used to separate dcf file and trig message when upper
+     * application downloading one multipart message from CI.
+     * @param inRawData input stream of raw data.
+     */
+    DrmManager(istream * inRawData, string mimeType);
+
+    /** Destructor for DomExpatAgent. */
+    ~DrmManager();
+    /**
+     * Config DRM engine
+     * Fix me later
+     */
+     bool config();
+
+    /**
+     * Consume rights according to specified operation, DrmManager will check.
+     * @param operationType the type of operation.
+     * @return the operation result.
+     */
+    int16_t consumeRights(int16_t operationType);
+
+    /**
+     * Get the list of all dcf containers object reference in the dcf file.
+     * @param the vector of the dcf objects list returned.
+     * @return the operation result.
+     */
+     int16_t getListOfDcfObjects(vector<DcfContainer*> **outDcfList);
+
+    /**
+     * Open one Dcf container to read the decrypted data according to specified
+     * operation.
+     * @param oneDcfObject the reference of the DcfContainer.
+     * @param operationType the type of operation.
+     * @param decrypted data returned.
+     * @return the operation result.
+     */
+    int16_t openDecryptedContent(DcfContainer *oneDcfObject,
+                                int16_t operationType,
+                                istream *outDecryptedData);
+
+    /**
+     * Get the separated Dcf raw data from multipart message.
+     * @return the ifstream of the dcf raw data which should be stored by upper
+     * application.
+     */
+    ifstream* getOriginalMediaData(void);
+
+    /**
+     * Handle DRM2.0 push message
+     */
+    bool handlePushMsg(uint8_t* data, string mimeType);
+
+PRIVATE:
+    istream *mDcfStream; /**< the handler of dcf stream. */
+    vector<DcfContainer*> mDcfs; /**< all the dcf containers included in one dcf file. */
+};
+
+#endif //_DRMMANAGER_
diff --git a/media/libdrm/mobile2/include/rights/Asset.h b/media/libdrm/mobile2/include/rights/Asset.h
new file mode 100644
index 0000000..66696dd
--- /dev/null
+++ b/media/libdrm/mobile2/include/rights/Asset.h
@@ -0,0 +1,132 @@
+/*
+ * 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 _ASSET_H
+#define _ASSET_H
+
+#include <ustring.h>
+#include <uvector.h>
+#include <Drm2CommonTypes.h>
+#include <rights/Right.h>
+using namespace ustl;
+
+class Asset {
+public:
+    /**
+     * Constructor for asset.
+     */
+    Asset();
+
+    /**
+     * Destructor for asset.
+     */
+    ~Asset();
+
+    /**
+     * Test whether asset has parent or not.
+     * @return true/false to indicate the result.
+     */
+    bool hasParent();
+
+    /**
+     * Set id of asset.
+     * @param id the id of asset.
+     */
+    void setID(const string &id);
+
+    /**
+     * Get the id of content.
+     * @return asset id.
+     */
+    const string& getID() const;
+
+    /**
+     * Set contend id related to asset.
+     * @param id the id of content.
+     */
+    void setContentID(const string &id);
+
+    /**
+     * Get content id.
+     * @return content id.
+     */
+    const string& getContentID() const;
+
+    /**
+     * Set digest value of DCF.
+     * @param value the DCF digest value.
+     */
+    void setDCFDigest(const string &value);
+
+    /**
+     * Get the DCF digest value.
+     * @return the digest value of DCF.
+     */
+    const string& getDCFDigest() const;
+
+    /**
+     * Set encrypted key in asset.
+     * @param the encrypted key.
+     */
+    void setEncryptedKey(const string &key);
+
+    /**
+     * Get encrypted key.
+     * @return encypted key.
+     */
+    const string& getEncrytedKey() const;
+
+    /**
+     * Get cek.
+     * @return cek.
+     */
+    const char* getCek() const;
+
+    /**
+     * Set the retrieval method of key.
+     * @param rm the retrieval method of the key.
+     */
+    void setKeyRetrievalMethod(const string &rm);
+
+    /**
+     * Set parent content id for asset.
+     * @param id the parent content id.
+     */
+    void setParentContentID(const string &id);
+
+    /**
+     * Get the parent content id of the asset.
+     * @return the parent content id.
+     */
+    const string& getParentContentID() const;
+
+    /**
+     * Recover the CEK using private key.
+     */
+    void recoverCek();
+
+PRIVATE:
+    string mAssetID;
+    string mContentID;
+    string mDigestMethod;
+    string mDigestValue;
+    string mEncryptedMethod;
+    string mEncryptedKey;
+    string mRetrievalMethod;
+    string mParentContentID;
+    string mCek;
+};
+
+#endif
diff --git a/media/libdrm/mobile2/include/rights/Constraint.h b/media/libdrm/mobile2/include/rights/Constraint.h
new file mode 100644
index 0000000..bcf5afe
--- /dev/null
+++ b/media/libdrm/mobile2/include/rights/Constraint.h
@@ -0,0 +1,190 @@
+/*
+ * 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 _CONSTRAINT_H
+#define _CONSTRAINT_H
+
+#include <Drm2CommonTypes.h>
+#include <ustring.h>
+#include <uvector.h>
+using namespace ustl;
+
+struct Context {
+    string id;
+    string version;
+};
+
+const int INIT_VALUE = -1;
+
+class Constraint {
+public:
+    enum MODE {NONE, MOVE, COPY}; /**< export mode type. */
+
+    /**
+     * Construtor for constraint.
+     */
+    Constraint();
+
+    /**
+     * Destructor for constraint.
+     */
+    ~Constraint();
+
+public:
+    /**
+     * Test whether constraint is valid or not
+     * @param time the specitic time to test.
+     * @return true/false to indicate the result.
+     */
+    bool isValid(long time) const;
+
+    /**
+     * Test whether constraint is unconstraint or not
+     * @return true/false to indicate the result.
+     */
+    bool isUnConstraint() const;
+
+    /**
+     * Test whether constraint is datetime related or not.
+     * @return true/false to indicate the result.
+     */
+    bool isDateTimeConstraint() const;
+
+    /**
+     * Test whether constraint contain interval or not
+     * @return true/false to indicate the result.
+     */
+    bool isIntervalConstraint() const;
+
+    /**
+     * Test whether constraint is timed count or not
+     * @return true/false to indicate the result.
+     */
+    bool isTimedCountConstraint() const;
+
+    /**
+     * Set the start time value of constraint.
+     * @param time the specific time value.
+     */
+    void setStartTime(long time);
+
+    /**
+     * Get the start time.
+     * @return value of start time.
+     */
+    long getStartTime() const;
+
+    /**
+     * Set the end time.
+     * @param time the value of end time.
+     */
+    void setEndTime(long time);
+
+    /**
+     * Get the end time.
+     * @param return the value of  end time.
+     */
+    long getEndTime() const;
+
+    /**
+     * Set the accumulated .
+     * @param time the specific time.
+     */
+    void setAccumulated(long time);
+
+    /**
+     * Get the accumulated.
+     * @return the value of accumulated
+     */
+    long getAccumulated() const;
+
+    /**
+     * Set the count.
+     * @param count the value of count.
+     */
+    void setCount(int count);
+
+    /**
+     * Get the count.
+     * @return value of count.
+     */
+    int getCount() const;
+
+    /**
+     * Set the value of timer.
+     * @param timer the value of the timer.
+     */
+    void setTimer(int timer);
+
+    /**
+     * Get the timer.
+     * @return value of time.
+     */
+    int getTimer() const;
+
+    /**
+     * Set the timedCount.
+     * @param timedCount the value of timedCount.
+     */
+    void setTimedCount(int timedCount);
+
+    /**
+     * Get the timedCount.
+     * @return the value of timedCount.
+     */
+    int getTimedCount() const;
+
+    /**
+     * Set the interval.
+     * @param interval the value of interval.
+     */
+    void setInterval(int interval);
+
+    /**
+     * Get the interval.
+     * @return the value of interval.
+     */
+    int getInterval() const;
+
+    /**
+     * set export mode.
+     * @param mode the mode type of export.
+     */
+    void setExportMode(MODE mode);
+
+    /**
+     * Get the export mode.
+     * @return the export mode.
+     */
+    MODE getExportMode() const;
+
+    /**
+     * Consume the constraint.
+     * @return true/false to indicate whether consume succesfully or not.
+     */
+    bool consume();
+
+PRIVATE:
+    int mCount; /**< the count. */
+    int mTimedCount; /**< timed count. */
+    int mTimer; /**< timer for timed count. */
+    long mStart; /**< start time. */
+    long mEnd; /**< end time. */
+    int mInterval; /**< interval. */
+    long mAccumulated; /**< accumlated. */
+    vector<Context> mSystemList; /**< system list. */
+    MODE mExport; /**< export mode. */
+};
+#endif
diff --git a/media/libdrm/mobile2/include/rights/OperationPermission.h b/media/libdrm/mobile2/include/rights/OperationPermission.h
new file mode 100644
index 0000000..28cba7b
--- /dev/null
+++ b/media/libdrm/mobile2/include/rights/OperationPermission.h
@@ -0,0 +1,83 @@
+/*
+ * 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 _OPERATIONPERMISSION_H
+#define _OPERATIONPERMISSION_H
+
+#include <Drm2CommonTypes.h>
+#include <rights/Constraint.h>
+
+class OperationPermission {
+public:
+    enum OPERATION {NONE, PLAY, DISPLAY, EXECUTE, PRINT, EXPORT, COMMON};
+
+    /**
+     * Construtor of OperationPermission.
+     */
+    OperationPermission();
+
+    /**
+     * Construtor of OperationPermission.
+     * @param type the specific operation type.
+     * @param cst the constraint related with operation permission.
+     */
+    OperationPermission(OPERATION type, Constraint* cst=NULL);
+
+    /**
+     * Destrutor of OperationPermission.
+     */
+    ~OperationPermission();
+
+    /**
+     * Set the type for operation permission.
+     * @param type the specific type.
+     */
+    void setType(OPERATION type);
+
+    /**
+     * Get the type of operation permission.
+     * @return operation type.
+     */
+    OPERATION getType() const;
+
+    /**
+     * Add constraint for operation permission.
+     * @param constraint the constraint related with operation permission.
+     */
+    void addConstraint(Constraint* constraint);
+
+    /**
+     * Add constraint for operation permission.
+     * @return constraint related with operation permission.
+     */
+    Constraint* getConstraint() const;
+
+PRIVATE:
+    OPERATION mType;
+    Constraint* mConstraint;
+
+PRIVATE:
+    /**
+     * Disable the assignment between OperationPermissions.
+     */
+    OperationPermission& operator=(const OperationPermission &op);
+
+    /**
+     * Disable copy construtor.
+     */
+    OperationPermission(const OperationPermission &op);
+};
+
+#endif
diff --git a/media/libdrm/mobile2/include/rights/Right.h b/media/libdrm/mobile2/include/rights/Right.h
new file mode 100644
index 0000000..347e484
--- /dev/null
+++ b/media/libdrm/mobile2/include/rights/Right.h
@@ -0,0 +1,83 @@
+/*
+ * 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 _RIGHT_H
+#define _RIGHT_H
+
+#include <Drm2CommonTypes.h>
+#include <uvector.h>
+#include <ustring.h>
+#include <rights/Constraint.h>
+#include <rights/OperationPermission.h>
+using namespace ustl;
+
+class Right {
+public:
+    /**
+     * Constructor for Right.
+     */
+    Right();
+
+    /**
+     * Destructor for Right.
+     */
+    ~Right();
+
+    /**
+     * Add the asset id related with right into asset name list.
+     * @param id the id of the asset.
+     */
+    void addAssetID(const string& id);
+
+    /**
+     * Add a operation permission into right's operation permission list.
+     * @param op a pointer of operation permission.
+     */
+    void addOperationPermission(OperationPermission* op);
+
+    /**
+     * Get the constraint related with operation type.
+     * @param type the specific operation type.
+     * @return NULL if not found otherwise the constraint pointer.
+     */
+    Constraint* getConstraint(OperationPermission::OPERATION type);
+
+    /**
+     * Test whether the right has specific operation type or not.
+     * @param type the specific type.
+     * @return true/false to indicate the result.
+     */
+    bool checkPermission(OperationPermission::OPERATION type);
+
+public:
+    vector<string> mAssetNameList;
+
+PRIVATE:
+    vector<OperationPermission*> mOpList;
+
+PRIVATE:
+
+    /**
+     * Disable the assignment between rights.
+     */
+    Right& operator=(const Right& right);
+
+    /**
+     * Disable copy constructor.
+     */
+    Right(const Right& right);
+   };
+
+#endif
diff --git a/media/libdrm/mobile2/include/rights/Ro.h b/media/libdrm/mobile2/include/rights/Ro.h
new file mode 100644
index 0000000..0bf0a97
--- /dev/null
+++ b/media/libdrm/mobile2/include/rights/Ro.h
@@ -0,0 +1,214 @@
+/*
+ * 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 _RO_H_
+#define _RO_H_
+
+#include <rights/Asset.h>
+#include <rights/Right.h>
+#include <uvector.h>
+#include <ustring.h>
+#include <sistream.h>
+using namespace ustl;
+
+class Asset;
+class XMLDocumentImpl;
+class XMLElementImpl;
+class NodeImpl;
+
+class Ro {
+public:
+    enum ERRCODE { RO_NULL_STREAM, RO_ERR_BAD_XML, RO_OK, RO_BAD };
+
+    /**
+     * Constructor for Ro.
+     */
+    Ro();
+
+    /**
+     * Destructor for Ro.
+     */
+    ~Ro();
+
+    /**
+     * Set id for Ro.
+     * @param id the id of Ro.
+     */
+    void setRoID(string &id);
+
+    /**
+     * Get the id of Ro.
+     * @return the id of Ro.
+     */
+    const string& getRoID() const;
+
+    /**
+     * Set version for Ro.
+     */
+    void setRoVersion(string &version);
+
+    /**
+     * Add a asset into ro's asset list.
+     * @param asset the pointer of asset.
+     */
+    void addAsset(Asset* asset);
+
+    /**
+     * Add a right into ro's right list.
+     * @param right the pointer of right.
+     */
+    void addRight(Right* right);
+
+    /**
+     * Save the Ro.
+     */
+    bool save();
+
+    /**
+     * Verify the Ro.
+     */
+    bool verify();
+
+    /**
+     * Parse the ro from stream.
+     * @param roStream the input ro stream.
+     * @return RO_OK if parse successfully otherwise return error code.
+     */
+    ERRCODE parse(istringstream *roStream);
+
+    /**
+     * Check the permission of the content.
+     * @param type the operation type.
+     * @param contentID the specific contentID.
+     * @return true/false to indicate result.
+     */
+    bool checkPermission(OperationPermission::OPERATION type,
+                         const string& contentID);
+
+    /**
+     * Consume the right related to content.
+     * @param type the operation type.
+     * @param contentID the specific contentID.
+     * @return the status of consume.
+     */
+    ERRCODE consume(OperationPermission::OPERATION type,
+                    const string& contentID);
+
+    /**
+     * Get CEK of content.
+     * @param contentID the specific content id.
+     * @return "" if not found otherwise return CEK.
+     */
+    string getContentCek(const string& contentID);
+
+    /**
+     * Get Digest value of content.
+     * @param contentID the specific content id.
+     * @return "" if not found otherwise return digest value.
+     */
+    string getContentHash(const string& contentID);
+
+PRIVATE:
+    /**
+     * Handle the xml dom document.
+     * @param doc the pointer to the dom document.
+     * @return true/false to indicate the result.
+     */
+    bool handleDocument(const XMLDocumentImpl* doc);
+
+    /**
+     * Handle the xml dom node which contains <right> element.
+     * @param curNode the dom node which contains <right> element.
+     * @return true/false to indicate the result.
+     */
+    bool handleRights(const NodeImpl *curNode);
+
+    /**
+     * Handle the xml dom node which contains the <agreement> element.
+     * @param curNode the dom node which contains <agreement> element.
+     * @return true/false to indicate the result.
+     */
+    bool handleAgreement(const NodeImpl *curNode);
+
+    /**
+     * Handle the xml dom node which contains the <asset> element.
+     * @param curNode the dom node which contains <asset> element.
+     * @return true/false to indicate the result.
+     */
+    bool handleAsset(const NodeImpl *curNode);
+
+    /**
+     * Handle the xml dom node which contains the <permission> element.
+     * @param curNode the dom node which contains <permission> element.
+     * @return true/false to indicate the result.
+     */
+    bool handlePermission(const NodeImpl *curNode);
+
+    /**
+     * Get the constraint in xml dom node.
+     * @param curNode the dom node which contains constraint.
+     * @return the constraint.
+     */
+    Constraint* getConstraint(const NodeImpl *curNode);
+
+    /**
+     * Convert ISO8601 time to long.
+     * @param ts the string with ISO8601 time.
+     * @return the result value.
+     */
+    long convertISO8601DateTimeToLong(const char* ts);
+
+    /**
+     * Convert ISO8601 period to long.
+     * @param ts the string with ISO8601 period.
+     * @return the result value.
+     */
+    long convertISO8601PeriodToLong(const char* ts);
+
+    /**
+     * Load the rights related with specific contentinto content rights list.
+     * @param contentID the specific content id.
+     */
+    void loadRights(const string& contentID);
+
+    /**
+     * Free the current content rights list.
+     */
+    void freeRights();
+
+PRIVATE:
+    /**
+     * Disable the assignment between rights.
+     */
+    Ro& operator=(const Ro& ro);
+
+    /**
+     * Disable copy constructor.
+     */
+    Ro(const Ro& ro);
+
+public:
+    vector<Asset*> mAssetList;
+    vector<Right*> mRightList;
+
+PRIVATE:
+    string mRoID; /** the Ro id. */
+    string mRoVersion; /** the Ro version. */
+    XMLDocumentImpl *mDoc; /**< the xml document handle. */
+    vector<Right*> mContentRightList; /**< the right list to store the result related with specific content. */
+    Right* mProperRight; /**< the right to consume. */
+};
+#endif
diff --git a/media/libdrm/mobile2/include/rights/RoManager.h b/media/libdrm/mobile2/include/rights/RoManager.h
new file mode 100644
index 0000000..cf398b3
--- /dev/null
+++ b/media/libdrm/mobile2/include/rights/RoManager.h
@@ -0,0 +1,98 @@
+/*
+ * 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 _ROMANAGER_H
+#define _ROMANAGER_H
+
+#include <Drm2CommonTypes.h>
+#include <ustring.h>
+#include <rights/Ro.h>
+
+using namespace ustl;
+
+class RoManager {
+
+public:
+    /**
+     * Singleton instance function.
+     * @return the singleton pointer.
+     */
+    static RoManager* Instance();
+
+    /**
+     * Destructor for ExpatWrapper.
+     */
+    ~RoManager();
+
+    /**
+     * Install Ro from stream.
+     * @param roStream the input ro stream.
+     * @return the status of installaltion.
+     */
+    Ro::ERRCODE installRo(istringstream *roStream);
+
+    /**
+     * Check whether Ro in cache or not.
+     * @param roID the specific roID.
+     * @return true/false to indicate result.
+     */
+    bool checkRoInCache(const string& roID);
+
+    /**
+     * Get the ro.
+     * @param roID the specific id of ro.
+     * @return NULL if not found otherwise return ro.
+     */
+    Ro* getRo(const string& roID);
+
+    /**
+     * Get all the Ro.
+     * @return ro list.
+     */
+    vector<Ro*> getAllRo();
+
+    /**
+     * Get the private key of the device.
+     * @return the private key.
+     */
+    const string& getDevicePrivateKey() const;
+
+    /**
+     * Get ro which contained rights of specific content.
+     * @param contentID the specific id of content.
+     * @return NULL if not fount otherwise the related ro.
+     */
+    Ro* getRoByContentID(const string& contentID);
+
+    /**
+     * Delete Ro by its id.
+     * @param roID the specific roID.
+     * @return true/false to indicate the result.
+     */
+    bool deleteRo(const string& roID);
+
+
+PRIVATE:
+    /**
+     * Constructor for RoManager.
+     */
+    RoManager();
+
+PRIVATE:
+    static RoManager* msInstance; /**< singleton instance pointer. */
+    vector<Ro*> mRoList; /**< the ro list. */
+};
+
+#endif
diff --git a/media/libdrm/mobile2/include/roap/Registration.h b/media/libdrm/mobile2/include/roap/Registration.h
new file mode 100644
index 0000000..0beed8e
--- /dev/null
+++ b/media/libdrm/mobile2/include/roap/Registration.h
@@ -0,0 +1,44 @@
+/*
+ * 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 _REGISTRATION_
+#define _REGISTRATION_
+
+#include <roap/RoapMessageHandler.h>
+
+class Registration : public RoapMessageHandler
+{
+public:
+    /**
+     * Constructor for Registration.
+     * @param type the address of RI.
+     */
+    Registration(string riAddres);
+
+    /**
+     * Registration with the RI.
+     * @return the result of registration.
+     */
+    int16_t registerWithRI();
+
+    /**
+     * Create one specified client message based on message template xml file.
+     * @param type the message type.     
+     * @return the pointer of the document object of the message if successful,otherwise
+     *         return NULL.
+     */
+     XMLDocumentImpl* createClientMsg(int16_t type);
+}
+#endif _REGISTRATION_
diff --git a/media/libdrm/mobile2/include/roap/RoapMessageHandler.h b/media/libdrm/mobile2/include/roap/RoapMessageHandler.h
new file mode 100644
index 0000000..c31047f
--- /dev/null
+++ b/media/libdrm/mobile2/include/roap/RoapMessageHandler.h
@@ -0,0 +1,66 @@
+/*
+ * 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 _ROAPMESSAGEHADLER_
+#define _ROAPMESSAGEHADLER_
+
+#include <Drm2CommonTypes.h>
+#include <util/xml/XMLDocumentImpl.h>
+
+class RoapMessageHandler
+{
+public:
+    /**
+     * define all the client message types.
+     */
+     enum msgType {DeviceHello=1,RegistrationRequest,RORequest};
+
+    /**
+     * Constructor for DrmManager,used to open local dcf file.
+     * @param type the message type.
+     */
+     RoapMessageHandler();
+
+    /**
+     * Create one specified client message based on message template xml file.
+     * @param type the message type.     
+     * @return the pointer of the document object of the message if successful,otherwise
+     *         return NULL.
+     */
+     XMLDocumentImpl* createClientMsg(msgType type);
+
+    /**
+     * Handle received message from RI.
+     * @return true if successful, otherwise return false.
+     */
+    bool handlePeerMsg();
+
+    /**
+     * Send the client message to RI
+     */
+    int16_t send();
+
+    /**
+     * Receive message from RI and parse it 
+     * @return the pointer of the parsed document.
+     */
+    XMLDocumentImpl* receive();
+
+PROTECTED:
+    XMLDocumentImpl * mDoc;
+PRIVATE:
+    int16_t mMsgType;
+};
+#endif //_ROAPMESSAGEHADLER_
diff --git a/media/libdrm/mobile2/include/util/crypto/DrmCrypto.h b/media/libdrm/mobile2/include/util/crypto/DrmCrypto.h
new file mode 100644
index 0000000..10e7bc1
--- /dev/null
+++ b/media/libdrm/mobile2/include/util/crypto/DrmCrypto.h
@@ -0,0 +1,211 @@
+/*
+ * 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 _DRMCRYPTO_H_
+#define _DRMCRYPTO_H_
+
+#include <Drm2CommonTypes.h>
+#include <openssl/aes.h>
+#include <openssl/hmac.h>
+#include <openssl/sha.h>
+#include <openssl/rsa.h>
+
+// AES encrypt mode
+typedef enum {AES_128_CBC = 0x01,AES_128_CTR = 0x02}AesMode;
+
+// aes crypto for decrypt
+class AesAgent
+{
+    public:
+        AesAgent(const AesMode method,const unsigned char* decryptedKey)
+            :mode(method),AesKey(decryptedKey){};
+
+        /**

+         * decrypt data using AES, now only support 128 bits CBC
+         * \param iv       128 bits initialization vector/counter
+         *                 prefixing the ciphertext

+         * \param encData  encrypted data

+         * \param encLen   the length of encData

+         * \param decData  the buffer to store decrypted data

+         * \param decLen   the actual length of decrypted data

+         * \return

+         *   >=   succeed, the padding length

+         *   < 0  failed

+         */
+        int32_t decContent( unsigned char* iv,
+                            const unsigned char* encData,
+                            const unsigned long encLen,
+                            unsigned char* decData);
+        static const int32_t AES_DEC_FAILED = -1;
+
+    PRIVATE:
+        static const uint32_t AES_KEY_BITS = 128;
+        const AesMode mode;
+        const unsigned char* AesKey;
+
+    PRIVATE:
+        // get the actual length of decrypt data

+        void discardPaddingByte(unsigned char* decryptedBuf,unsigned long* decryptedBufLen);

+};
+
+// Sha1 crypto for hash
+class Sha1Agent
+{
+    public:
+        /**

+         * compute hash using Sha1

+         * \param inData   the data to be hashed

+         * \param inLen    the length of inData

+         * \param outHash  the hash of inData

+         * \return   none

+         */

+        void computeHash( const unsigned char* inData,

+                          unsigned long inLen,

+                          unsigned char* outHash) const;

+

+        /**

+         * get the length of SHA1 hash

+         * \param  none

+         * \return

+         *      the length of SHA1 hash

+         */

+        unsigned long getShaLen(void) const
+        {
+            return SHA_DIGEST_LENGTH;
+        }

+};
+
+// Hmac-Sha1 crypto for MAC
+class HmacSha1Agent
+{
+    public:
+        HmacSha1Agent(const unsigned char* Key, int key_len)
+          :macKey(Key),keyLen(key_len){};
+
+        /**

+         * compute MAC using Hmac-Sha1

+         * \param inData  the data to be MAC

+         * \param inLen   the length of inData

+         * \param outMac  the MAC of inData

+         * \return   none

+         */

+        void computeMac( const unsigned char* inData,

+                         unsigned long inLen,

+                         unsigned char* outMac) const;

+

+        /**

+         * get the length of HMAC-SHA1 MAC

+         * \param  none

+         * \return

+         *      the length of HMAC-SHA1 MAC

+         */

+        unsigned long getHmacLen(void) const
+        {
+            return SHA_DIGEST_LENGTH;
+        }
+

+    PRIVATE:
+        const unsigned char* macKey;
+        const int keyLen;
+};
+
+// Rsa crypto for signature,verify signature and key transport
+class RsaAgent
+{
+    public:
+        RsaAgent(RSA& Key):rsaKey(Key)
+        {
+            rsaSize = (unsigned int)RSA_size(&Key);
+        };
+
+        // signature algorithm
+        typedef enum {RSA_PSS,RSA_SHA1}RsaAlg;
+
+        /**

+         * Do signature using RSA-PSS

+         * \param rawData  the data to be signature

+         * \param rawLen   the length of inData

+         * \param sigData  the buffer to store the signature of rawData
+         * \param sigAlg   signature algorithm

+         * \return

+         *   true   succeed

+         *   false  failed

+         */

+        bool signature( const unsigned char* rawData,

+                        const unsigned long rawLen,

+                        unsigned char* sigData,
+                        const RsaAlg sigAlg);

+

+        /**

+         * get the length of signature

+         * \param  none

+         * \return

+         *      the length of signature

+         */

+        unsigned int getSigLen(void) const
+        {
+            return rsaSize;
+        }
+
+        /**

+         * Verify signature using RSA-PSS

+         * \param sigData  the data to be verify

+         * \param sigLen   the length of sigData
+         * \param rawData  the data from which the sigData generated
+         * \param rawLen   the length of rawData
+         * \param sigAlg   signature algorithm

+         * \return

+         *   true   succeed

+         *   false  failed

+         */

+        bool sigVerify(unsigned char* sigData,
+                       unsigned long sigLen,
+                       const unsigned char* rawData,
+                       const unsigned long rawLen,
+                       const RsaAlg sigAlg);
+

+
+        /**

+         * Decrypt data using RSA

+         * \param encData  encrypted data

+         * \param encLen   the length of encData

+         * \param decData  the buffer to store decrypted data

+         * \return

+         *   -1  decrypted failed

+         *   >0  the actual length of decrypted data

+         */

+        int decrypt( const unsigned char* encData,

+                     const unsigned long encLen,

+                     unsigned char* decData);

+

+        /**

+         * get the length of decrypted data

+         * \param none

+         * \return

+         *      the length of decrypted data

+         */

+        unsigned int getDecLen(void) const
+        {
+           return rsaSize;
+        }
+

+    PRIVATE:
+        RSA& rsaKey;
+        unsigned int rsaSize;
+};
+
+
+#endif /* _DRMCRYPTO_H_ */
diff --git a/media/libdrm/mobile2/include/util/domcore/CharacterDataImpl.h b/media/libdrm/mobile2/include/util/domcore/CharacterDataImpl.h
new file mode 100644
index 0000000..d1ab31e
--- /dev/null
+++ b/media/libdrm/mobile2/include/util/domcore/CharacterDataImpl.h
@@ -0,0 +1,102 @@
+/*
+ * 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 __CHARACTER_IMPL__

+#define __CHARACTER_IMPL__

+

+#include "NodeImpl.h"

+#include "DOMString.h"

+

+class CharacterDataImpl : public NodeImpl

+{

+private:

+    DOMString* charData;

+public:

+

+     /**

+      * Default Constructor for CharacterDataImpl.

+      */

+     CharacterDataImpl();

+

+     /**

+      * Constructor for CharacterDataImpl.

+      * @param data The specify character data.

+      */

+     CharacterDataImpl(const DOMString* data);

+

+    /**

+     * The character data of the node that implements this interface. The DOM

+     * implementation may not put arbitrary limits on the amount of data

+     * that may be stored in a <code>CharacterData</code> node. However,

+     * implementation limits may mean that the entirety of a node's data may

+     * not fit into a single <code>DOMString</code>. In such cases, the user

+     * may call <code>substringData</code> to retrieve the data in

+     * appropriately sized pieces.

+     * @exception DOMException

+     *   NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly.

+     * @exception DOMException

+     *   DOMSTRING_SIZE_ERR: Raised when it would return more characters than

+     *   fit in a <code>DOMString</code> variable on the implementation

+     *   platform.

+     * @return the character data.

+     */

+    const DOMString* getData() const throw (DOMException);

+

+    /**

+     * The character data of the node that implements this interface. The DOM

+     * implementation may not put arbitrary limits on the amount of data

+     * that may be stored in a <code>CharacterData</code> node. However,

+     * implementation limits may mean that the entirety of a node's data may

+     * not fit into a single <code>DOMString</code>. In such cases, the user

+     * may call <code>substringData</code> to retrieve the data in

+     * appropriately sized pieces.

+     * @param data the specify character data.

+     * @exception DOMException

+     *   NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly.

+     * @exception DOMException

+     *   DOMSTRING_SIZE_ERR: Raised when it would return more characters than

+     *   fit in a <code>DOMString</code> variable on the implementation

+     *   platform.

+     */

+    void setData(const DOMString* data) throw (DOMException);

+

+    /**

+     * The number of 16-bit units that are available through <code>data</code>

+     * and the <code>substringData</code> method below. This may have the

+     * value zero, i.e., <code>CharacterData</code> nodes may be empty.

+     * @return the size of characters data.

+     */

+    int getLength() const;

+

+    /**

+     * Append the string to the end of the character data of the node. Upon

+     * success, <code>data</code> provides access to the concatenation of

+     * <code>data</code> and the <code>DOMString</code> specified.

+     * @param arg The <code>DOMString</code> to append.

+     * @exception DOMException

+     *   NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.

+     */

+    void appendData(const DOMString* arg) throw(DOMException);

+

+    /** Override getNodeValue() method in NodeImpl.h.*/

+    const DOMString* getNodeValue() const throw(DOMException);

+

+    /** Override setNodeValue() method in NodeImpl.h */

+    void setNodeValue(DOMString* nodeValue) throw(DOMException);

+

+    ~CharacterDataImpl();

+};

+#endif /*__CHARACTER_IMPL__*/

+

diff --git a/media/libdrm/mobile2/include/util/domcore/DOMException.h b/media/libdrm/mobile2/include/util/domcore/DOMException.h
new file mode 100644
index 0000000..416519b
--- /dev/null
+++ b/media/libdrm/mobile2/include/util/domcore/DOMException.h
@@ -0,0 +1,155 @@
+/*
+ * 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 __DOM_EXCEPTION__

+#define __DOM_EXCEPTION__

+

+#include <uexception.h>

+using namespace ustl;

+

+/**

+ * DOM operations only raise exceptions in "exceptional" circumstances, i.e.,

+ * when an operation is impossible to perform (either for logical reasons, because data is lost,

+ * or because the implementation has become unstable). In general, DOM methods return specific error

+ * values in ordinary processing situations, such as out-of-bound errors when using <code>NodeList</code>.

+ * <p>Implementations should raise other exceptions under other circumstances. For example, implementations

+ * should raise an implementation-dependent exception if a null argument is passed.

+ * Some languages and object systems do not support the concept of exceptions.

+ * For such systems, error conditions may be indicated using native error reporting mechanisms.

+ * For some bindings, for example, methods may return error codes similar to those listed in the corresponding

+ * method descriptions.

+ */

+class DOMException : public exception {

+

+ private:

+        short code;

+ public:

+        DOMException(short code)

+        {

+            this->code = code;

+        }

+ public:

+

+        enum ExceptionReason {

+           /**

+            * If index or size is negative, or greater than the allowed value

+            */

+            INDEX_SIZE_ERR = 1,

+

+            /**

+             * If the specified range of text does not fit into a DOMString

+             * @since http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html

+             */

+            DOMSTRING_SIZE_ERR = 2,

+            /**

+             * If any node is inserted somewhere it doesn't belong

+             * @since http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html

+             */

+            HIERARCHY_REQUEST_ERR = 3,

+

+            /**

+             * If a node is used in a different document than the one that created it

+             * (that doesn't support it)

+             * @since http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html

+             */

+            WRONG_DOCUMENT_ERR = 4,

+

+            /**

+             * If an invalid or illegal character is specified, such as in a name. See

+             * production 2 in the XML specification for the definition of a legal

+             * character, and production 5 for the definition of a legal name

+             * character.

+             * @since http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html

+             */

+            INVALID_CHARACTER_ERR = 5,

+

+            /**

+             * If data is specified for a node which does not support data

+             * @since http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html

+             */

+            NO_DATA_ALLOWED_ERR = 6,

+

+            /**

+             * If an attempt is made to modify an object where modifications are not

+             * allowed

+             * @since http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html

+             */

+            NO_MODIFICATION_ALLOWED_ERR = 7,

+

+            /**

+             * If an attempt is made to reference a node in a context where it does

+             * not exist

+             * @since http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html

+             */

+            NOT_FOUND_ERR = 8,

+

+            /**

+             * If the implementation does not support the requested type of object or

+             * operation.

+             * @since http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html

+             */

+            NOT_SUPPORTED_ERR = 9,

+

+            /**

+             * If an attempt is made to add an attribute that is already in use

+             * elsewhere

+             */

+            INUSE_ATTRIBUTE_ERR = 10,

+

+            /**

+             * If an attempt is made to use an object that is not, or is no longer,

+             * usable.

+             * @since http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html

+             */

+            INVALID_STATE_ERR = 11,

+

+            /**

+             * If an invalid or illegal string is specified.

+             * @since http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html

+             */

+            SYNTAX_ERR = 12,

+

+            /**

+             * If an attempt is made to modify the type of the underlying object.

+             * @since http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html

+             */

+            INVALID_MODIFICATION_ERR = 13,

+

+            /**

+             * If an attempt is made to create or change an object in a way which is

+             * incorrect with regard to namespaces.

+             * @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html

+             */

+            NAMESPACE_ERR = 14,

+

+            /**

+             * If a parameter or an operation is not supported by the underlying

+             * object.

+             * @since http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html

+             */

+            INVALID_ACCESS_ERR = 15,

+        };

+public:

+        /**

+         * Return the exception reason.

+         * @return the exception reason.

+         */

+        short getCode() const

+        {

+            return code;

+        }

+};

+#endif /*__DOMEXCEPTION__*/

+

diff --git a/media/libdrm/mobile2/include/util/domcore/DOMString.h b/media/libdrm/mobile2/include/util/domcore/DOMString.h
new file mode 100644
index 0000000..f6f2b14
--- /dev/null
+++ b/media/libdrm/mobile2/include/util/domcore/DOMString.h
@@ -0,0 +1,26 @@
+/*
+ * 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 __DOM_STRING_H__

+#define __DOM_STRING_H__

+

+#include <ustring.h>

+using namespace ustl;

+typedef string DOMString;

+

+const DOMString emptyString = DOMString("");

+

+#endif /*__DOM_STRING_H_*/

+

diff --git a/media/libdrm/mobile2/include/util/domcore/DocumentImpl.h b/media/libdrm/mobile2/include/util/domcore/DocumentImpl.h
new file mode 100644
index 0000000..b003e2a
--- /dev/null
+++ b/media/libdrm/mobile2/include/util/domcore/DocumentImpl.h
Binary files differ
diff --git a/media/libdrm/mobile2/include/util/domcore/ElementImpl.h b/media/libdrm/mobile2/include/util/domcore/ElementImpl.h
new file mode 100644
index 0000000..2b0bc45
--- /dev/null
+++ b/media/libdrm/mobile2/include/util/domcore/ElementImpl.h
@@ -0,0 +1,147 @@
+/*
+ * 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 __DOM_ELEMENT_IMPL__

+#define __DOM_ELEMENT_IMPL__

+#include "NodeImpl.h"

+#include "NodeListImpl.h"

+#include "NodeType.h"

+

+class ElementImpl : public NodeImpl

+{

+public:

+

+        /**

+         * The name of the element. For example, in:

+         * <pre> &lt;elementExample

+         * id="demo"&gt; ... &lt;/elementExample&gt; , </pre>

+         *  <code>tagName</code> has

+         * the value <code>"elementExample"</code>. Note that this is

+         * case-preserving in XML, as are all of the operations of the DOM. The

+         * HTML DOM returns the <code>tagName</code> of an HTML element in the

+         * canonical uppercase form, regardless of the case in the source HTML

+         * document.

+         * @return the element's tag name.

+         */

+        virtual const DOMString* getTagName() const;

+

+        /**

+         * Retrieves an attribute value by name.

+         * @param name The name of the attribute to retrieve.

+         * @return The <code>Attr</code> value as a string, or the empty string

+         *   if that attribute does not have a specified or default value.

+         */

+        virtual const DOMString* getAttribute(const DOMString* name) const;

+

+        /**

+         * Adds a new attribute. If an attribute with that name is already present

+         * in the element, its value is changed to be that of the value

+         * parameter. This value is a simple string; it is not parsed as it is

+         * being set. So any markup (such as syntax to be recognized as an

+         * entity reference) is treated as literal text, and needs to be

+         * appropriately escaped by the implementation when it is written out.

+         * In order to assign an attribute value that contains entity

+         * references, the user must create an <code>Attr</code> node plus any

+         * <code>Text</code> and <code>EntityReference</code> nodes, build the

+         * appropriate subtree, and use <code>setAttributeNode</code> to assign

+         * it as the value of an attribute.

+         * <br>To set an attribute with a qualified name and namespace URI, use

+         * the <code>setAttributeNS</code> method.

+         * @param name The name of the attribute to create or alter.

+         * @param value Value to set in string form.

+         * @exception DOMException

+         *   INVALID_CHARACTER_ERR: Raised if the specified name contains an

+         *   illegal character.

+         *   <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.

+         */

+        virtual void setAttribute(const DOMString* name, const DOMString* value) throw (DOMException);

+

+        /**

+         * Removes an attribute by name. If the removed attribute is known to have

+         * a default value, an attribute immediately appears containing the

+         * default value as well as the corresponding namespace URI, local name,

+         * and prefix when applicable.

+         * <br>To remove an attribute by local name and namespace URI, use the

+         * <code>removeAttributeNS</code> method.

+         * @param name The name of the attribute to remove.

+         * @exception DOMException

+         *   NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.

+         */

+        virtual void removeAttribute(const DOMString* name) throw (DOMException);

+

+        /**

+         * Returns a <code>NodeList</code> of all descendant <code>Elements</code>

+         * with a given tag name, in the order in which they are encountered in

+         * a preorder traversal of this <code>Element</code> tree.

+         * @param name The name of the tag to match on. The special value "*"

+         *   matches all tags.

+         * @return A list of matching <code>Element</code> nodes.

+         */

+        NodeListImpl* getElementsByTagName(const DOMString* name) const;

+

+        /** Override getNodeType() method in NodeImpl.h.*/

+        virtual bool hasAttributes() const;

+

+        /** Override getNodeName() method in NodeImpl.h.*/

+        const DOMString* getNodeName() const;

+

+        /** Override getNodeType() method in NodeImpl.h.*/

+        NodeType getNodeType() const;

+

+        /** Defining "click()" method*/

+        virtual void click(){}

+

+        /** Defining "blur()" method,*/

+        virtual void blur(){}

+

+        /** Defining "focus()" method*/

+        virtual void focus(){}

+

+        /** Defining "change()" method*/

+        virtual void change(){}

+

+        /** Defining "select()" method*/

+        virtual void select(){}

+

+        /** Defining "onClick()" event input,textarea,button, and anchor*/

+        virtual bool onClick(){return true;}

+

+        /** Defining "onBlur()" event,for input,textarea,button,anchor and select */

+        virtual bool onBlur(){return true;}

+

+        /** Defining "onFocus()" event,for input,textarea,button,anchor and select*/

+        virtual bool onFocus(){return true;}

+

+        /** Defining "onChange()" event,for input,textarea and select tag*/

+        virtual bool onChange(){return true;}

+

+        /** Defining "onSelect()" event,for textarea and input*/

+        virtual bool onSelect(){return true;}

+

+        /**

+         * when the end tag of one element is found,this method would be called.The basic action is call seCompleted().

+        **/

+        virtual void endElement() {}

+

+private:

+        /**

+         * Get elements whose name match on <code>name</code>,than keep they into <code>nodeList</code>.

+         * @param name   The tag name of the elements to match on.

+         * @param nodeList keep all the matched element.

+         */

+        void getElementsByTagName(const DOMString* name,NodeListImpl* nodeList) const;

+};

+#endif /*__DOM_ELEMENT_IMPL__*/

+

diff --git a/media/libdrm/mobile2/include/util/domcore/NodeImpl.h b/media/libdrm/mobile2/include/util/domcore/NodeImpl.h
new file mode 100644
index 0000000..10423c3
--- /dev/null
+++ b/media/libdrm/mobile2/include/util/domcore/NodeImpl.h
@@ -0,0 +1,266 @@
+/*
+ * 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  __DOM_NODE_IMPL__

+#define  __DOM_NODE_IMPL__

+

+#include "DOMException.h"

+#include "NodeType.h"

+#include "DOMString.h"

+class LayoutAttr;

+class DocumentImpl;

+class NodeImpl {

+private:

+    /** The pointer to first children */

+    NodeImpl* firstChild;

+

+    /** The pointer to lastChild children */

+    NodeImpl* lastChild;

+

+    /** The pointer to previous sibling children */

+    NodeImpl* previousSibling;

+

+    /** The pointer to next sibling children */

+    NodeImpl* nextSibling;

+

+    /** The pointer to parent */

+    NodeImpl* parent;

+

+    /** Current node's document context */

+    const DocumentImpl* document;

+

+   /**

+     * Add next slibing node

+     * @param node the node to be add.

+     */

+    void appendNextSibling(NodeImpl* node);

+

+public:

+    /**

+     * Default constuctor.

+     */

+    NodeImpl(): firstChild(NULL),lastChild(NULL),previousSibling(NULL),nextSibling(NULL),parent(NULL),document(NULL) {};

+

+    /**

+     * Set <code>parentNode</code> as current node's parent.

+     *

+     * @param parentNode The specify parent node.

+     */

+    void setParent(NodeImpl* parentNode);

+

+    /**

+     * Set the node immediately following node.

+     *

+     * @param siblingNode The special node be insert after current node.

+     */

+    void setNextSibling(NodeImpl* siblingNode);

+

+    /**

+     * Returns the node immediately preceding this node.

+     *

+     * @param siblingNode The special node be insert before current node.

+     */

+    void setPreviousSibling(NodeImpl* siblingNode);

+

+    /**

+     * Set <code>childNode</code> as current node's first children. If current

+     * node have first child node,it will replace with the <code>childNode</code>.

+     *

+     * @param childNode The special node be set as the first children node of current

+     *                  node.

+     */

+    void setFirstChild(NodeImpl* childNode);

+

+    /**

+     * Set <code>childNode</code> as current node's last children. If current

+     * node have last child node,it will replace with the <code>childNode</code>.

+     *

+     * @param childNode The special node be set as the last children node of current

+     *                  node.

+     */

+    void setLastChild(NodeImpl* childNode);

+

+    /**

+     * The name of this node, depending on its type;

+     * @return the node's name.

+     */

+    virtual const DOMString* getNodeName() const = 0;

+

+    /**

+     * The value of this node, depending on its type;

+     * When it is defined to be <code>null</code>, setting it has no effect.

+     * @return the value of node.

+     * @exception DOMException

+     * DOMSTRING_SIZE_ERR: Raised when it would return more characters than

+     * fit in a <code>DOMString</code> variable on the implementation

+     * platform.

+     */

+    virtual const DOMString* getNodeValue() const throw (DOMException);

+

+    /**

+     * Set the node value.

+     * @param nodeValue the node value

+     * @exception DOMException

+     * NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly.

+     */

+    virtual void setNodeValue(DOMString* nodeValue) throw (DOMException);

+

+    /**

+     * A code representing the type of the underlying object, as defined above.

+     * @return the node's type.

+     */

+    virtual NodeType getNodeType() const = 0;

+

+    /**

+     * Returns whether this node (if it is an element) has any attributes.

+     * @return <code>true</code> if this node has any attributes,

+     *   <code>false</code> otherwise.

+     * @since DOM Level 2

+     */

+    virtual bool hasAttributes() const;

+

+    /**

+     * The parent of this node. All nodes, except <code>Attr</code>,

+     * <code>Document</code>, <code>DocumentFragment</code>,

+     * <code>Entity</code>, and <code>Notation</code> may have a parent.

+     * However, if a node has just been created and not yet added to the

+     * tree, or if it has been removed from the tree, this is

+     * <code>NULL</code>.

+     * @return return current node's parent.

+     */

+    NodeImpl* getParentNode() const;

+

+    /**

+     * The first child of this node. If there is no such node, this returns

+     * <code>NULL</code>.

+     * @return current node  first children.

+     */

+    NodeImpl* getFirstChild() const;

+

+    /**

+     * The last child of this node. If there is no such node, this returns

+     * <code>NULL</code>.

+     * @return current  node last children.

+     */

+    NodeImpl* getLastChild() const;

+

+    /**

+     * The node immediately preceding this node. If there is no such node,

+     * this returns <code>NULL</code>.

+     * @return current node previous sibling children.

+     */

+    NodeImpl* getPreviousSibling() const;

+

+    /**

+     * The node immediately following this node. If there is no such node,

+     * this returns <code>NULL</code>.

+     * @return return current  node next sibling children.

+     */

+    NodeImpl* getNextSibling() const;

+

+    /**

+     * Inserts the node <code>newChild</code> before the existing child node

+     * <code>refChild</code>. If <code>refChild</code> is <code>NULL</code>,

+     * insert <code>newChild</code> at the end of the list of children.

+     * <br>If <code>newChild</code> is a <code>DocumentFragment</code> object,

+     * all of its children are inserted, in the same order, before

+     * <code>refChild</code>. If the <code>newChild</code> is already in the

+     * tree, it is first removed.

+     * @param newChild The node to insert.

+     * @param refChild The reference node, i.e., the node before which the

+     *   new node must be inserted.

+     * @return The node being inserted.

+     * @exception DOMException

+     *   HIERARCHY_REQUEST_ERR: Raised if this node is of a type that does not

+     *   allow children of the type of the <code>newChild</code> node, or if

+     *   the node to insert is one of this node's ancestors or this node

+     *   itself.

+     *   <br>WRONG_DOCUMENT_ERR: Raised if <code>newChild</code> was created

+     *   from a different document than the one that created this node.

+     *   <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly or

+     *   if the parent of the node being inserted is readonly.

+     *   <br>NOT_FOUND_ERR: Raised if <code>refChild</code> is not a child of

+     *   this node.

+     */

+    NodeImpl* insertBefore(NodeImpl* newChild, NodeImpl* refChild) throw (DOMException);

+

+    /**

+     * Removes the child node indicated by <code>oldChild</code> from the list

+     * of children, and returns it.

+     * @param oldChild The node being removed.

+     * @return The node removed.

+     * @exception DOMException

+     *   NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.

+     *   <br>NOT_FOUND_ERR: Raised if <code>oldChild</code> is not a child of

+     *   this node.

+     */

+    NodeImpl* removeChild(NodeImpl* oldChild) throw (DOMException);

+

+    /**

+     * Adds the node <code>newChild</code> to the end of the list of children

+     * of this node. If the <code>newChild</code> is already in the tree, it

+     * is first removed.

+     * @param newChild The node to add.If it is a

+     *   <code>DocumentFragment</code> object, the entire contents of the

+     *   document fragment are moved into the child list of this node

+     * @return The node added.

+     * @exception DOMException

+     *   HIERARCHY_REQUEST_ERR: Raised if this node is of a type that does not

+     *   allow children of the type of the <code>newChild</code> node, or if

+     *   the node to append is one of this node's ancestors or this node

+     *   itself.

+     *   <br>WRONG_DOCUMENT_ERR: Raised if <code>newChild</code> was created

+     *   from a different document than the one that created this node.

+     *   <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly or

+     *   if the previous parent of the node being inserted is readonly.

+     */

+    NodeImpl* appendChild(NodeImpl* newChild) throw (DOMException);

+

+    /**

+     * Returns whether this node has any children.

+     * @return <code>true</code> if this node has any children,

+     *   <code>false</code> otherwise.

+     */

+    bool hasChildNodes() const;

+

+    virtual ~NodeImpl() {};

+

+    /**

+     * Get the LayoutAttr of this node

+     * @return the pointer to  LayoutAttr

+     */

+    virtual LayoutAttr* getLayoutAttr() const { return NULL;}

+

+    /**

+     * Set the LayoutAttr of this node

+     * @param attr the attributes to be set

+     * @return void

+     */

+    virtual void setLayoutAttr(LayoutAttr* attr) { return;}

+

+    /**

+     * Set document context.

+     * @param document The specify document context.

+     */

+    void setDocument(const DocumentImpl* document);

+

+    /**

+     * Get document context.

+     * @return the current node's document context.

+     */

+    const DocumentImpl* getDocument() const;

+};

+#endif  /*__DOM_NODE_IMPL__*/

+

diff --git a/media/libdrm/mobile2/include/util/domcore/NodeIterator.h b/media/libdrm/mobile2/include/util/domcore/NodeIterator.h
new file mode 100644
index 0000000..06fda28
--- /dev/null
+++ b/media/libdrm/mobile2/include/util/domcore/NodeIterator.h
@@ -0,0 +1,74 @@
+/*
+ * 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 __DOM_NODE_ITERATOR__

+#define __DOM_NODE_ITERATOR__

+class NodeImpl;

+/**

+ * The Iterator is used to visit DOM_TREE.

+ * <code>Attention</code>:The Iterator is not safe.

+ * When the caller using the Iterator to access the tree,

+ * the underlying data was modified, the next() or prev() may not return the right result.

+ * means we have a <code>restriction</code>: the Iterator can only be used in the case that the tree structure will

+ * not be modified before the end of iteration.

+ */

+class NodeIterator {

+private:

+    NodeImpl* scopeNode;/** The specify the range of iterating */

+    NodeImpl* endNode;  /** The specify the end position of iterating */

+    NodeImpl* curNode;  /** The position of current node.*/

+

+    /**

+     * Find the specify node's next order node.

+     * @param node The specify node.

+     * @return The next order node when success.

+     *         NULL when has an error.

+     */

+    NodeImpl* findNextOrderNode(NodeImpl* node);

+

+    /**

+     * Find the specify node's previous order node.

+     * @param node The specify node.

+     * @return The previous order node when success.

+     *         NULL when has an error.

+     */

+    NodeImpl* findPreviousOrderNode(NodeImpl* node);

+public:

+    /**

+     * Construct for NodeIterator.

+     * we must specify <code>start</code> value when we want iterate the DOM_TREE.

+     * and we also can specify the <code>scope</code> if want restrict the range of iterator.

+     * (eg: restrict the range of iterating at a subtree).otherwise it will iterate the whole DOM_TREE.

+     * @param start The start position.

+     * @param scope The scope of iterating.

+     * @param end The end position of iterating.

+     */

+    NodeIterator(NodeImpl* start, NodeImpl* scope = NULL, NodeImpl* end = NULL);

+

+    /**

+     * Get next order node at current position in DOM_TREE.

+     * @return NULL On there is not node can be get.

+     *         The pointer of node On can get next node.

+     */

+    NodeImpl* next();

+

+    /**

+     * Get next order node at current position in DOM_TREE.

+     * @return NULL On there is not node can be get.

+     *         The pointer of node On can get previous node.

+     */

+    NodeImpl* prev();

+};

+#endif /*  __DOM_NODE_ITERATOR__ */

diff --git a/media/libdrm/mobile2/include/util/domcore/NodeListImpl.h b/media/libdrm/mobile2/include/util/domcore/NodeListImpl.h
new file mode 100644
index 0000000..07c0a6a
--- /dev/null
+++ b/media/libdrm/mobile2/include/util/domcore/NodeListImpl.h
@@ -0,0 +1,48 @@
+/*
+ * 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 __NODE_LIST_IMPL__

+#define __NODE_LIST_IMPL__

+

+#include "NodeImpl.h"

+#include "Vector.h"

+class NodeListImpl {

+private:

+    vector<const NodeImpl*> nodeList;

+public:

+    /**

+     *  Add a special node into list.

+     *  @param newNode specify component.

+     */

+    void append(const NodeImpl* newNode);

+

+    /**

+     * Return The special position node pointer.

+     * @param index The special position.

+     * @return The node's pointer on success.

+     *         NULL when out of list's boundary.

+     */

+    const NodeImpl* item(int index) const;

+

+    /**

+     * Return the length of list.

+     * @return the length of list.

+     */

+    int getLength() const;

+

+    ~NodeListImpl();

+};

+#endif /*__NODE_LIST_IMPL__ */

+

diff --git a/media/libdrm/mobile2/include/util/domcore/NodeType.h b/media/libdrm/mobile2/include/util/domcore/NodeType.h
new file mode 100644
index 0000000..0e51a63
--- /dev/null
+++ b/media/libdrm/mobile2/include/util/domcore/NodeType.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 __DOM_NODE_TYPE__

+#define __DOM_NODE_TYPE__

+enum NodeType {

+    /**

+     * The node is an <code>Element</code>.

+     */

+    ELEMENT_NODE = 1,

+    /**

+     * The node is an <code>Attr</code>.

+     */

+    ATTRIBUTE_NODE = 2,

+    /**

+     * The node is a <code>Text</code> node.

+     */

+    TEXT_NODE                 = 3,

+    /**

+     * The node type is CDATASection.

+     */

+    CDATA_SECTION_NODE        = 4,

+    /**

+     * The node type is an EntityReference.

+     */

+    ENTITY_REFERENCE_NODE     = 5,

+    /**

+     * The node type is an <code>Entity</code>.

+     */

+    ENTITY_NODE               = 6,

+    /**

+     * The node type is a ProcessingInstruction.

+     */

+    PROCESSING_INSTRUCTION_NODE = 7,

+    /**

+     * The node is a Comment

+     */

+    COMMENT_NODE              = 8,

+    /**

+     * The node is a Document.

+     */

+    DOCUMENT_NODE             = 9,

+    /**

+     * The node is a DocumentType.

+     */

+    DOCUMENT_TYPE_NODE        = 10,

+    /**

+     * The node is a DocumentFragment.

+     */

+    DOCUMENT_FRAGMENT_NODE    = 11,

+    /**

+     * The node is a Notation.

+     */

+    NOTATION_NODE             = 12,

+};

+#endif

diff --git a/media/libdrm/mobile2/include/util/domcore/TextImpl.h b/media/libdrm/mobile2/include/util/domcore/TextImpl.h
new file mode 100644
index 0000000..fc55fcd
--- /dev/null
+++ b/media/libdrm/mobile2/include/util/domcore/TextImpl.h
@@ -0,0 +1,40 @@
+/*
+ * 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 __DOM_TEXT_IMPL__

+#define __DOM_TEXT_IMPL__

+#include "CharacterDataImpl.h"

+class TextImpl:public CharacterDataImpl

+{

+private:

+        const static DOMString nodeName;

+public:

+        /** Text default constructor for TextImpl.*/

+        TextImpl();

+

+        /**

+         * Constructor for TextImpl

+         * @param data The specify data to be set.

+         */

+        TextImpl(const DOMString* data);

+

+        /** Override getNodeType method in NodeImpl.h */

+        NodeType getNodeType() const;

+

+        /** Override getNodeName method in NodeImpl.h */

+        const DOMString* getNodeName() const;

+};

+#endif /*__DOM_TEXT_IMPL__*/

+

diff --git a/media/libdrm/mobile2/include/util/domcore/Vector.h b/media/libdrm/mobile2/include/util/domcore/Vector.h
new file mode 100644
index 0000000..8ceae3b
--- /dev/null
+++ b/media/libdrm/mobile2/include/util/domcore/Vector.h
@@ -0,0 +1,21 @@
+/*
+ * 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 __VECTOR_H__

+#define __VECTOR_H__

+#include <uvector.h>

+using namespace ustl;

+#endif /*__VECTOR_H__*/

+

diff --git a/media/libdrm/mobile2/include/util/domcore/stack.h b/media/libdrm/mobile2/include/util/domcore/stack.h
new file mode 100644
index 0000000..cfcf4e5
--- /dev/null
+++ b/media/libdrm/mobile2/include/util/domcore/stack.h
@@ -0,0 +1,21 @@
+/*
+ * 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 __STACK_H__

+#define __STACK_H__

+#include <ustack.h>

+using namespace ustl;

+#endif /*__STACK_H__*/

+

diff --git a/media/libdrm/mobile2/include/util/xml/DomExpatAgent.h b/media/libdrm/mobile2/include/util/xml/DomExpatAgent.h
new file mode 100644
index 0000000..9972d5b
--- /dev/null
+++ b/media/libdrm/mobile2/include/util/xml/DomExpatAgent.h
@@ -0,0 +1,104 @@
+/*
+ * 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 _DOMEXPATAGENT_
+#define _DOMEXPATAGENT_
+
+#include <Drm2CommonTypes.h>
+#include <ofstream.h>
+#include <sostream.h>
+#include <ustring.h>
+#include <sistream.h>
+#include <util/domcore/NodeImpl.h>
+#include <util/domcore/DOMString.h>
+#include "ExpatWrapper.h"
+#include "XMLElementImpl.h"
+#include "XMLDocumentImpl.h"
+using namespace ustl;
+
+class DomExpatAgent : public ExpatWrapper {
+public:
+    /**
+     * Constructor for DomExpatAgent.
+     * @param xmlDocPtr XMLDocument pointer.
+     */
+    DomExpatAgent(XMLDocumentImpl* xmlDocPtr);
+
+    /** Destructor for DomExpatAgent. */
+    ~DomExpatAgent();
+
+    /**
+     * Generate XML DOM Document from XML source.
+     * @param <code>xmlStream</code> the XML source stream.
+     * @return ture or false to indicate whether generate successfully.
+     */
+    bool generateDocumentFromXML(istringstream *xmlStream);
+
+    /**
+     * Generate XML stream from XML DOM document.
+     * @return xml stream.
+     */
+    ostringstream* generateXMLFromDocument();
+
+    /**
+     * deal with start element in Expat.
+     */
+    virtual void startElement(const XML_Char *name,
+                              const XML_Char **atts);
+
+    /**
+     * deal with end element for Expat.
+     */
+    virtual void endElement(const XML_Char *name);
+
+    /**
+     * deal with data handler for Expat.
+     */
+    virtual void dataHandler(const XML_Char *s, int len);
+
+PRIVATE:
+    /**
+     * Push a xml element with the specific tag name into stack.
+     * @param name The name of tag.
+     * @param atts The attributes of related tag.
+     */
+    void pushTag(const DOMString *name, const XML_Char **atts);
+
+    /**
+     * Append text into top element of stack.
+     * @param text The data related to the present tag.
+     */
+    void appendText(const DOMString *text);
+
+    /**
+     * Pop the xml element with the specific tag name.
+     * @param name The name of tag.
+     */
+    void popTag(const DOMString *name);
+
+    /**
+     * Traverse the XML DOM document starting from specific element.
+     * @param root The specific element start to traverse.
+     */
+    void traverse(ElementImpl *root);
+
+PRIVATE:
+    vector<NodeImpl*> mStack; /**< the stack to manage the tag. */
+    XMLElementImpl* mTopElementPtr; /**< the top element of the stack. */
+    XMLDocumentImpl* mXMLDocumentPtr; /**< XML DOM document pointer. */
+    ostringstream mXMLostream; /**< xml output stream. */
+};
+
+#endif
diff --git a/media/libdrm/mobile2/include/util/xml/ExpatWrapper.h b/media/libdrm/mobile2/include/util/xml/ExpatWrapper.h
new file mode 100644
index 0000000..5a2d7fe
--- /dev/null
+++ b/media/libdrm/mobile2/include/util/xml/ExpatWrapper.h
@@ -0,0 +1,81 @@
+/*
+ * 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 _XML_H_
+#define _XML_H_
+
+#include <expat.h>
+#include <ustring.h>
+#include <Drm2CommonTypes.h>
+
+using namespace ustl;
+
+class ExpatWrapper {
+public:
+    /**
+     * Constructor for ExpatWrapper.
+     */
+    ExpatWrapper();
+
+    /**
+     * Destructor for ExpatWrapper.
+     */
+    virtual ~ExpatWrapper();
+
+    /**
+     * decode call expat to parse the xml.
+     * @param buf The buffer to be parsed.
+     * @param len The length of the buffer.
+     * @param isFinal The flag to indicate whether the buffer
+     *                is a fragment or whole xml.
+     */
+    int decode(const char* buf, int len, int isFinal);
+
+    /**
+     * virtual funtion to deal with the start element in expat, need implement by child class.
+     */
+    virtual void startElement(const XML_Char *name, const XML_Char **atts);
+
+    /**
+     * virtual funtion to deal with the end element in expat, need implement by child class.
+     */
+    virtual void endElement(const XML_Char *name);
+
+    /**
+     * virtual funtion to deal with the data handler in expat, need implement by child class.
+     */
+    virtual void dataHandler(const XML_Char *s, int len);
+
+PRIVATE:
+    /**
+     * Callback for Expat startElement.
+     */
+    static void startElementCallback(void *userData, const XML_Char *name, const XML_Char **atts);
+
+    /**
+     * Callback for Expat endElement.
+     */
+    static void endElementCallback(void *userData, const XML_Char *name);
+
+    /**
+     * Callback for Expat dataHandler.
+     */
+    static void dataHandlerCallback(void *userData, const XML_Char *s, int len);
+
+PRIVATE:
+    XML_Parser mParser; /**< The expat parser object. */
+};
+
+#endif
diff --git a/media/libdrm/mobile2/include/util/xml/XMLDocumentImpl.h b/media/libdrm/mobile2/include/util/xml/XMLDocumentImpl.h
new file mode 100644
index 0000000..c29b87d
--- /dev/null
+++ b/media/libdrm/mobile2/include/util/xml/XMLDocumentImpl.h
@@ -0,0 +1,52 @@
+/*
+ * 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 _XMLDOCUMENTIMPL_H_
+#define _XMLDOCUMENTIMPL_H_
+
+#include <Drm2CommonTypes.h>
+#include <util/domcore/DocumentImpl.h>
+
+class XMLDocumentImpl : public DocumentImpl {
+public:
+    /** Constructor for XMLDocumentImpl. */
+    XMLDocumentImpl();
+
+    /** Destructor for XMLDocumentImpl. */
+    ~XMLDocumentImpl();
+
+    /**
+     * Get the first child element of the document.
+     * @return the first child <code>Element</code> of document.
+     */
+    virtual ElementImpl* getDocumentElement() const;
+
+    /**
+     * Create a XML element with the specific name.
+     * @param tagName The specific tag name.
+     * @return a new xml <code>Element</code>
+     * @exception DOMException
+     */
+    virtual ElementImpl* createElement(const DOMString* tagName) const throw (DOMException);
+
+    /**
+     * Create a text node with the specific data.
+     * @param data The specific data.
+     * @return a new <code>Text</code> node.
+     */
+    virtual TextImpl* createTextNode(const DOMString* data) const;
+};
+
+#endif
diff --git a/media/libdrm/mobile2/include/util/xml/XMLElementImpl.h b/media/libdrm/mobile2/include/util/xml/XMLElementImpl.h
new file mode 100644
index 0000000..a0c95ec
--- /dev/null
+++ b/media/libdrm/mobile2/include/util/xml/XMLElementImpl.h
@@ -0,0 +1,105 @@
+/*
+ * 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 _XMLELEMENTIMPL_H_
+#define _XMLELEMENTIMPL_H_
+
+#include <Drm2CommonTypes.h>
+#include <util/domcore/ElementImpl.h>
+#include <util/domcore/DOMString.h>
+#include <umap.h>
+#include <ustring.h>
+using namespace ustl;
+
+typedef map<DOMString, DOMString> DOMStringMap;
+
+class XMLElementImpl : public ElementImpl {
+public:
+    /**
+     * Constructor for XMLElementImpl.
+     * @param tag The name of the tag.
+     */
+    XMLElementImpl(const DOMString *tag);
+
+    /** Destructor for XMLElementImpl. */
+    ~XMLElementImpl();
+
+    /**
+     * Get the attribute map of the XML element.
+     * @return <code>DOMStringMap</code>
+     */
+    const DOMStringMap* getAttributeMap() const;
+
+    /**
+     * Get the tag name of the element.
+     * return tag name.
+     */
+    virtual const DOMString* getTagName() const;
+
+    /**
+     * Set the attribute of the element.
+     * @param name The key of the attribute.
+     * @param value The value of the attribute.
+     */
+    virtual void setAttribute(const DOMString* name, const DOMString* value) throw (DOMException);
+
+    /**
+     * Remove the specific attribute.
+     * @param name The key of the attribute.
+     * @exception DOMException.
+     */
+    virtual void removeAttribute(const DOMString* name) throw (DOMException);
+
+    /**
+     * Get the specific attribute.
+     * @param name The key of the attribute.
+     * @return the value of the attribute.
+     */
+    virtual const DOMString* getAttribute(const DOMString* name) const;
+
+    /**
+     * Detect whether element has attributes or not.
+     * @return true or false to indicate the result.
+     */
+    virtual bool hasAttributes() const;
+
+    /**
+     * Find the first child node in element by its tag name.
+     * @param element the specific element to be found.
+     * @param tag the specific tag name to be searched.
+     * @return NULL if not found otherwise the child node.
+     */
+    const NodeImpl* findSoloChildNode(const char* tag) const;
+
+    /**
+     * Get the first text containted in first child of the element.
+     * @param tag the specific tag name to be searched.
+     * @return NULL if not found otherwise the text.
+     */
+    const string* getSoloText(const char* tag) const;
+
+    /**
+     * Get the first child xml element containted in the element.
+     * @param tag the specific tag name to be searched.
+     * @return NULL if not found otherwise the element.
+     */
+    const XMLElementImpl* getSoloElement(const char* tag) const;
+
+PRIVATE:
+    DOMString mTagName; /**< The tag name. */
+    DOMStringMap mAttributeMap; /** The map of attributes. */
+};
+
+#endif
diff --git a/media/libdrm/mobile2/src/dcf/DrmDcfCommon.cpp b/media/libdrm/mobile2/src/dcf/DrmDcfCommon.cpp
new file mode 100644
index 0000000..0f5e4ac
--- /dev/null
+++ b/media/libdrm/mobile2/src/dcf/DrmDcfCommon.cpp
@@ -0,0 +1,206 @@
+/*
+ * 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.
+ */
+
+#include <dcf/DrmDcfCommon.h>
+
+int64_t ntoh_int64(int64_t x)
+{
+    return (((int64_t)(ntohl((int32_t)((x << 32) >> 32))) << 32) | (uint32_t)ntohl(((int32_t)(x >> 32))));
+}
+
+/**
+ * Class: Box
+ */
+Box::Box(const uint8_t* box):mLargeSize(0),mUserType(NULL)
+{
+    if(!box)
+    {
+        return ;
+    }
+
+    const uint8_t* p = box;
+
+    /* Get the size value */
+    mSize = ntohl(*(uint32_t *)p);
+    p += sizeof(mSize);
+
+    /* Get the type value */
+    mType = *((uint32_t *)p);
+    p += sizeof(mType);
+
+    if (1 == mSize)
+    {
+        mLargeSize = ntoh_int64(*(uint64_t *)p);
+        p += sizeof(mLargeSize);
+    }
+
+    if (DCF_USER_TYPE == mType)
+    {
+        mUserType = new uint8_t[USER_TYPE_LEN];
+        memcpy(mUserType, p, USER_TYPE_LEN);
+        p += USER_TYPE_LEN;
+    }
+
+    mBoxLength = p - box;
+}
+
+Box::Box(const Box& other)
+{
+    mSize = other.mSize;
+    mType = other.mType;
+    mLargeSize = other.mLargeSize;
+    mUserType = NULL;
+
+    if(other.mUserType)
+    {
+        mUserType = new uint8_t[USER_TYPE_LEN];
+        memcpy(mUserType,other.mUserType,USER_TYPE_LEN);
+    }
+}
+
+Box& Box::operator=(const Box& other)
+{
+    if(this == &other)
+    {
+        return *this;
+    }
+
+    if(mUserType)
+    {
+        delete []mUserType;
+        mUserType = NULL;
+    }
+
+    if(other.mUserType)
+    {
+        mUserType = new uint8_t[USER_TYPE_LEN];
+        memcpy(mUserType, other.mUserType, USER_TYPE_LEN);
+    }
+
+    return *this;
+}
+
+Box::~Box()
+{
+    if(mUserType)
+    {
+        delete []mUserType;
+        mUserType = NULL;
+    }
+}
+
+uint64_t Box::getSize(void) const
+{
+    if(1 == mSize)
+    {
+        return mLargeSize;
+    }
+
+    return mSize;
+}
+
+uint32_t Box::getType(void) const
+{
+    return mType;
+}
+
+const uint8_t* Box::getUsertype(void) const
+{
+    return mUserType;
+}
+
+uint32_t Box::getLen(void) const
+{
+    return mBoxLength;
+}
+
+
+/**
+ * Class: FullBox
+ */
+FullBox::FullBox(const uint8_t* fullBox) : Box(fullBox)
+{
+    if(!fullBox)
+    {
+        return ;
+    }
+
+    const uint8_t* p = fullBox;
+
+    p += Box::getLen();
+
+    mVersion = *p;
+    p++;
+
+    memcpy(mFlag, p,FLAG_LEN);
+    p += FLAG_LEN;
+
+    mFullBoxLength = p - fullBox;
+}
+
+uint8_t FullBox::getVersion(void) const
+{
+    return mVersion;
+}
+
+const uint8_t* FullBox::getFlag(void) const
+{
+    return mFlag;
+}
+
+uint32_t FullBox::getLen(void) const
+{
+    return mFullBoxLength;
+}
+
+///// class TextualHeader implementation
+TextualHeader::TextualHeader(const string& inData)
+{
+    string::size_type loc1 = inData.find(":", 0);
+
+    if (loc1 != string::npos)
+    {
+        name.assign(inData, 0, loc1);
+    }
+
+    string::size_type loc2 = inData.find(";", loc1 + 1);
+
+    if (loc2 != string::npos)
+    {
+        value.assign(inData, loc1 + 1, loc2 - loc1 - 1);
+        param.assign(inData, loc2 + 1, inData.length() - loc2 - 1);
+    }
+    else
+    {
+        value.assign(inData, loc1 + 1, inData.length() - loc1 - 1);
+    }
+}
+
+string TextualHeader::getName() const
+{
+    return name;
+}
+
+string TextualHeader::getValue() const
+{
+    return value;
+}
+
+string TextualHeader::getParam() const
+{
+    return param;
+}
+
diff --git a/media/libdrm/mobile2/src/dcf/DrmDcfContainer.cpp b/media/libdrm/mobile2/src/dcf/DrmDcfContainer.cpp
new file mode 100644
index 0000000..517c930
--- /dev/null
+++ b/media/libdrm/mobile2/src/dcf/DrmDcfContainer.cpp
@@ -0,0 +1,294 @@
+/*
+ * 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.
+ */
+
+#include <dcf/DrmDcfContainer.h>
+
+DcfContainer::DcfContainer(const uint8_t* data,istream& inRawData,uint64_t conOff)
+                : FullBox(data),mConStream(inRawData)
+{
+    if(!data)
+    {
+        return;
+    }
+
+    const uint8_t* p = data;
+    const uint8_t* flag = this->getFlag();
+
+    if(flag[0] & USER_DATA_FLAG)
+    {
+        mHasUserData = true;
+    }
+    else
+    {
+        mHasUserData = false;
+    }
+
+    p += this->getLen();
+
+    FullBox fullBoxDiscrete(p);
+
+    p += fullBoxDiscrete.getLen();
+
+    mContentTypeLen = *p;
+    p++;
+
+    mContentType.assign((const char*)p,0,mContentTypeLen);
+    p += mContentTypeLen;
+
+    // parse common header
+    FullBox fullBoxComm(p);
+    p += fullBoxComm.getLen();
+
+    mEncryptionMethod = *p;
+    p++;
+
+    mPaddingScheme = *p;
+    p++;
+
+    mPlaintextLength = ntoh_int64(*((uint64_t *)p));
+    p += sizeof(mPlaintextLength);
+
+    mContentIDLength = ntohs(*(uint16_t *)p);
+    p += sizeof(mContentIDLength);
+
+    mRightsIssuerURLLength = ntohs(*(uint16_t *)p);
+    p += sizeof(mRightsIssuerURLLength);
+
+    mTextualHeadersLength = ntohs(*(uint16_t *)p);
+    p += sizeof(mTextualHeadersLength);
+
+    mContentID.assign((const char *)p,0,mContentIDLength);
+    p += mContentIDLength;
+
+    mRightsIssuerURL.assign((const char *)p,0,mRightsIssuerURLLength);
+    p += mRightsIssuerURLLength;
+
+    // parse textual header
+    if (mTextualHeadersLength > 0)
+    {
+        if(false == parseTextualHeaders(p,mTextualHeadersLength))
+        {
+            return;
+        }
+
+        p += mTextualHeadersLength;
+    }
+
+    ////////////// parser group id
+
+    ///parse content
+    p = data + this->getLen() + fullBoxDiscrete.getSize();
+    FullBox fullBoxContetn(p);
+    p += fullBoxContetn.getLen();
+    mDataLen = ntoh_int64(*((uint64_t *)p));
+    p += sizeof(mDataLen);
+
+    mDecOffset = conOff + (p - data);
+    p += mDataLen;
+
+    /////////////// parser user data
+}
+
+DcfContainer::~DcfContainer()
+{
+    uint32_t size = mTextualHeaders.size();
+
+    for(uint32_t i = 0; i < size; i++)
+    {
+        delete mTextualHeaders[i];
+    }
+
+    mTextualHeaders.clear();
+    mCustomHeader.clear();
+}
+
+
+string DcfContainer::getContentType(void) const
+{
+    return mContentType;
+}
+
+uint8_t DcfContainer::getEncryptionMethod(void) const
+{
+    return mEncryptionMethod;
+}
+
+uint8_t DcfContainer::getPaddingScheme(void) const
+{
+    return mPaddingScheme;
+}
+
+uint64_t DcfContainer::getPlaintextLength(void) const
+{
+    return mPlaintextLength;
+}
+
+uint16_t DcfContainer::getContentIDLength(void) const
+{
+    return mContentIDLength;
+}
+
+uint16_t DcfContainer::getRightsIssuerURLLength(void) const
+{
+    return mRightsIssuerURLLength;
+}
+
+uint16_t DcfContainer::getTextualHeadersLength(void) const
+{
+    return mTextualHeadersLength;
+}
+
+string DcfContainer::getContentID(void) const
+{
+    return mContentID;
+}
+
+string DcfContainer::getRightsIssuerURL(void) const
+{
+    return mRightsIssuerURL;
+}
+
+string DcfContainer::getPreviewMethod(void) const
+{
+    return mSlientMethod;
+}
+
+string DcfContainer::getContentLocation(void) const
+{
+    return mContentLocation;
+}
+
+string DcfContainer::getContentURL(void) const
+{
+    return mContentURL;
+}
+
+vector<string> DcfContainer::getCustomerHead(void) const
+{
+    return mCustomHeader;
+}
+
+istream& DcfContainer::getStream(void) const
+{
+    return mConStream;
+}
+
+DrmInStream DcfContainer::getPreviewElementData(void) const
+{
+     // get data based on mPreviewElementURI
+     //encryptedData = ;
+
+     DrmInStream inStream;
+     return inStream;
+}
+
+DrmInStream DcfContainer::getDecryptContent(uint8_t* decryptKey) const
+{
+    DrmInStream inStream(this,decryptKey);
+    return inStream;
+}
+
+bool DcfContainer::parseTextualHeaders(const uint8_t* data, uint32_t len)
+{
+    if(!data)
+    {
+        return false;
+    }
+
+    const uint8_t* p = data;
+
+    while (len > (uint32_t)(p - data))
+    {
+        uint32_t l = strlen((const char*)p);
+
+        string str((const char*)p, l);
+        TextualHeader* tmp = new TextualHeader(str);
+
+        if(!tmp)
+        {
+            return false;
+        }
+
+        mTextualHeaders.push_back(tmp);
+
+        p += l + 1;
+    }
+
+    uint32_t size = mTextualHeaders.size();
+    uint32_t silentpos = 0;
+    uint32_t previewpos = 0;
+
+    for( uint32_t i = 0; i < size; i++)
+    {
+        string tempStr = mTextualHeaders[i]->getName();
+
+        if(tempStr == "Silent")
+        {
+            silentpos = i;
+            mSlientMethod = mTextualHeaders[i]->getValue();
+            mSilentRightsURL = mTextualHeaders[i]->getParam();
+        }
+        else if(tempStr == "Preview")
+        {
+            previewpos = i;
+            mPreviewMethod = mTextualHeaders[i]->getValue();
+
+            if(mPreviewMethod == "instant")
+            {
+                mPreviewElementURI = mTextualHeaders[i]->getParam();
+            }
+            else
+            {
+                mPreviewRightsURL = mTextualHeaders[i]->getParam();
+            }
+        }
+        else if(tempStr == "ContentURL")
+        {
+            mContentURL = mTextualHeaders[i]->getValue();
+        }
+        else if(tempStr == "ContentVersion")
+        {
+            mContentVersion = mTextualHeaders[i]->getValue();
+        }
+        if(tempStr == "Content-Location")
+        {
+            mContentLocation = mTextualHeaders[i]->getValue();
+        }
+        else
+        {
+            string str = mTextualHeaders[i]->getName();
+            str += ":";
+            str += mTextualHeaders[i]->getValue();
+            mCustomHeader.push_back(str);
+        }
+    }
+
+    if(silentpos < previewpos)
+    {
+        mSilentFirst = true;
+    }
+    else
+    {
+        mSilentFirst = false;
+    }
+
+    return true;
+}
+
+
+
+
+
diff --git a/media/libdrm/mobile2/src/dcf/DrmIStream.cpp b/media/libdrm/mobile2/src/dcf/DrmIStream.cpp
new file mode 100644
index 0000000..1bcc16a
--- /dev/null
+++ b/media/libdrm/mobile2/src/dcf/DrmIStream.cpp
@@ -0,0 +1,94 @@
+/*
+ * 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.
+ */
+
+#include <dcf/DrmIStream.h>
+
+
+DrmInStream::DrmInStream(const DcfContainer* container,uint8_t* Key)
+:mDcfCon(container),mDecryptPos(0)
+{
+    memcpy(mAesKey,Key,AES_KEY_LEN);
+}
+
+uint64_t DrmInStream::size() const
+{
+    return mDcfCon->mPlaintextLength;
+}
+
+uint64_t DrmInStream::read(uint8_t* data, uint64_t len)
+{
+    if(!data)
+    {
+        return 0;
+    }
+
+    if(mDecryptPos >= mDcfCon->mPlaintextLength)
+    {
+        return 0;
+    }
+
+    uint64_t readLen = len;
+
+    // come to the end of decrypted data
+    if(mDecryptPos + len > mDcfCon->mPlaintextLength)
+    {
+        readLen = mDcfCon->mPlaintextLength - mDecryptPos;
+    }
+
+    uint64_t encLen = mDcfCon->mDataLen;
+    uint8_t* encData = new uint8_t[encLen];
+
+    if(!encData)
+    {
+        return 0;
+    }
+
+    mDcfCon->mConStream.seek(mDcfCon->mDecOffset);
+    mDcfCon->mConStream.read(encData,encLen);
+
+    uint8_t iv[AES_IV_LEN] = {0};
+
+    memcpy(iv,encData,AES_IV_LEN);
+    encLen -= AES_IV_LEN;
+
+    if(AES_128_CBC != mDcfCon->mEncryptionMethod)
+    {
+        delete []encData;
+        return 0;
+    }
+
+    AesAgent drmAesDecrypt(AES_128_CBC,mAesKey);
+    int32_t padLen = drmAesDecrypt.decContent( iv,
+                                               encData + AES_IV_LEN,
+                                               encLen,
+                                               data);
+
+    delete []encData;
+
+    if(padLen >= 0)
+    {
+        return readLen;
+    }
+    else
+    {
+        return 0;
+    }
+}
+
+
+
+
+
diff --git a/media/libdrm/mobile2/src/dcf/DrmRawContent.cpp b/media/libdrm/mobile2/src/dcf/DrmRawContent.cpp
new file mode 100644
index 0000000..8813e3c
--- /dev/null
+++ b/media/libdrm/mobile2/src/dcf/DrmRawContent.cpp
@@ -0,0 +1,164 @@
+/*
+ * 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.
+ */
+
+#include <dcf/DrmRawContent.h>
+
+
+DrmRawContent::DrmRawContent(istream& inRawData)
+{
+    uint32_t count = inRawData.stream_size();
+
+    if (count <= MAX_PIECE_LEN)
+    {
+        uint8_t* data = new uint8_t[count];
+
+        if(!data)
+        {
+            return;
+        }
+
+        inRawData.read(data,count);
+
+        const uint8_t* dcf = data;
+
+        //parse DCF file header
+        if(false == parseDcfHeader(dcf))
+        {
+            delete []data;
+            return;
+        }
+
+        dcf = data;
+        dcf += FIX_HEADER_LEN;
+
+        if(dcf >= (data + count))
+        {
+            return;
+        }
+
+        // parse container box
+        FullBox conFullBox(dcf);
+
+        if(DCF_CONTAINER_BOX != conFullBox.getType())
+        {
+            return;
+        }
+
+        //check whether it is multipart DCF or not
+        do
+        {
+            uint64_t size = conFullBox.getSize();
+
+            mContainer.push_back(new DcfContainer(dcf,inRawData,dcf-data));
+
+            dcf += size;
+
+            // come to the end of raw content
+            if(dcf >= (data + count))
+            {
+                break;
+            }
+
+            conFullBox = FullBox(dcf);
+        }while(DCF_CONTAINER_BOX == conFullBox.getType());
+
+        // compute DCF hash using Sha1Agent
+        Sha1Agent drmSha1Hash;
+        drmSha1Hash.computeHash(data,dcf-data,mDcfHash);
+
+        //// parse mutable box
+
+        delete []data;
+    }
+}
+
+DrmRawContent::~DrmRawContent()
+{
+    uint32_t size = mContainer.size();
+
+    for(uint32_t i = 0; i < size; i++)
+    {
+        delete mContainer[i];
+    }
+
+    mContainer.clear();
+}
+
+vector<DcfContainer*> DrmRawContent::getContents(void) const
+{
+    return mContainer;
+}
+
+uint32_t DrmRawContent::getDcfHashLen() const
+{
+    return DCF_HASH_LEN;
+}
+
+void DrmRawContent::getDcfHash(uint8_t* outDcfHash) const
+{
+    if(outDcfHash)
+    {
+        memcpy(outDcfHash,mDcfHash,DCF_HASH_LEN);
+    }
+
+    return;
+}
+
+bool DrmRawContent::parseDcfHeader(const uint8_t* dcfHead)
+{
+    if(!dcfHead)
+    {
+        return false;
+    }
+
+    if(FIX_HEADER_LEN != ntohl(*(uint32_t *)dcfHead))
+    {
+        return false;
+    }
+
+    dcfHead += 4;
+    uint32_t type = *(uint32_t *)dcfHead;
+
+    if(DCF_FILE_TYPE != type)
+    {
+        return false;
+    }
+
+    dcfHead += 4;
+    type = *(uint32_t *)dcfHead;
+
+    if(DCF_FILE_BRAND != type)
+    {
+        return false;
+    }
+
+    dcfHead += 4;
+    if(2 != ntohl(*(uint32_t *)dcfHead))
+    {
+        return false;
+    }
+
+    dcfHead += 4;
+    type = *(uint32_t *)dcfHead;
+
+    if(DCF_FILE_BRAND != type)
+    {
+        return false;
+    }
+
+    dcfHead += 4;
+    return true;
+}
diff --git a/media/libdrm/mobile2/src/drmmanager/DrmManager.cpp b/media/libdrm/mobile2/src/drmmanager/DrmManager.cpp
new file mode 100644
index 0000000..599526f
--- /dev/null
+++ b/media/libdrm/mobile2/src/drmmanager/DrmManager.cpp
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ */
+#include <drmmanager/DrmManager.h>
+#include <ustring.h>
+#include <ofstream.h>
+#include <sostream.h>
+#include <sistream.h>
+using namespace ustl;
+
+/**see DrmManager.h */
+DrmManager::DrmManager(istream * inRawData)
+{
+    mDcfStream = NULL;
+    if (inRawData != NULL)
+    {
+        mDcfStream = inRawData;
+    }
+}
+
+/**see DrmManager.h */
+DrmManager::DrmManager(istream * inRawData, string mimeType)
+{
+    mDcfStream = inRawData;
+}
+
+/**see DrmManager.h */
+int16_t DrmManager::getListOfDcfObjects(vector<DcfContainer*> **outDcfList)
+{
+    /** call dcf functions to parse the dcf file*/
+    if (NULL == mDcfStream)
+    {
+        return ERR_DCFSTREAM_NOT_INITIALIZED;
+    }
+    if (NULL == outDcfList)
+    {
+        return ERR_DCFSTREAM_NOT_INITIALIZED;
+    }
+    *outDcfList=&mDcfs;
+    return DRM_OK;
+}
+
+/**see DrmManager.h */
+int16_t DrmManager::openDecryptedContent(DcfContainer *oneDcfObject,
+                                         int16_t operationType,
+                                         istream *outDecryptedData)
+{
+    return 1;
+}
+
+/**see DrmManager.h */
+DrmManager::~DrmManager()
+{
+
+}
diff --git a/media/libdrm/mobile2/src/rights/Asset.cpp b/media/libdrm/mobile2/src/rights/Asset.cpp
new file mode 100644
index 0000000..120b465
--- /dev/null
+++ b/media/libdrm/mobile2/src/rights/Asset.cpp
@@ -0,0 +1,110 @@
+/*
+ * 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.
+ */
+
+#include <rights/Asset.h>
+
+/** see Asset.h */
+Asset::Asset()
+{}
+
+/** see Asset.h */
+Asset::~Asset()
+{}
+
+/** see Asset.h */
+bool Asset::hasParent()
+{
+    return false;
+}
+
+/** see Asset.h */
+void Asset::setID(const string &id)
+{
+    mAssetID = id;
+}
+
+/** see Asset.h */
+const string& Asset::getID() const
+{
+    return mAssetID;
+}
+
+/** see Asset.h */
+void Asset::setContentID(const string &id)
+{
+    mContentID = id;
+}
+
+/** see Asset.h */
+const string& Asset::getContentID() const
+{
+    return mContentID;
+}
+
+/** see Asset.h */
+void Asset::setEncryptedKey(const string &key)
+{
+    mEncryptedKey = key;
+}
+
+/** see Asset.h */
+void Asset::setDCFDigest(const string &value)
+{
+    mDigestValue = value;
+}
+
+/** see Asset.h */
+const string& Asset::getDCFDigest() const
+{
+    return mDigestValue;
+}
+
+/** see Asset.h */
+void Asset::setKeyRetrievalMethod(const string &rm)
+{
+    mRetrievalMethod = rm;
+}
+
+/** see Asset.h */
+void Asset::setParentContentID(const string &id)
+{
+    mParentContentID = id;
+}
+
+/** see Asset.h */
+const string& Asset::getEncrytedKey() const
+{
+    return mEncryptedKey;
+}
+
+/** see Asset.h */
+const char* Asset::getCek() const
+{
+    return NULL;
+}
+
+/** see Asset.h */
+void Asset::recoverCek()
+{
+//fix later.
+
+}
+
+/** see Asset.h */
+const string& Asset::getParentContentID() const
+{
+    return mParentContentID;
+}
diff --git a/media/libdrm/mobile2/src/rights/Constraint.cpp b/media/libdrm/mobile2/src/rights/Constraint.cpp
new file mode 100644
index 0000000..2cb4311
--- /dev/null
+++ b/media/libdrm/mobile2/src/rights/Constraint.cpp
@@ -0,0 +1,210 @@
+/*
+ * 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.
+ */
+
+#include <rights/Constraint.h>
+
+/** see Constraint.h */
+Constraint::Constraint()
+{
+    mCount = INIT_VALUE;
+    mTimedCount = INIT_VALUE;
+    mTimer = INIT_VALUE;
+    mStart = INIT_VALUE;
+    mEnd = INIT_VALUE;
+    mInterval = INIT_VALUE;
+    mAccumulated = INIT_VALUE;
+    mExport = NONE;
+}
+
+/** see Constraint.h */
+Constraint::~Constraint()
+{}
+
+/** see Constraint.h */
+bool Constraint::isUnConstraint() const
+{
+    return (mCount == INIT_VALUE && mTimedCount == INIT_VALUE &&
+            mTimer == INIT_VALUE && mStart == INIT_VALUE &&
+            mEnd == INIT_VALUE && mInterval == INIT_VALUE &&
+            mAccumulated == INIT_VALUE && mExport == NONE &&
+            mSystemList.empty());
+}
+
+/** see Constraint.h */
+bool Constraint::isDateTimeConstraint() const
+{
+    return !(mStart == INIT_VALUE && mEnd == INIT_VALUE);
+}
+
+/** see Constraint.h */
+bool Constraint::isIntervalConstraint() const
+{
+    return !(mInterval == INIT_VALUE);
+}
+
+/** see Constraint.h */
+bool Constraint::isTimedCountConstraint() const
+{
+    return !(mTimedCount == INIT_VALUE);
+}
+
+/** see Constraint.h */
+bool Constraint::isValid(long time) const
+{
+    if (isUnConstraint())
+    {
+        return true;
+    }
+
+    if (isDateTimeConstraint())
+    {
+        if (time < mStart || time > mEnd)
+        {
+            return false;
+        }
+    }
+
+    if (mInterval == 0 || mCount == 0 ||
+        mTimedCount == 0 || mAccumulated == 0)
+    {
+        return false;
+    }
+
+    return true;
+}
+
+/** see Constraint.h */
+void Constraint::setStartTime(long time)
+{
+    mStart = time;
+}
+
+/** see Constraint.h */
+long Constraint::getStartTime() const
+{
+    return mStart;
+}
+
+/** see Constraint.h */
+void Constraint::setEndTime(long time)
+{
+    mEnd = time;
+}
+
+/** see Constraint.h */
+long Constraint::getEndTime() const
+{
+    return mEnd;
+}
+
+/** see Constraint.h */
+void Constraint::setAccumulated(long time)
+{
+    mAccumulated = time;
+}
+
+/** see Constraint.h */
+long Constraint::getAccumulated() const
+{
+    return mAccumulated;
+}
+
+/** see Constraint.h */
+void Constraint::setCount(int count)
+{
+    mCount = count;
+}
+
+/** see Constraint.h */
+int Constraint::getCount() const
+{
+    return mCount;
+}
+
+/** see Constraint.h */
+void Constraint::setTimer(int timer)
+{
+    mTimer = timer;
+}
+
+/** see Constraint.h */
+int Constraint::getTimer() const
+{
+    return mTimer;
+}
+
+/** see Constraint.h */
+void Constraint::setTimedCount(int timedCount)
+{
+    mTimedCount = timedCount;
+}
+
+/** see Constraint.h */
+int Constraint::getTimedCount() const
+{
+    return mTimedCount;
+}
+
+/** see Constraint.h */
+void Constraint::setInterval(int interval)
+{
+    mInterval = interval;
+}
+
+/** see Constraint.h */
+int Constraint::getInterval() const
+{
+    return mInterval;
+}
+
+/** see Constraint.h */
+void Constraint::setExportMode(MODE mode)
+{
+    mExport = mode;
+}
+
+/** see Constraint.h */
+Constraint::MODE Constraint::getExportMode() const
+{
+    return mExport;
+}
+
+/** see Constraint.h */
+bool Constraint::consume()
+{
+    if (isUnConstraint())
+    {
+        return true;
+    }
+
+    if (mCount > 0)
+    {
+        mCount--;
+        return true;
+    }
+
+    if (mAccumulated > 0)
+    {
+        mAccumulated--;
+        return true;
+    }
+
+    if (mTimedCount > 0)
+    {
+
+    }
+    return false;
+}
diff --git a/media/libdrm/mobile2/src/rights/OperationPermission.cpp b/media/libdrm/mobile2/src/rights/OperationPermission.cpp
new file mode 100644
index 0000000..fc75fb1
--- /dev/null
+++ b/media/libdrm/mobile2/src/rights/OperationPermission.cpp
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+
+#include <rights/OperationPermission.h>
+#include <rights/Constraint.h>
+
+/** see OperationPermission.h */
+OperationPermission::OperationPermission() : mConstraint(NULL)
+{
+
+}
+
+/** see OperationPermission.h */
+OperationPermission::OperationPermission(OPERATION type, Constraint *cst) : mType(type), mConstraint(cst)
+{
+
+}
+
+/** see OperationPermission.h */
+OperationPermission::~OperationPermission()
+{
+    delete mConstraint;
+}
+
+/** see OperationPermission.h */
+void OperationPermission::setType(OPERATION type)
+{
+    mType = type;
+}
+
+/** see OperationPermission.h */
+OperationPermission::OPERATION OperationPermission::getType() const
+{
+    return mType;
+}
+
+/** see OperationPermission.h */
+void OperationPermission::addConstraint(Constraint* constraint)
+{
+    mConstraint = constraint;
+}
+
+/** see OperationPermission.h */
+Constraint* OperationPermission::getConstraint() const
+{
+    return mConstraint;
+}
diff --git a/media/libdrm/mobile2/src/rights/Right.cpp b/media/libdrm/mobile2/src/rights/Right.cpp
new file mode 100644
index 0000000..6be9c70
--- /dev/null
+++ b/media/libdrm/mobile2/src/rights/Right.cpp
@@ -0,0 +1,79 @@
+/*
+ * 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.
+ */
+#include <rights/Right.h>
+#include <rights/OperationPermission.h>
+#include <rights/Constraint.h>
+
+/** see Right.h */
+Right::Right()
+{
+
+}
+
+/** see Right.h */
+Right::~Right()
+{
+     vector<OperationPermission*>::iterator it;
+
+     for (it = mOpList.begin(); it != mOpList.end(); it++)
+     {
+        delete(*it);
+     }
+
+     mOpList.clear();
+}
+
+/** see Right.h */
+void Right::addAssetID(const string& id)
+{
+    mAssetNameList.push_back(id);
+}
+
+/** see Right.h */
+void Right::addOperationPermission(OperationPermission* op)
+{
+    mOpList.push_back(op);
+}
+
+/** see Right.h */
+bool Right::checkPermission(OperationPermission::OPERATION type)
+{
+    for (vector<OperationPermission*>::iterator it = mOpList.begin();
+             it != mOpList.end(); it++)
+    {
+        if ((*it)->getType() == type)
+        {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+/** see Right.h */
+Constraint* Right::getConstraint(OperationPermission::OPERATION type)
+{
+    for (vector<OperationPermission*>::iterator it = mOpList.begin();
+             it != mOpList.end(); it++)
+    {
+        if ((*it)->getType() == type)
+        {
+            return (*it)->getConstraint();
+        }
+    }
+
+    return NULL;
+}
diff --git a/media/libdrm/mobile2/src/rights/Ro.cpp b/media/libdrm/mobile2/src/rights/Ro.cpp
new file mode 100644
index 0000000..8141e17
--- /dev/null
+++ b/media/libdrm/mobile2/src/rights/Ro.cpp
@@ -0,0 +1,831 @@
+/*
+ * 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.
+ */
+
+#include <rights/Ro.h>
+#include <rights/Constraint.h>
+#include <rights/OperationPermission.h>
+#include <util/xml/DomExpatAgent.h>
+#include <util/domcore/DOMString.h>
+#include <utils/Log.h>
+
+#include <uassert.h>
+#include <time.h>
+#include <ofstream.h>
+using namespace ustl;
+
+const char *STR_RO_RIGHTS = "o-ex:rights";
+const char *STR_RO_CONTEXT = "o-ex:context";
+const char *STR_RO_AGREEMENT = "o-ex:agreement";
+const char *STR_RO_ASSET = "o-ex:asset";
+const char *STR_RO_INHERIT = "o-ex:inherit";
+const char *STR_RO_DIGEST = "o-ex:digest";
+const char *STR_RO_KEYINFO = "ds:KeyInfo";
+const char *STR_RO_PERMISSION = "o-ex:permission";
+const char *STR_RO_ASSET_ID = "o-ex:id";
+const char *STR_RO_ASSET_IDREF = "o-ex:idref";
+const char *STR_RO_CONTEXT_ID = "o-dd:uid";
+const char *STR_RO_CONTEXT_VERSION = "o-dd:version";
+const char *STR_RO_DIGEST_VALUE = "ds:DigestValue";
+const char *STR_RO_CIPHER_VALUE = "xenc:CipherValue";
+const char *STR_RO_RETRIEVAL_METHOD = "ds:RetrievalMethod";
+const char *STR_RO_PLAY = "o-dd:play";
+const char *STR_RO_DISPLAY = "o-dd:display";
+const char *STR_RO_EXECUTE = "o-dd:execute";
+const char *STR_RO_PRINT = "o-dd:print";
+const char *STR_RO_EXPORT = "o-dd:export";
+const char *STR_RO_CONSTRAINT = "o-ex:constraint";
+const char *STR_RO_COUNT = "o-dd:count";
+const char *STR_RO_TIMEDCOUNT = "o-dd:timed-count";
+const char *STR_RO_TIMER = "oma-dd:timer";
+const char *STR_RO_INTERVAL = "o-dd:interval";
+const char *STR_RO_DATETIME = "o-dd:datetime";
+const char *STR_RO_START = "o-dd:start";
+const char *STR_RO_END = "o-dd:end";
+const char *STR_RO_ACCUMULATED = "o-dd:accumulated";
+const char *STR_RO_INDIVIDUAL = "o-dd:individual";
+const char *STR_RO_SYSTEM = "o-dd:system";
+
+/** see Ro.h */
+Ro::Ro()
+{
+    mDoc = new XMLDocumentImpl();
+    mProperRight = NULL;
+}
+
+/** see Ro.h */
+Ro::~Ro()
+{
+     for (vector<Right*>::iterator itr = mRightList.begin(); itr != mRightList.end(); itr++)
+     {
+        delete(*itr);
+     }
+
+     mRightList.clear();
+
+     for (vector<Asset*>::iterator ita = mAssetList.begin(); ita != mAssetList.end(); ita++)
+     {
+        delete(*ita);
+     }
+
+     mAssetList.clear();
+
+     mProperRight = NULL;
+     delete mDoc;
+
+}
+
+/** see Ro.h */
+void Ro::setRoID(string& id)
+{
+    mRoID = id;
+}
+
+/** see Ro.h */
+const string& Ro::getRoID() const
+{
+    return mRoID;
+}
+
+/** see Ro.h */
+void Ro::setRoVersion(string& version)
+{
+    mRoVersion = version;
+}
+
+/** see Ro.h */
+void Ro::addAsset(Asset* asset)
+{
+    mAssetList.push_back(asset);
+}
+
+/** see Ro.h */
+void Ro::addRight(Right* right)
+{
+    mRightList.push_back(right);
+}
+
+/** see Ro.h */
+bool Ro::save()
+{
+     LOGI("==============Ro save.=================");
+
+     return true;
+}
+
+/** see Ro.h */
+Ro::ERRCODE Ro::parse(istringstream *roStream)
+{
+    DomExpatAgent xmlAgent(mDoc);
+
+    if (NULL == roStream)
+    {
+        LOGI("NULL stream");
+        return RO_NULL_STREAM;
+    }
+
+    if (xmlAgent.generateDocumentFromXML(roStream) == false)
+    {
+        LOGI("generate xml doc error");
+        return RO_ERR_BAD_XML;
+    }
+
+    handleDocument(mDoc);
+
+    return RO_OK;
+}
+
+/** see Ro.h */
+bool Ro::handleDocument(const XMLDocumentImpl* doc)
+{
+    assert(doc != NULL);
+
+    NodeImpl* node = doc->getDocumentElement();
+
+    return handleRights(node);
+}
+
+/** see Ro.h */
+bool Ro::handleRights(const NodeImpl *curNode)
+{
+    assert(curNode != NULL);
+
+    NodeImpl *node = curNode->getFirstChild();
+
+    while (NULL != node)
+    {
+        const DOMString* name;
+
+        name = static_cast<const XMLElementImpl*>(node)->getTagName();
+
+        if (name->compare(STR_RO_CONTEXT) == 0)
+        {
+            LOGI("rights context");
+            const DOMString *token = NULL;
+            token = static_cast<const XMLElementImpl*>(node)->getSoloText(STR_RO_CONTEXT_ID);
+
+            if (token)
+            {
+                LOGI(*token);
+                mRoID = *token;
+            }
+
+            token = static_cast<const XMLElementImpl*>(node)->getSoloText(STR_RO_CONTEXT_VERSION);
+            if (token)
+            {
+                LOGI(*token);
+                mRoVersion = *token;
+            }
+        }
+
+        if (name->compare(STR_RO_AGREEMENT) == 0)
+        {
+
+            LOGI("rights agreement");
+            if (handleAgreement(node) == false)
+            {
+                return false;
+            }
+        }
+
+        node = node->getNextSibling();
+    }
+    return true;
+}
+
+/** see Ro.h */
+bool Ro::handleAgreement(const NodeImpl *curNode)
+{
+    assert(curNode != NULL);
+
+    NodeImpl *node = curNode->getFirstChild();
+
+    while (NULL != node)
+    {
+        const DOMString* name;
+
+        name = static_cast<const XMLElementImpl*>(node)->getTagName();
+
+        if (name->compare(STR_RO_ASSET) == 0)
+        {
+            // do something about asset.
+            LOGI("asset");
+
+            if (handleAsset(node) == false)
+            {
+                return false;
+            }
+        }
+
+        if (name->compare(STR_RO_PERMISSION) == 0)
+        {
+            // do something about permission.
+            LOGI("permission");
+
+            if (handlePermission(node) == false)
+            {
+                return false;
+            }
+        }
+
+        node = node->getNextSibling();
+    }
+
+    return true;
+}
+
+/** see Ro.h */
+bool Ro::handleAsset(const NodeImpl *curNode)
+{
+    assert(curNode != NULL);
+
+    Asset *asset = new Asset();
+
+    const XMLElementImpl *curElement = static_cast<const XMLElementImpl*>(curNode);
+
+    if (curElement->hasAttributes())
+    {
+        DOMString assetID(STR_RO_ASSET_ID);
+        LOGI("asset id:");
+
+        const DOMString *id = curElement->getAttribute(&assetID);
+
+        if (id)
+        {
+            asset->setID(*id);
+        }
+
+    }
+
+    NodeImpl* node = curNode->getFirstChild();
+
+    const DOMString *name = NULL;
+    const string *token = NULL;
+
+    while (NULL != node)
+    {
+        curElement = static_cast<const XMLElementImpl*>(node);
+        name = curElement->getTagName();
+
+        if (name->compare(STR_RO_CONTEXT) == 0 ||
+            name->compare(STR_RO_INHERIT) == 0)
+        {
+            LOGI("asset context");
+
+            token = curElement->getSoloText(STR_RO_CONTEXT_ID);
+            if (token)
+            {
+                LOGI(*token);
+
+                if (name->compare(STR_RO_CONTEXT) == 0)
+                {
+                    asset->setContentID(*token);
+                }
+                else
+                {
+                    //parent ID.
+                    asset->setParentContentID(*token);
+                }
+            }
+        }
+
+        if (name->compare(STR_RO_DIGEST) == 0)
+        {
+            LOGI("asset digest");
+            //digest method is fixed value:
+            //http://www.w3.org/2000/09/xmldisig#sha1
+            token = curElement->getSoloText(STR_RO_DIGEST_VALUE);
+            if (token)
+            {
+                LOGI(*token);
+                asset->setDCFDigest(*token);
+            }
+        }
+
+        if (name->compare(STR_RO_KEYINFO) == 0)
+        {
+            LOGI("asset keyinfo");
+
+            token = curElement->getSoloText(STR_RO_CIPHER_VALUE);
+            if (token)
+            {
+                LOGI(*token);
+                asset->setEncryptedKey(*token);
+            }
+
+            const XMLElementImpl *node = curElement->getSoloElement(STR_RO_RETRIEVAL_METHOD);
+
+            if (node)
+            {
+                if (node->hasAttributes())
+                {
+                    DOMString uri("URI");
+                    token = node->getAttribute(&uri);
+                    if (token)
+                    {
+                        LOGI(*token);
+                        asset->setKeyRetrievalMethod(*token);
+                    }
+                }
+            }
+        }
+
+        node = node->getNextSibling();
+    }
+
+    this->addAsset(asset);
+    return true;
+}
+
+/** see Ro.h */
+bool Ro::handlePermission(const NodeImpl *curNode)
+{
+    assert(curNode != NULL);
+
+    Right *right = new Right();
+
+    const XMLElementImpl *curElement = static_cast<const XMLElementImpl*>(curNode);
+
+    NodeImpl* node = curNode->getFirstChild();
+
+    while (NULL != node)
+    {
+        const DOMString *name = NULL;
+        NodeListImpl *nodeList = NULL;
+
+        const string *token = NULL;
+        curElement = static_cast<const XMLElementImpl*>(node);
+        name = curElement->getTagName();
+
+        if (name->compare(STR_RO_ASSET) == 0)
+        {
+            LOGI("permission asset");
+            if (curElement->hasAttributes())
+            {
+                DOMString assetID(STR_RO_ASSET_IDREF);
+                const DOMString *id = curElement->getAttribute(&assetID);
+                if (id)
+                {
+                    right->addAssetID(*id);
+                    LOGI(*id);
+                }
+            }
+        }
+
+        OperationPermission::OPERATION type = OperationPermission::NONE;
+
+        if (name->compare(STR_RO_PLAY) == 0)
+        {
+            LOGI("permission play constraint");
+            type = OperationPermission::PLAY;
+        }
+
+        if (name->compare(STR_RO_DISPLAY) == 0)
+        {
+            LOGI("permission display costraint");
+            type = OperationPermission::DISPLAY;
+        }
+
+        if (name->compare(STR_RO_EXECUTE) == 0)
+        {
+            LOGI("permission execute constraint");
+            type = OperationPermission::EXECUTE;
+        }
+
+        if (name->compare(STR_RO_EXPORT) == 0)
+        {
+            LOGI("permission export constraint");
+            type = OperationPermission::EXPORT;
+        }
+
+        if (name->compare(STR_RO_PRINT) == 0)
+        {
+            LOGI("permission print constraint");
+            type = OperationPermission::PRINT;
+        }
+
+        Constraint *cst = NULL;
+
+        if (name->compare(STR_RO_CONSTRAINT) == 0)
+        {
+            LOGI("permission common constraint");
+            type = OperationPermission::COMMON;
+        }
+
+        cst = getConstraint(curElement);
+        if (cst)
+        {
+            OperationPermission *op = new OperationPermission(type, cst);
+            right->addOperationPermission(op);
+        }
+
+        node = node->getNextSibling();
+    }
+
+    this->addRight(right);
+    return true;
+}
+
+/** see Ro.h */
+long Ro::convertISO8601DateTimeToLong(const char* ts)
+{
+    if (NULL == ts)
+    {
+        return -1;
+    }
+
+    struct tm time;
+    memset(&time, 0, sizeof(struct tm));
+
+    strptime(ts, "%FT%T%z", &time);
+
+//need timezone support:  return mktime(&time) - timezone;
+//It seems android-sooner doesn't support timezone function.
+//line below is just for building, value would be wrong if no timezone minus.
+    return mktime(&time);
+}
+
+/** see Ro.h */
+long Ro::convertISO8601PeriodToLong(const char* ts)
+{
+    if (NULL == ts)
+    {
+        return -1;
+    }
+
+    int date, hour, min, sec;
+    sscanf(ts, "P%dDT%dH%dM%dS", &date, &hour, &min, &sec);
+    LOGI("%d %d %d %d", date, hour, min, sec);
+    return (date*24*60*60 + hour*60*60 + min*60 + sec);
+}
+
+/** see Ro.h */
+Constraint* Ro::getConstraint(const NodeImpl* curNode)
+{
+    assert(curNode != NULL);
+
+    Constraint *constraint = new Constraint();
+
+    const XMLElementImpl *curElement = static_cast<const XMLElementImpl*>(curNode);
+
+    const string *name = NULL;
+    const string *token = NULL;
+
+    if ((token = curElement->getSoloText(STR_RO_COUNT)))
+    {
+        LOGI(*token);
+        constraint->setCount(atoi(token->c_str()));
+    }
+
+    if ((token = curElement->getSoloText(STR_RO_START)))
+    {
+        LOGI(*token);
+        //start Time
+        constraint->setStartTime(convertISO8601DateTimeToLong(token->c_str()));
+    }
+
+    if ((token = curElement->getSoloText(STR_RO_END)))
+    {
+        LOGI(*token);
+        //end Time
+        constraint->setEndTime(convertISO8601DateTimeToLong(token->c_str()));
+    }
+
+    if ((token = curElement->getSoloText(STR_RO_INTERVAL)))
+    {
+        LOGI(*token);
+        constraint->setInterval(atoi(token->c_str()));
+    }
+
+    if ((token = curElement->getSoloText(STR_RO_ACCUMULATED)))
+    {
+        LOGI(*token);
+        //Period
+        constraint->setAccumulated(convertISO8601PeriodToLong(token->c_str()));
+    }
+
+    if ((token = curElement->getSoloText(STR_RO_TIMEDCOUNT)))
+    {
+        LOGI(*token);
+        constraint->setTimedCount(atoi(token->c_str()));
+
+        const XMLElementImpl *node = curElement->getSoloElement(STR_RO_TIMEDCOUNT);
+
+        if (node)
+        {
+            if (node->hasAttributes())
+            {
+                DOMString timer(STR_RO_TIMER);
+                token = node->getAttribute(&timer);
+                if (token)
+                {
+                    LOGI(*token);
+                    constraint->setTimer(atoi(token->c_str()));
+                }
+            }
+        }
+
+    }
+
+    return constraint;
+}
+
+/** see Ro.h */
+void Ro::loadRights(const string& contentID)
+{
+    for (vector<Right*>::iterator it = this->mRightList.begin();
+        it != this->mRightList.end(); it++)
+    {
+        if ((*it)->mAssetNameList.empty())
+        {
+            mContentRightList.push_back(*it);
+        }
+        else
+        {
+            for (vector<Asset*>::iterator ita = this->mAssetList.begin();
+                 ita != this->mAssetList.end(); ita++)
+            {
+                for (vector<string>::iterator its = (*it)->mAssetNameList.begin();
+                     its != (*it)->mAssetNameList.end(); its++)
+                {
+                    if ((*its).compare((*ita)->getID()) == 0)
+                    {
+                        if (contentID.compare((*ita)->getContentID()) == 0)
+                        {
+                            LOGI("find content right");
+                            mContentRightList.push_back(*it);
+                        }
+                    }
+                }
+            }
+        }
+
+
+    }
+
+}
+
+/** see Ro.h */
+void Ro::freeRights()
+{
+    mContentRightList.clear();
+}
+
+/** see Ro.h */
+bool Ro::checkPermission(OperationPermission::OPERATION type,
+                                const string& contentID)
+{
+    loadRights(contentID);
+
+    for (vector<Right*>::iterator it = mContentRightList.begin(); it != mContentRightList.end(); it++)
+     {
+        if ((*it)->checkPermission(type))
+        {
+            freeRights();
+            return true;
+        }
+
+     }
+    freeRights();
+    return false;
+}
+
+/** see Ro.h */
+Ro::ERRCODE Ro::consume(OperationPermission::OPERATION type,
+                         const string& contentID)
+{
+    loadRights(contentID);
+
+    //check in mRightList
+    vector<Right*>::iterator it;
+    vector<Right*> tmpList;
+    vector<Right*> retList;
+    Constraint *constraint = NULL;
+    long ealiestEnd = -1;
+    bool hasCommonConstraint = false;
+    bool hasUnconstraint = false;
+    bool hasDateTimeConstraint = false;
+    bool hasTimedCountConstraint = false;
+    bool hasIntervalConstraint = false;
+
+
+    //apply the RO rule, if do not satisfy the constraint, .
+    //proper right select process
+
+    for (it = mContentRightList.begin(); it != mContentRightList.end(); it++)
+    {
+        if ((*it)->checkPermission(type))
+        {
+            constraint = (*it)->getConstraint(OperationPermission::COMMON);
+            if (constraint)
+            {
+                if (!constraint->isValid(time(NULL)))
+                {
+                    continue;
+                }
+
+                hasCommonConstraint = true;
+                tmpList.push_back(*it);
+            }
+
+            constraint = (*it)->getConstraint(type);
+            assert(constraint != NULL);
+
+            if (!constraint->isValid(time(NULL)))
+            {
+                continue;
+            }
+
+            if (constraint->isUnConstraint())
+            {
+                //use uncontrainted firstly.
+                hasUnconstraint = true;
+                tmpList.push_back(*it);
+                break;
+            }
+
+            if (constraint->isDateTimeConstraint())
+            {
+                //use datetime constraint in high priority.
+                //if contain multipe constraints, use the earliest expire time.
+                hasDateTimeConstraint = true;
+                tmpList.push_back(*it);
+                continue;
+            }
+
+            if (constraint->isTimedCountConstraint())
+            {
+            //illegal Operation when time counted
+                if (type == OperationPermission::PRINT ||
+                    type == OperationPermission::EXPORT)
+                {
+                    continue;
+                }
+
+                hasTimedCountConstraint = true;
+                tmpList.push_back(*it);
+                continue;
+            }
+
+            if (constraint->isIntervalConstraint())
+            {
+                hasIntervalConstraint = true;
+                tmpList.push_back(*it);
+                continue;
+            }
+
+            tmpList.push_back(*it);
+        }
+    }
+
+
+    for (it = tmpList.begin(); it != tmpList.end(); it++)
+    {
+        if (hasUnconstraint == true)
+        {
+            //delete other constraint
+            constraint = (*it)->getConstraint(type);
+            if (constraint)
+            {
+                if (constraint->isUnConstraint())
+                {
+                    retList.push_back(*it);
+                    break;
+                }
+            }
+            continue;
+        }
+
+        if (hasDateTimeConstraint == true)
+        {
+            //delete other constraint
+            constraint = (*it)->getConstraint(type);
+            if (constraint)
+            {
+                if (constraint->isDateTimeConstraint())
+                {
+                    long tt = constraint->getEndTime();
+
+                    if (ealiestEnd == -1)
+                    {
+                        ealiestEnd = tt;
+                        retList.push_back(*it);
+                    }
+                    else if (ealiestEnd > tt)
+                    {
+                        ealiestEnd = tt;
+                        retList.pop_back();
+                        retList.push_back(*it);
+                    }
+                }
+            }
+            continue;
+        }
+
+        if (hasIntervalConstraint == true)
+        {
+            //delete other constraint
+            constraint = (*it)->getConstraint(type);
+            if (constraint)
+            {
+                if (constraint->isIntervalConstraint())
+                {
+                    retList.push_back(*it);
+                }
+            }
+            continue;
+        }
+
+        if (hasTimedCountConstraint == true)
+        {
+            constraint = (*it)->getConstraint(type);
+            if (constraint)
+            {
+                if (constraint->isTimedCountConstraint())
+                {
+                    retList.push_back(*it);
+                }
+            }
+            continue;
+        }
+
+        retList.push_back(*it);
+    }
+
+    if (retList.size() == 0)
+    {
+        freeRights();
+        return RO_BAD;
+    }
+
+    LOGI("Proper right has %d", retList.size());
+
+    assert(retList.size() == 1);
+
+    mProperRight = retList[0];
+    constraint = retList[0]->getConstraint(OperationPermission::COMMON);
+    if (constraint)
+    {
+        if (constraint->consume() == false)
+        {
+            freeRights();
+            return RO_BAD;
+        }
+    }
+
+    constraint = retList[0]->getConstraint(type);
+    if (constraint)
+    {
+        if (constraint->consume() == false)
+        {
+            freeRights();
+            return RO_BAD;
+        }
+    }
+
+    //update the constraint
+    freeRights();
+    return RO_OK;
+}
+
+/** see Ro.h */
+string Ro::getContentCek(const string& contentID)
+{
+    for (vector<Asset*>::iterator it = mAssetList.begin();
+        it != mAssetList.end(); it++)
+    {
+        if (contentID.compare((*it)->getContentID()) == 0)
+        {
+            return (*it)->getCek();
+        }
+    }
+
+    return "";
+}
+
+/** see Ro.h */
+string Ro::getContentHash(const string& contentID)
+{
+    for (vector<Asset*>::iterator it = mAssetList.begin();
+        it != mAssetList.end(); it++)
+    {
+        if (contentID.compare((*it)->getContentID()) == 0)
+        {
+            return (*it)->getDCFDigest();
+        }
+    }
+
+    return "";
+}
diff --git a/media/libdrm/mobile2/src/rights/RoManager.cpp b/media/libdrm/mobile2/src/rights/RoManager.cpp
new file mode 100644
index 0000000..848c2ba
--- /dev/null
+++ b/media/libdrm/mobile2/src/rights/RoManager.cpp
@@ -0,0 +1,129 @@
+/*
+ * 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.
+ */
+
+#include <rights/RoManager.h>
+#include <rights/Asset.h>
+
+using namespace ustl;
+
+RoManager* RoManager::msInstance = NULL;
+
+/** see RoManager.h */
+RoManager* RoManager::Instance()
+{
+    if (NULL == msInstance)
+    {
+        msInstance = new RoManager();
+    }
+
+    return msInstance;
+}
+
+/** see RoManager.h */
+RoManager::RoManager()
+{
+//load the ro list from local system.
+}
+
+/** see RoManager.h */
+RoManager::~RoManager()
+{
+    msInstance = NULL;
+
+    for (vector<Ro*>::iterator it = mRoList.begin();
+         it != mRoList.end(); it++)
+    {
+        delete (*it);
+    }
+
+    mRoList.clear();
+}
+
+/** see RoManager.h */
+Ro::ERRCODE RoManager::installRo(istringstream *roStream)
+{
+    Ro *ro = new Ro();
+
+    Ro::ERRCODE ret = ro->parse(roStream);
+
+    if (Ro::RO_OK == ret)
+    {
+        ro->save();
+
+        mRoList.push_back(ro);
+    }
+
+    return ret;
+}
+
+/** see RoManager.h */
+Ro* RoManager::getRoByContentID(const string& contentID)
+{
+    for (vector<Ro*>::iterator it = mRoList.begin();
+         it != mRoList.end(); it++)
+    {
+        for (vector<Asset*>::iterator ita = (*it)->mAssetList.begin();
+             ita != (*it)->mAssetList.end(); ita++)
+        {
+            if (contentID.compare((*ita)->getContentID()) == 0)
+            {
+                return *it;
+            }
+        }
+    }
+
+    return NULL;
+}
+
+/** see RoManager.h */
+Ro* RoManager::getRo(const string& roID)
+{
+    for (vector<Ro*>::iterator it = mRoList.begin();
+         it != mRoList.end(); it++)
+    {
+        if (roID.compare((*it)->getRoID()) == 0)
+        {
+            return (*it);
+        }
+    }
+
+    return NULL;
+}
+
+/** see RoManager.h */
+vector<Ro*> RoManager::getAllRo()
+{
+    return mRoList;
+}
+
+/** see RoManager.h */
+bool RoManager::deleteRo(const string& roID)
+{
+    return true;
+}
+
+/** see RoManager.h */
+bool RoManager::checkRoInCache(const string& roID)
+{
+    return true;
+}
+
+/** see RoManager.h */
+const string& RoManager::getDevicePrivateKey() const
+{
+    string pk;
+    return pk;
+}
diff --git a/media/libdrm/mobile2/src/roap/Registration.cpp b/media/libdrm/mobile2/src/roap/Registration.cpp
new file mode 100644
index 0000000..9d6f459
--- /dev/null
+++ b/media/libdrm/mobile2/src/roap/Registration.cpp
@@ -0,0 +1 @@
+/**/
diff --git a/media/libdrm/mobile2/src/roap/RoapMessageHandler.cpp b/media/libdrm/mobile2/src/roap/RoapMessageHandler.cpp
new file mode 100644
index 0000000..9d190ee
--- /dev/null
+++ b/media/libdrm/mobile2/src/roap/RoapMessageHandler.cpp
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+#include <roap/RoapMessageHandler.h>
+#include <util/xml/DomExpatAgent.h>
+#include <util/xml/XMLDocumentImpl.h>
+#include <util/domcore/NodeListImpl.h>
+#include <util/domcore/DOMString.h>
+#include <ofstream.h>
+using namespace ustl;
+
+/**see RoapMessageHandler.h */
+RoapMessageHandler::RoapMessageHandler()
+{
+    mDoc = NULL;
+}
+
+/**see RoapMessageHandler.h */
+XMLDocumentImpl* RoapMessageHandler::createClientMsg(RoapMessageHandler::msgType type)
+{
+    /* load template from files temporarily, FIX ME later */
+    string msgTemplate;
+    switch (type)
+    {
+        case RoapMessageHandler::DeviceHello:
+            msgTemplate.append("deviceHello.xml");
+            break;
+        case RoapMessageHandler::RegistrationRequest:
+            msgTemplate.append("deviceHello.xml");        
+            break;
+        case RoapMessageHandler::RORequest:
+            msgTemplate.append("deviceHello.xml");      
+            break;
+        default:
+            return NULL;
+    }
+    ifstream xmlStream(msgTemplate.c_str());
+    XMLDocumentImpl* xmlDoc = new XMLDocumentImpl();
+    DomExpatAgent domExpatAgent1(xmlDoc);
+    if (domExpatAgent1.generateDocumentFromXML(&xmlStream))
+    {
+        return xmlDoc;
+    }
+    else
+    {
+        delete(xmlDoc);
+        return NULL;
+    }
+}
+
diff --git a/media/libdrm/mobile2/src/util/crypto/DrmCrypto.cpp b/media/libdrm/mobile2/src/util/crypto/DrmCrypto.cpp
new file mode 100644
index 0000000..fbbefb8
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/crypto/DrmCrypto.cpp
@@ -0,0 +1,235 @@
+/*
+ * 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.
+ */
+
+#include <util/crypto/DrmCrypto.h>
+#include <ustring.h>
+
+using namespace ustl;
+
+void AesAgent::discardPaddingByte( unsigned char* decryptedBuf,unsigned long* decryptedBufLen)

+{

+    if(!decryptedBuf)

+    {
+        return;
+    }
+
+    int i;
+    unsigned long tmpLen = *decryptedBufLen;
+

+    // Check whether the last several bytes are padding or not

+    for ( i = 1; i < decryptedBuf[tmpLen - 1]; i++)
+    {

+        if (decryptedBuf[tmpLen - 1 - i] != decryptedBuf[tmpLen - 1])

+            break;

+    }
+
+    // They are padding bytes

+    if (i == decryptedBuf[tmpLen - 1])

+    {
+        *decryptedBufLen = tmpLen - i;
+    }
+

+    return;

+}
+
+int32_t AesAgent::decContent( unsigned char* iv,
+                              const unsigned char* encData,

+                              unsigned long encLen,

+                              unsigned char* decData)

+{
+    if(AES_128_CBC == mode)
+    {
+        AES_KEY key;
+        AES_set_decrypt_key(AesKey,AES_KEY_BITS,&key);
+
+        uint8_t *tmpBuf = new uint8_t[encLen];
+
+        AES_cbc_encrypt( encData,
+                         tmpBuf,
+                         encLen,
+                         &key,
+                         iv,
+                         AES_DECRYPT);
+
+        unsigned long tempLen = encLen;
+        discardPaddingByte(tmpBuf,&tempLen);
+
+        memcpy(decData, tmpBuf, tempLen);
+
+        delete []tmpBuf;
+        return encLen - tempLen;
+    }
+    else
+    {
+        return AES_DEC_FAILED;
+    }
+}
+
+void Sha1Agent::computeHash( const unsigned char* inData,

+                             unsigned long inLen,

+                             unsigned char* outHash) const

+{
+    EVP_Digest(inData,inLen,outHash,NULL,EVP_sha1(),NULL);
+    return;
+}
+
+void HmacSha1Agent::computeMac( const unsigned char* inData,

+                                unsigned long inLen,

+                                unsigned char* outData) const

+{
+    HMAC(EVP_sha1(),macKey,keyLen,inData,inLen,outData,NULL);
+    return;
+}
+
+bool RsaAgent::signature( const unsigned char* rawData,

+                          unsigned long rawLen,

+                          unsigned char* sigData,
+                          RsaAlg sigAlg)

+{
+    switch(sigAlg)
+    {
+        case RSA_PSS:
+            {
+                unsigned char mHash[SHA_DIGEST_LENGTH];
+                Sha1Agent sha1;
+                sha1.computeHash(rawData,rawLen,mHash);
+
+                unsigned char EM[rsaSize];
+                if( 0 == RSA_padding_add_PKCS1_PSS( &rsaKey,
+                                                    EM,
+                                                    mHash,
+                                                    EVP_sha1(),
+                                                    SHA_DIGEST_LENGTH))
+                {
+                    return false;
+                }
+
+                if(0 > RSA_private_encrypt( SHA_DIGEST_LENGTH,
+                                            EM,
+                                            sigData,
+                                            &rsaKey,
+                                            RSA_PKCS1_PADDING))
+                {
+                    return false;
+                }
+                else
+                {
+                    return true;

+                }
+            }
+            break;
+        case RSA_SHA1:
+            {
+                unsigned char mHash[SHA_DIGEST_LENGTH];
+                Sha1Agent sha1;
+                sha1.computeHash(rawData,rawLen,mHash);
+
+                if(0 != RSA_sign( NID_sha1WithRSA,
+                                  mHash,
+                                  SHA_DIGEST_LENGTH,
+                                  sigData,
+                                  &rsaSize,
+                                  &rsaKey))
+                {
+                    return true;
+                }
+                else
+                {
+                    return false;
+                }
+            }
+           break;
+        default:
+            return false;
+    }
+
+    return false;
+}
+
+bool RsaAgent::sigVerify( unsigned char* sigData,
+                          unsigned long sigLen,
+                          const unsigned char* rawData,
+                          unsigned long rawLen,
+                          RsaAlg sigAlg)

+{
+    if( sigAlg == RSA_PSS)
+    {
+        unsigned char decSigData[rsaSize];
+
+        if(0 > RSA_public_decrypt(sigLen,
+                                  sigData,
+                                  decSigData,
+                                  &rsaKey,
+                                  RSA_PKCS1_PADDING))

+        {
+            return false;
+        }
+        else
+        {
+            unsigned char mHash[SHA_DIGEST_LENGTH];
+            Sha1Agent sha1;
+            sha1.computeHash(rawData,rawLen,mHash);
+
+            if( 0 == RSA_verify_PKCS1_PSS( &rsaKey,
+                                           mHash,
+                                           EVP_sha1(),
+                                           decSigData,
+                                           -1))
+            {
+                return true;
+            }
+            else
+            {
+                return false;
+            }
+        }
+    }
+    else if(sigAlg == RSA_SHA1)
+    {
+        unsigned char mHash[SHA_DIGEST_LENGTH];
+        Sha1Agent sha1;
+        sha1.computeHash(rawData,rawLen,mHash);
+
+        if(0 != RSA_verify( NID_sha1WithRSA,
+                            mHash,
+                            SHA_DIGEST_LENGTH,
+                            sigData,
+                            sigLen,
+                            &rsaKey))
+        {
+            return true;
+        }
+        else
+        {
+            return false;
+        }
+    }
+    else
+    {
+        return false;
+    }
+}
+
+int RsaAgent::decrypt( const unsigned char* encData,
+                       unsigned long encLen,
+                       unsigned char* decData)

+{
+    return RSA_private_decrypt( encLen,
+                                encData,
+                                decData,
+                                &rsaKey,
+                                RSA_PKCS1_PADDING);
+}
diff --git a/media/libdrm/mobile2/src/util/domcore/CharacterDataImpl.cpp b/media/libdrm/mobile2/src/util/domcore/CharacterDataImpl.cpp
new file mode 100644
index 0000000..0fe699a
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/domcore/CharacterDataImpl.cpp
@@ -0,0 +1,83 @@
+/*
+ * 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.
+ */
+#include <util/domcore/CharacterDataImpl.h>

+

+/** see CharacterDataImpl.h */

+const DOMString* CharacterDataImpl::getData() const throw (DOMException)

+{

+    return charData;

+}

+

+/** see CharacterDataImpl.h */

+CharacterDataImpl::CharacterDataImpl():charData(NULL)

+{

+}

+

+/** see CharacterDataImpl.h*/

+CharacterDataImpl::CharacterDataImpl(const DOMString* data):charData(NULL)

+{

+    if (data != NULL)

+        charData = new DOMString(*data);

+}

+

+/** see CharacterDataImpl.h */

+void CharacterDataImpl::setData(const DOMString* data) throw (DOMException)

+{

+

+    if (charData != NULL)

+        delete charData;

+

+    if (data == NULL)

+        charData = NULL;

+    else

+        charData = new DOMString(*data);

+}

+

+/** see CharacterDataImpl.h */

+int CharacterDataImpl::getLength() const

+{

+    return charData != NULL ? charData->length() : 0;

+}

+

+/** see CharacterDataImpl.h */

+void CharacterDataImpl::appendData(const DOMString* arg) throw(DOMException)

+{

+    if (arg != NULL) {

+        if (charData != NULL)

+            charData->append(*arg);

+        else

+            charData = new DOMString(*arg);

+    }

+}

+

+/** see CharacterDataImpl.h */

+const DOMString* CharacterDataImpl::getNodeValue() const throw(DOMException)

+{

+    return getData();

+}

+

+/** see CharacterDataImpl.h */

+void CharacterDataImpl::setNodeValue(DOMString* nodeValue) throw(DOMException)

+{

+    setData(nodeValue);

+}

+

+/** see CharacterDataImpl.h */

+CharacterDataImpl::~CharacterDataImpl()

+{

+    delete charData;

+}

+

diff --git a/media/libdrm/mobile2/src/util/domcore/DOMException.cpp b/media/libdrm/mobile2/src/util/domcore/DOMException.cpp
new file mode 100644
index 0000000..da9d3ce
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/domcore/DOMException.cpp
@@ -0,0 +1,15 @@
+/*
+ * 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.
+ */

diff --git a/media/libdrm/mobile2/src/util/domcore/DocumentImpl.cpp b/media/libdrm/mobile2/src/util/domcore/DocumentImpl.cpp
new file mode 100644
index 0000000..ebf46fb
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/domcore/DocumentImpl.cpp
Binary files differ
diff --git a/media/libdrm/mobile2/src/util/domcore/ElementImpl.cpp b/media/libdrm/mobile2/src/util/domcore/ElementImpl.cpp
new file mode 100644
index 0000000..df48831
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/domcore/ElementImpl.cpp
@@ -0,0 +1,98 @@
+/*
+ * 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.
+ */
+#include <util/domcore/ElementImpl.h>

+

+/** see ElementImpl.h */

+NodeType ElementImpl::getNodeType() const

+{

+    return ELEMENT_NODE;

+}

+

+/** see ElementImpl.h */

+const DOMString* ElementImpl::getNodeName() const

+{

+    return getTagName();

+}

+

+/** see ElementImpl.h */

+const DOMString* ElementImpl::getTagName() const

+{

+    return NULL;

+}

+

+/** see ElementImpl.h */

+void ElementImpl::setAttribute(const DOMString* name, const DOMString* value) throw (DOMException)

+{

+

+}

+

+/** see ElementImpl.h */

+void ElementImpl::removeAttribute(const DOMString* name) throw (DOMException)

+{

+

+}

+

+/** see ElementImpl.h */

+const DOMString* ElementImpl::getAttribute(const DOMString* name) const

+{

+    return NULL;

+}

+

+/** see ElementImpl.h */

+void ElementImpl::getElementsByTagName(const DOMString* name, NodeListImpl* nodeList) const

+{

+    NodeImpl* node = getFirstChild();

+

+    if (node == NULL || name == NULL || nodeList == NULL)

+        return;

+

+    do {

+

+        if (node->getNodeType() == ELEMENT_NODE) {

+            ElementImpl* elementNode = static_cast<ElementImpl*>(node);

+            if (*elementNode->getTagName() == *name)

+               /* if current is element node and tag name is equal to <code>name</code>,put it into nodeList */

+                nodeList->append(node);

+               /*

+                * visit DOM tree recursively,

+                * get all Elements node whose tage name is equal to name.

+                */

+               elementNode->getElementsByTagName(name, nodeList);

+        }

+

+        /* set current node's next sibling node as current node.*/

+        node = node->getNextSibling();

+    } while(node != NULL);

+}

+

+/** see ElementImpl.h */

+NodeListImpl* ElementImpl::getElementsByTagName(const DOMString* name) const

+{

+    NodeListImpl* nodeList = new NodeListImpl();

+

+    if (nodeList == NULL || name == NULL)

+        return NULL;

+

+    getElementsByTagName(name,nodeList);

+

+    return nodeList;

+}

+

+/** see ElementImpl.h */

+bool ElementImpl::hasAttributes() const

+{

+    return false;

+}

diff --git a/media/libdrm/mobile2/src/util/domcore/NodeImpl.cpp b/media/libdrm/mobile2/src/util/domcore/NodeImpl.cpp
new file mode 100644
index 0000000..183c55e
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/domcore/NodeImpl.cpp
@@ -0,0 +1,239 @@
+/*
+ * 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.
+ */
+#include <util/domcore/NodeImpl.h>

+#include <util/domcore/DocumentImpl.h>

+

+/** see NodeImpl.h. */

+void NodeImpl::setParent(NodeImpl* parentNode)

+{

+    this->parent = parentNode;

+}

+

+/** see NodeImpl.h. */

+void NodeImpl::setNextSibling(NodeImpl* siblingNode)

+{

+    this->nextSibling = siblingNode;

+}

+/** see NodeImpl.h. */

+void NodeImpl::setPreviousSibling(NodeImpl* siblingNode)

+{

+    this->previousSibling = siblingNode;

+}

+

+/** see NodeImpl.h. */

+void NodeImpl::setFirstChild(NodeImpl* childNode)

+{

+    this->firstChild = childNode;

+}

+

+/** see NodeImpl.h. */

+void NodeImpl::setLastChild(NodeImpl* childNode)

+{

+    this->lastChild = childNode;

+}

+

+/** see NodeImpl.h. */

+NodeImpl* NodeImpl::getParentNode() const

+{

+    return parent;

+}

+

+/** see NodeImpl.h. */

+NodeImpl* NodeImpl::getFirstChild() const

+{

+    return firstChild;

+}

+

+/** see NodeImpl.h. */

+NodeImpl* NodeImpl::getLastChild() const

+{

+    return lastChild;

+}

+

+/** see NodeImpl.h. */

+NodeImpl* NodeImpl::getPreviousSibling() const

+{

+    return previousSibling;

+}

+

+/** see NodeImpl.h. */

+NodeImpl* NodeImpl::getNextSibling() const

+{

+    return nextSibling;

+}

+

+/** see NodeImpl.h. */

+NodeImpl* NodeImpl::insertBefore(NodeImpl* newChild, NodeImpl* refChild) throw (DOMException)

+{

+    if (newChild == NULL)
+        #if PLATFORM_ANDROID
+            return NULL;
+        #else

+            throw DOMException(DOMException::WRONG_DOCUMENT_ERR);

+        #endif

+    if (refChild == NULL || refChild->getParentNode() != this)
+        #if PLATFORM_ANDROID
+            return NULL;
+        #else

+            throw DOMException(DOMException::NOT_FOUND_ERR);
+        #endif

+

+    NodeImpl* parentNode = newChild->getParentNode();

+

+    if (parentNode != NULL)

+        parentNode->removeChild(newChild);

+

+    NodeImpl* prevSiblingNode = refChild->getPreviousSibling();

+

+    if (prevSiblingNode != NULL)

+        prevSiblingNode->appendNextSibling(newChild);

+    else

+        setFirstChild(newChild);

+

+    newChild->appendNextSibling(refChild);

+    newChild->setParent(this);

+

+    return newChild;

+}

+

+/** see NodeImpl.h. */

+NodeImpl* NodeImpl::removeChild(NodeImpl* oldChild) throw (DOMException)

+{

+

+    if (oldChild == NULL || oldChild->getParentNode() != this )
+    #if PLATFORM_ANDROID
+        return NULL;
+    #else
+        throw DOMException(DOMException::NOT_FOUND_ERR);
+    #endif

+

+    NodeImpl* parentNode = oldChild->getParentNode();

+    NodeImpl* nextSiblingNode = oldChild->getNextSibling();

+    NodeImpl* prevSiblingNode = oldChild->getPreviousSibling();

+

+    if (prevSiblingNode == NULL && nextSiblingNode != NULL) {

+        /*

+         * children's previous sibling node == NULL and next sibling node !=

+         * NULL, means the children node is the first node of its parent.

+         * so set the children's next sibling node as the first node of its parent.

+         */

+        parentNode->setFirstChild(nextSiblingNode);

+        nextSiblingNode->setPreviousSibling(NULL);

+

+    } else if (prevSiblingNode != NULL && nextSiblingNode == NULL) {

+        /*

+         * children's previous sibling node != NULL and next sibling node ==

+         * NULL, means the child node is the last node of parent.so set the

+         * last node of children's parent as children's previous sibling node.

+         */

+        prevSiblingNode->setNextSibling(NULL);

+        parentNode->setLastChild(prevSiblingNode);

+

+    } else if (prevSiblingNode != NULL && nextSiblingNode != NULL) {

+        /*

+         * children's previous sibling node != NULL and next sibling node !=

+         * NULL,means the node is neither first child nor last children of its parent.

+         */

+        prevSiblingNode->appendNextSibling(nextSiblingNode);

+

+    } else if (prevSiblingNode == NULL && nextSiblingNode == NULL) {

+        /*

+         * this means it's only one children node of its parent.

+         * so adjust the first child and last child to NULL when remove the children node.

+         */

+        this->setFirstChild(NULL);

+        this->setLastChild(NULL);

+    }

+

+    oldChild->setParent(NULL);

+    oldChild->setNextSibling(NULL);

+    oldChild->setPreviousSibling(NULL);

+

+    return oldChild;

+}

+

+/** see NodeImpl.h. */

+void NodeImpl::appendNextSibling(NodeImpl* node)

+{

+    if (node == NULL)

+        return;

+

+    setNextSibling(node);

+    node->setPreviousSibling(this);

+}

+

+/** see NodeImpl.h. */

+NodeImpl* NodeImpl::appendChild(NodeImpl* newChild) throw (DOMException)

+{

+    if (newChild == NULL)
+        #if PLATFORM_ANDROID
+            return NULL;
+        #else

+            throw DOMException(DOMException::WRONG_DOCUMENT_ERR);

+        #endif

+    /* If newChild have parent,remove it from its parent at first.*/

+    NodeImpl* parent = newChild->getParentNode();

+    if (parent != NULL)

+        parent->removeChild(newChild);

+

+    if (getFirstChild() == NULL && getLastChild() == NULL) {

+        /* There are not any nodes in current node.*/

+        setFirstChild(newChild);

+    } else if (getLastChild() != NULL) {

+        getLastChild()->appendNextSibling(newChild);

+    }

+

+    newChild->setParent(this);

+    setLastChild(newChild);

+

+

+    return newChild;

+}

+

+/** see NodeImpl.h. */

+bool NodeImpl::hasChildNodes() const

+{

+    return getFirstChild() != NULL;

+}

+

+/** see NodeImpl.h. */

+const DOMString* NodeImpl::getNodeValue() const throw (DOMException)

+{

+    return NULL;

+}

+

+/** see NodeImpl.h. */

+void NodeImpl::setNodeValue(DOMString* nodeValue) throw (DOMException)

+{

+}

+

+/** see NodeImpl.h. */

+bool NodeImpl::hasAttributes() const

+{

+    return false;

+}

+

+/** see NodeImpl.h */

+const DocumentImpl* NodeImpl::getDocument() const

+{

+    return document;

+}

+

+/** see NodeImpl.h */

+void NodeImpl::setDocument(const DocumentImpl* document)

+{

+    this->document = document;

+}

diff --git a/media/libdrm/mobile2/src/util/domcore/NodeIterator.cpp b/media/libdrm/mobile2/src/util/domcore/NodeIterator.cpp
new file mode 100644
index 0000000..f076cda
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/domcore/NodeIterator.cpp
@@ -0,0 +1,101 @@
+/*
+ * 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.
+ */
+#include <util/domcore/NodeImpl.h>

+#include <util/domcore/NodeIterator.h>

+

+/** see NodeIterator.h */

+NodeIterator::NodeIterator(NodeImpl* start,NodeImpl* scope,NodeImpl* end): scopeNode(scope),endNode(end),curNode(start)

+{

+}

+

+/** see NodeIterator.h */

+NodeImpl* NodeIterator::findNextOrderNode(NodeImpl* node)

+{

+    if (node == endNode)

+        return NULL;

+

+    if (node != NULL) {

+        if (node->hasChildNodes() == true) {

+            node = node->getFirstChild();

+        }else if (node == scopeNode && node->hasChildNodes() == false) {

+            node = NULL;

+        } else if (node->getNextSibling() != NULL) {

+            node = node->getNextSibling();

+        } else {

+            while (node != scopeNode && node != NULL && node->getNextSibling() == NULL) {

+                node = node->getParentNode();

+            }

+            if (node == scopeNode)

+                node = NULL;

+            if (node != NULL)

+                node = node->getNextSibling();

+        }

+    }

+    if (node == endNode || node == scopeNode)

+        node = NULL;

+

+    return node;

+}

+

+/** see NodeIterator.h */

+NodeImpl* NodeIterator::next()

+{

+    NodeImpl* node = NULL;

+

+    node = findNextOrderNode(curNode);

+

+    if (node != NULL)

+        curNode = node;

+

+    return node;

+}

+

+/** see NodeIterator.h */

+NodeImpl* NodeIterator::prev()

+{

+    NodeImpl* node;

+

+    node = findPreviousOrderNode(curNode);

+

+    if (node != NULL)

+        curNode = node;

+

+    return node;

+}

+

+/** see NodeIterator.h */

+NodeImpl* NodeIterator::findPreviousOrderNode(NodeImpl* node)

+{

+    if (node == NULL || node == endNode)

+        return NULL;

+

+    if (node->getPreviousSibling() != NULL) {

+        node = node->getPreviousSibling();

+        while(node != NULL && node->hasChildNodes() == true)

+            node = node->getLastChild();

+    } else {

+        if (node == scopeNode)

+            node == NULL;

+        else

+            node = node->getParentNode();

+    }

+

+    if (node == scopeNode || node == endNode)

+        return NULL;

+

+    return node;

+}

+

diff --git a/media/libdrm/mobile2/src/util/domcore/NodeListImpl.cpp b/media/libdrm/mobile2/src/util/domcore/NodeListImpl.cpp
new file mode 100644
index 0000000..710d62d
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/domcore/NodeListImpl.cpp
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+#include <util/domcore/NodeListImpl.h>

+

+/** see NodeListImpl.h*/

+void NodeListImpl::append(const NodeImpl* newNode)

+{

+    if (newNode == NULL)

+        return;

+

+    nodeList.push_back(newNode);

+}

+

+/** see NodeListImpl.h*/

+const NodeImpl* NodeListImpl::item(int index) const

+{

+    int size = nodeList.size();

+

+    if (size == 0 || index > size - 1 || index < 0)

+        return NULL;

+

+    return nodeList.at(index);

+}

+

+/** see NodeListImpl.h*/

+int NodeListImpl::getLength() const

+{

+    return nodeList.size();

+}

+

+/** see NodeListImpl.h*/

+NodeListImpl::~NodeListImpl()

+{

+    nodeList.clear();

+}

diff --git a/media/libdrm/mobile2/src/util/domcore/TextImpl.cpp b/media/libdrm/mobile2/src/util/domcore/TextImpl.cpp
new file mode 100644
index 0000000..5e421d5
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/domcore/TextImpl.cpp
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+#include <util/domcore/TextImpl.h>

+

+const DOMString TextImpl::nodeName = "#TEXT";

+

+/** see TextImpl.h */

+TextImpl::TextImpl()

+{

+}

+

+/** see TextImpl.h */

+TextImpl::TextImpl(const DOMString* data):CharacterDataImpl(data)

+{

+}

+

+/** see TextImpl.h */

+NodeType TextImpl::getNodeType() const

+{

+    return TEXT_NODE;

+}

+

+/** see TextImpl.h */

+const DOMString* TextImpl::getNodeName() const

+{

+    return &nodeName;

+}

+

diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/bktrace.cpp b/media/libdrm/mobile2/src/util/ustl-1.0/bktrace.cpp
new file mode 100644
index 0000000..ae66463
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/ustl-1.0/bktrace.cpp
@@ -0,0 +1,160 @@
+// This file is part of the ustl library, an STL implementation.
+//
+// Copyright (C) 2006 by Mike Sharov <msharov@users.sourceforge.net>
+// This file is free software, distributed under the MIT License.
+//
+// bktrace.cc
+//
+
+#include "bktrace.h"
+#include "sostream.h"
+#include "mistream.h"
+#include "uassert.h"
+#if linux && __GNUC__ && !defined(HAVE_ANDROID_OS)
+    #include <execinfo.h>
+#else
+    static inline int backtrace (void**, int)			{ return (0); }
+    static inline char** backtrace_symbols (void* const*, int)	{ return (NULL); }
+#endif
+#if __GNUC__ >= 3 && !PLATFORM_ANDROID
+    #include <cxxabi.h>
+#endif
+
+namespace ustl {
+
+/// Default constructor. The backtrace is obtained here.
+CBacktrace::CBacktrace (void)
+: m_Symbols (NULL),
+  m_nFrames (0),
+  m_SymbolsSize (0)
+{
+#if !PLATFORM_ANDROID
+    try {
+#endif
+	m_nFrames = backtrace (VectorBlock (m_Addresses));
+	GetSymbols();
+#if !PLATFORM_ANDROID
+    } catch (...) {}
+#endif
+}
+
+/// Copy constructor.
+CBacktrace::CBacktrace (const CBacktrace& v)
+: m_Symbols (NULL),
+  m_nFrames (0),
+  m_SymbolsSize (0)
+{
+    operator= (v);
+}
+
+/// Copy operator.
+const CBacktrace& CBacktrace::operator= (const CBacktrace& v)
+{
+    memcpy (m_Addresses, v.m_Addresses, sizeof(m_Addresses));
+    m_Symbols = strdup (v.m_Symbols);
+    m_nFrames = v.m_nFrames;
+    m_SymbolsSize = v.m_SymbolsSize;
+    return (*this);
+}
+
+/// Converts a string returned by backtrace_symbols into readable form.
+static size_t ExtractAbiName (const char* isym, char* nmbuf)
+{
+    // Prepare the demangled name, if possible
+    size_t nmSize = 0;
+    if (isym) {
+	// Copy out the name; the strings are: "file(function+0x42) [0xAddress]"
+	const char* mnStart = strchr (isym, '(');
+	if (++mnStart == (const char*)(1))
+	    mnStart = isym;
+	const char* mnEnd = strchr (isym, '+');
+	const char* isymEnd = isym + strlen (isym);
+	if (!mnEnd)
+	    mnEnd = isymEnd;
+	nmSize = min (size_t (distance (mnStart, mnEnd)), 256U);
+	memcpy (nmbuf, mnStart, nmSize);
+    }
+    nmbuf[nmSize] = 0;
+    // Demangle
+    demangle_type_name (nmbuf, 256U, &nmSize);
+    return (nmSize);
+}
+
+/// Tries to get symbol information for the addresses.
+void CBacktrace::GetSymbols (void)
+{
+    auto_ptr<char*> symbols (backtrace_symbols (m_Addresses, m_nFrames));
+    if (!symbols.get())
+	return;
+    char nmbuf [256];
+    size_t symSize = 1;
+    for (uoff_t i = 0; i < m_nFrames; ++ i)
+	symSize += ExtractAbiName (symbols.get()[i], nmbuf) + 1;
+    if (!(m_Symbols = (char*) calloc (symSize, 1)))
+	return;
+    for (uoff_t i = 0; m_SymbolsSize < symSize - 1; ++ i) {
+	size_t sz = ExtractAbiName (symbols.get()[i], nmbuf);
+	memcpy (m_Symbols + m_SymbolsSize, nmbuf, sz);
+	m_SymbolsSize += sz + 1;
+	m_Symbols [m_SymbolsSize - 1] = '\n';
+    }
+}
+
+/// Default destructor.
+CBacktrace::~CBacktrace (void)
+{
+    free_nullok (m_Symbols);
+}
+
+#if SIZE_OF_LONG == 8
+    #define ADDRESS_FMT	"%16p  "
+#else
+    #define ADDRESS_FMT	"%8p  "
+#endif
+
+/// Prints the backtrace to \p os.
+void CBacktrace::text_write (ostringstream& os) const
+{
+    const char *ss = m_Symbols, *se;
+    for (uoff_t i = 0; i < m_nFrames; ++ i) {
+	os.format (ADDRESS_FMT, m_Addresses[i]);
+	se = strchr (ss, '\n') + 1;
+	os.write (ss, distance (ss, se));
+	ss = se;
+    }
+}
+
+/// Reads the object from stream \p is.
+void CBacktrace::read (istream& is)
+{
+    assert (is.aligned (alignof (m_Addresses[0])) && "Backtrace object contains pointers and must be void* aligned");
+    is >> m_nFrames >> m_SymbolsSize;
+    free_nullok (m_Symbols);
+    m_Symbols = (char*) malloc (m_SymbolsSize + 1);
+    is.read (m_Symbols, m_SymbolsSize);
+    m_Symbols [m_SymbolsSize] = 0;
+    is.align();
+    is.read (m_Addresses, m_nFrames * sizeof(void*));
+}
+
+/// Writes the object to stream \p os.
+void CBacktrace::write (ostream& os) const
+{
+    assert (os.aligned (alignof (m_Addresses[0])) && "Backtrace object contains pointers and must be void* aligned");
+    os << m_nFrames << m_SymbolsSize;
+    os.write (m_Symbols, m_SymbolsSize);
+    os.align();
+    os.write (m_Addresses, m_nFrames * sizeof(void*));
+}
+
+/// Returns the size of the written object.
+size_t CBacktrace::stream_size (void) const
+{
+    return (Align (stream_size_of (m_nFrames) +
+		   stream_size_of (m_SymbolsSize) +
+		   m_nFrames * sizeof(void*) +
+		   m_SymbolsSize));
+}
+
+} // namespace ustl
+
diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/bktrace.h b/media/libdrm/mobile2/src/util/ustl-1.0/bktrace.h
new file mode 100644
index 0000000..7b8c0ea
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/ustl-1.0/bktrace.h
@@ -0,0 +1,55 @@
+// This file is part of the ustl library, an STL implementation.
+//
+// Copyright (C) 2006 by Mike Sharov <msharov@users.sourceforge.net>
+// This file is free software, distributed under the MIT License.
+//
+// bktrace.h
+//
+
+#ifndef BKTRACE_H_63ABB1E4388CEDD975DBE58B57DE474F
+#define BKTRACE_H_63ABB1E4388CEDD975DBE58B57DE474F
+
+#include "ulimits.h"
+
+namespace ustl {
+
+class ostringstream;
+class istream;
+class ostream;
+
+/// \class CBacktrace bktrace.h ustl.h
+///
+/// \brief Stores the backtrace from the point of construction.
+///
+/// The backtrace, or callstack, is the listing of functions called to
+/// reach the construction of this object. This is useful for debugging,
+/// to print the location of an error. To get meaningful output you'll
+/// need to use a debug build with symbols and with frame pointers. For
+/// GNU ld you will also need to link with the -rdynamic option to see
+/// actual function names instead of __gxx_personality0+0xF4800.
+///
+class CBacktrace {
+public:
+			CBacktrace (void);
+			CBacktrace (const CBacktrace& v);
+		       ~CBacktrace (void);
+    const CBacktrace&	operator= (const CBacktrace& v);
+    void		text_write (ostringstream& os) const;
+    void		read (istream& is);
+    void		write (ostream& os) const;
+    size_t		stream_size (void) const;
+private:
+    void		GetSymbols (void);
+private:
+    void*		m_Addresses [64];	///< Addresses of each function on the stack.
+    char*		m_Symbols;		///< Symbols corresponding to each address.
+    uint32_t		m_nFrames;		///< Number of addresses in m_Addresses.
+    uint32_t		m_SymbolsSize;		///< Size of m_Symbols.
+};
+
+} // namespace ustl
+
+ALIGNOF(ustl::CBacktrace, sizeof(void*))
+
+#endif
+
diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/bsconf.h b/media/libdrm/mobile2/src/util/ustl-1.0/bsconf.h
new file mode 100644
index 0000000..79b4af1
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/ustl-1.0/bsconf.h
@@ -0,0 +1,173 @@
+/* This file is part of bsconf - a configure replacement.
+ *
+ * This is the configuration file used by bsconf.c to specify information
+ * specific to your project that it needs to substitute into files listed
+ * in g_Files. Being a configuration file, this file can be used or
+ * modified entirely without restriction. You should change all values
+ * appropriately to the name of your project and its requirements. The
+ * bsconf license does not apply to this file. It can and should be
+ * treated as a template for the creation of your own configuration file.
+ *
+ * All substituted variable names are given without enclosing @@. For
+ * example: "CC" will match "@CC@" in config.h.in and replace it with
+ * "gcc" in config.h.
+*/
+
+#include "uassert.h"
+
+#define BSCONF_VERSION		0x03
+
+#define PACKAGE_NAME		"ustl"
+#define LIB_MAJOR		"1"
+#define LIB_MINOR		"0"
+#define LIB_BUILD		"0"
+
+#define PACKAGE_VERSION		LIB_MAJOR "." LIB_MINOR
+#define PACKAGE_TARNAME		PACKAGE_NAME
+#define PACKAGE_STRING		PACKAGE_NAME " " PACKAGE_VERSION
+#define PACKAGE_BUGREPORT	"Mike Sharov <msharov@users.sourceforge.net>"
+
+static cpchar_t g_Files [] = {
+    "Config.mk",
+    "config.h",
+    "ustl.spec"
+};
+
+/* Values substitute @VARNAME@ */
+static cpchar_t g_EnvVars [] = {
+    "CC",
+    "LD",
+    "CXX",
+    "CPP",
+    "HOME",
+    "CXXFLAGS",
+    "LDFLAGS",
+    "CPPFLAGS",
+    "LDFLAGS",
+    "CFLAGS"
+};
+
+/*  VARIABLE	PROGRAM		HOW TO CALL	IF NOT FOUND */
+static cpchar_t g_ProgVars [] = {
+    "CC",	"gcc",		"gcc",		"@CC@",
+    "CC",	"cc",		"cc",		"gcc",
+    "CXX",	"g++",		"g++",		"@CXX@",
+    "CXX",	"c++",		"c++",		"g++",
+    "LD",	"ld",		"ld",		"ld",
+    "AR",	"ar",		"ar",		"echo",
+    "RANLIB",	"ranlib",	"ranlib",	"touch",
+    "DOXYGEN",	"doxygen",	"doxygen",	"echo",
+    "INSTALL",	"install",	"install -c",	"cp"
+};
+
+/*   NAME               IF NOT FOUND                    IF FOUND */
+static cpchar_t	g_Headers [] = {
+    "assert.h",		"#undef HAVE_ASSERT_H",		"#define HAVE_ASSERT_H 1",
+    "ctype.h",		"#undef HAVE_CTYPE_H",		"#define HAVE_CTYPE_H 1",
+    "errno.h",		"#undef HAVE_ERRNO_H",		"#define HAVE_ERRNO_H 1",
+    "fcntl.h",		"#undef HAVE_FCNTL_H",		"#define HAVE_FCNTL_H 1",
+    "float.h",		"#undef HAVE_FLOAT_H",		"#define HAVE_FLOAT_H 1",
+    "inttypes.h",	"#undef HAVE_INTTYPES_H",	"#define HAVE_INTTYPES_H 1",
+    "limits.h",		"#undef HAVE_LIMITS_H",		"#define HAVE_LIMITS_H 1",
+    "locale.h",		"#undef HAVE_LOCALE_H",		"#define HAVE_LOCALE_H 1",
+    "malloc.h",		"#undef HAVE_MALLOC_H",		"#define HAVE_MALLOC_H 1",
+    "alloca.h",		"#undef HAVE_ALLOCA_H",		"#define HAVE_ALLOCA_H 1",
+    "memory.h",		"#undef HAVE_MEMORY_H",		"#define HAVE_MEMORY_H 1",
+    "signal.h",		"#undef HAVE_SIGNAL_H",		"#define HAVE_SIGNAL_H 1",
+    "stdarg.h",		"#undef HAVE_STDARG_H",		"#define HAVE_STDARG_H 1",
+    "stddef.h",		"#undef HAVE_STDDEF_H",		"#define HAVE_STDDEF_H 1",
+    "stdint.h",		"#undef HAVE_STDINT_H",		"#define HAVE_STDINT_H 1",
+    "stdio.h",		"#undef HAVE_STDIO_H",		"#define HAVE_STDIO_H 1",
+    "stdlib.h",		"#undef HAVE_STDLIB_H",		"#define HAVE_STDLIB_H 1",
+    "string.h",		"#undef HAVE_STRING_H",		"#define HAVE_STRING_H 1",
+    "strings.h",	"#undef HAVE_STRINGS_H",	"#define HAVE_STRINGS_H 1",
+    "sys/stat.h",	"#undef HAVE_SYS_STAT_H",	"#define HAVE_SYS_STAT_H 1",
+    "sys/types.h",	"#undef HAVE_SYS_TYPES_H",	"#define HAVE_SYS_TYPES_H 1",
+    "sys/wait.h",	"#undef HAVE_SYS_WAIT_H",	"#define HAVE_SYS_WAIT_H 1",
+    "time.h",		"#undef HAVE_TIME_H",		"#define HAVE_TIME_H 1",
+    "unistd.h",		"#undef HAVE_UNISTD_H",		"#define HAVE_UNISTD_H 1",
+    "math.h",		"#undef HAVE_MATH_H",		"#define HAVE_MATH_H 1",
+    "stdlib.h",		"#undef HAVE_STDLIB_H",		"#define HAVE_STDLIB_H 1"
+};
+
+/*   NAME               IF NOT FOUND                    IF FOUND */
+static cpchar_t g_Libs [] = {
+    "supc++",		"",				"-lsupc++",
+#if __GNUC__ >= 4
+    "gcc",		"-lgcc_s",			"-lgcc_s",
+    "gcc_eh",		"",				"",
+#elif __GNUC__ >= 3
+    "gcc",		"-lgcc_s",			"-lgcc",
+    "gcc_eh",		"-lgcc_s",			"-lgcc_eh",
+#else
+    "gcc",		"",				"-lgcc",
+    "gcc_eh",		"",				"",
+#endif
+    "SystemStubs",	"",				"-lSystemStubs", /* For MacOS 10.4+ */
+    "c",		"",				"-lc"
+};
+
+/*   NAME               IF NOT FOUND                    IF FOUND */
+static cpchar_t g_Functions [] = {
+    "atexit",		"#undef HAVE_ATEXIT",		"#define HAVE_ATEXIT 1",
+    "malloc",		"#undef HAVE_MALLOC\n",		"#define HAVE_MALLOC 1\n",
+    "memchr",		"#undef HAVE_MEMCHR",		"#define HAVE_MEMCHR 1",
+    "memmove",		"#undef HAVE_MEMMOVE",		"#define HAVE_MEMMOVE 1",
+    "memset",		"#undef HAVE_MEMSET",		"#define HAVE_MEMSET 1",
+    "ptrdiff_t",	"#undef HAVE_PTRDIFF_T",	"#define HAVE_PTRDIFF_T 1",
+    "strerror",		"#undef HAVE_STRERROR",		"#define HAVE_STRERROR 1",
+    "strsignal",	"#undef HAVE_STRSIGNAL",	"#define HAVE_STRSIGNAL 1",
+    "strtol",		"#undef HAVE_STRTOL",		"#define HAVE_STRTOL 1",
+#if __GNUC__ >= 3
+    "round",		"#undef HAVE_ROUND",		"#define HAVE_ROUND 1",
+#endif
+    "strrchr",		"#undef HAVE_STRRCHR",		"#define HAVE_STRRCHR 1",
+    "__va_copy",	"#undef HAVE_VA_COPY",		"#define HAVE_VA_COPY 1"
+};
+
+/*   NAME               WITHOUT TEXT                            WITH TEXT */
+static cpchar_t g_Components [] = {
+    "shared",		"#BUILD_SHARED\t= 1",			"BUILD_SHARED\t= 1 ",
+    "static",		"#BUILD_STATIC\t= 1",			"BUILD_STATIC\t= 1 ",
+    "debug",		"#DEBUG\t\t= 1",			"DEBUG\t\t= 1 ",
+    "bounds",		"#undef WANT_STREAM_BOUNDS_CHECKING",	"#define WANT_STREAM_BOUNDS_CHECKING 1 ",
+    "fastcopy",		"#undef WANT_UNROLLED_COPY",		"#define WANT_UNROLLED_COPY 1 ",
+#if __GNUC__ >= 3 && (__i386__ || __x86_64__) && !sun
+    "mmx",		"#undef WANT_MMX",			"#define WANT_MMX 1 ",
+#endif
+    "libstdc++",	"#define WITHOUT_LIBSTDCPP 1",		"#undef WITHOUT_LIBSTDCPP",
+    "libstdc++",	"NOLIBSTDCPP\t= -nodefaultlibs ",	"#NOLIBSTDCPP\t= -nodefaultlibs"
+};
+
+/* Parallel to g_Components */
+static SComponentInfo g_ComponentInfos [VectorSize(g_Components) / 3] = {
+    { 1, "Builds the shared library (if supported by the OS)" },
+    { 0, "Builds the static library" },
+    { 0, "Compiles the library with debugging information" },
+    { 1, "Disable runtime bounds checking on stream reads/writes" },
+    { 1, "Disable specializations for copy/fill" },
+#if __GNUC__ >= 3 && (__i386__ || __x86_64__) && !sun
+    { 1, "Disable use of MMX/SSE/3dNow! instructions" },
+#endif
+#if __GNUC__ >= 3
+    { 0, "Link with libstdc++" },
+    { 0, "" }
+#else
+    { 1, "" },
+    { 1, "" }
+#endif
+};
+
+/* Substitutes names like @PACKAGE_NAME@ with the second field */
+static cpchar_t g_CustomVars [] = {
+    "PACKAGE_NAME",		PACKAGE_NAME,
+    "PACKAGE_VERSION",		PACKAGE_VERSION,
+    "PACKAGE_TARNAME",		PACKAGE_TARNAME,
+    "PACKAGE_STRING",		PACKAGE_STRING,
+    "PACKAGE_BUGREPORT",	PACKAGE_BUGREPORT,
+    "LIBNAME",			PACKAGE_NAME,
+    "LIB_MAJOR",		LIB_MAJOR,
+    "LIB_MINOR",		LIB_MINOR,
+    "LIB_BUILD",		LIB_BUILD
+};
+
diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/cmemlink.cpp b/media/libdrm/mobile2/src/util/ustl-1.0/cmemlink.cpp
new file mode 100644
index 0000000..7250e9f
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/ustl-1.0/cmemlink.cpp
@@ -0,0 +1,110 @@
+// This file is part of the ustl library, an STL implementation.
+//
+// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
+// This file is free software, distributed under the MIT License.
+//
+// cmemlink.cc
+//
+// See cmemlink.h for documentation.
+//
+
+#include "cmemlink.h"
+#include "ofstream.h"
+#include "strmsize.h"
+#include "ualgo.h"
+#include "uassert.h"
+
+#if PLATFORM_ANDROID
+#include <stdio.h>
+#undef CPU_HAS_MMX
+#endif
+
+namespace ustl {
+
+/// \brief Attaches the object to pointer \p p of size \p n.
+///
+/// If \p p is NULL and \p n is non-zero, bad_alloc is thrown and current
+/// state remains unchanged.
+///
+void cmemlink::link (const void* p, size_type n)
+{
+    if (!p && n)
+#if PLATFORM_ANDROID
+       printf("bad alloc\n");
+#else /* !PLATFORM_ANDROID */
+	throw bad_alloc (n);
+#endif
+    unlink();
+    relink (p, n);
+}
+
+/// Writes the object to stream \p os
+void cmemlink::write (ostream& os) const
+{
+    const written_size_type sz (size());
+    assert (sz == size() && "No support for writing memblocks larger than 4G");
+    os << sz;
+    os.write (cdata(), sz);
+    os.align (alignof (sz));
+}
+
+/// Writes the object to stream \p os
+void cmemlink::text_write (ostringstream& os) const
+{
+    os.write (begin(), readable_size());
+}
+
+/// Returns the number of bytes required to write this object to a stream.
+cmemlink::size_type cmemlink::stream_size (void) const
+{
+    const written_size_type sz (size());
+    return (Align (stream_size_of (sz) + sz, alignof(sz)));
+}
+
+/// Writes the data to file \p "filename".
+void cmemlink::write_file (const char* filename, int mode) const
+{
+    fstream f;
+    f.exceptions (fstream::allbadbits);
+    f.open (filename, fstream::out | fstream::trunc, mode);
+    f.write (cdata(), readable_size());
+    f.close();
+}
+
+/// swaps the contents with \p l
+void cmemlink::swap (cmemlink& l)
+{
+#if CPU_HAS_MMX && SIZE_OF_POINTER == 4
+    asm (
+	"movq %0, %%mm0\n\t"
+	"movq %2, %%mm1\n\t"
+	"movq %%mm0, %2\n\t"
+	"movq %%mm1, %0"
+	: "=m"(m_Data), "=m"(m_Size), "=m"(l.m_Data), "=m"(l.m_Size)
+	: 
+	: "mm0", "mm1", "st", "st(1)");
+    simd::reset_mmx();
+#elif CPU_HAS_SSE && SIZE_OF_POINTER == 8
+    asm (
+	"movups %0, %%xmm0\n\t"
+	"movups %2, %%xmm1\n\t"
+	"movups %%xmm0, %2\n\t"
+	"movups %%xmm1, %0"
+	: "=m"(m_Data), "=m"(m_Size), "=m"(l.m_Data), "=m"(l.m_Size)
+	: 
+	: "xmm0", "xmm1");
+#else
+    ::ustl::swap (m_Data, l.m_Data);
+    ::ustl::swap (m_Size, l.m_Size);
+#endif
+}
+
+/// Compares to memory block pointed by l. Size is compared first.
+bool cmemlink::operator== (const cmemlink& l) const
+{
+    return (l.m_Size == m_Size &&
+	    (l.m_Data == m_Data || 0 == memcmp (l.m_Data, m_Data, m_Size)));
+}
+
+} // namespace ustl
+
diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/cmemlink.h b/media/libdrm/mobile2/src/util/ustl-1.0/cmemlink.h
new file mode 100644
index 0000000..46a9388
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/ustl-1.0/cmemlink.h
@@ -0,0 +1,101 @@
+// This file is part of the ustl library, an STL implementation.
+//
+// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
+// This file is free software, distributed under the MIT License.
+//
+// cmemlink.h
+//
+
+#ifndef CMEMLINK_H_7CFAB32C5C6732ED29B34EF00EA40A12
+#define CMEMLINK_H_7CFAB32C5C6732ED29B34EF00EA40A12
+
+#include "ualgobase.h"
+
+/// The ustl namespace contains all ustl classes and algorithms.
+namespace ustl {
+
+class istream;
+class ostream;
+class ostringstream;
+
+/// \class cmemlink cmemlink.h ustl.h
+/// \ingroup MemoryManagement
+///
+/// \brief A read-only pointer to a sized block of memory.
+///
+/// Use this class the way you would a const pointer to an allocated unstructured block.
+/// The pointer and block size are available through member functions and cast operator.
+///
+/// Example usage:
+///
+/// \code
+///     void* p = malloc (46721);
+///     cmemlink a, b;
+///     a.link (p, 46721);
+///     assert (a.size() == 46721));
+///     b = a;
+///     assert (b.size() == 46721));
+///     assert (b.DataAt(34) == a.DataAt(34));
+///     assert (0 == memcmp (a, b, 12));
+/// \endcode
+///
+class cmemlink {
+public:
+    typedef char		value_type;
+    typedef const value_type*	pointer;
+    typedef const value_type*	const_pointer;
+    typedef value_type		reference;
+    typedef value_type		const_reference;
+    typedef size_t		size_type;
+    typedef uint32_t		written_size_type;
+    typedef ptrdiff_t		difference_type;
+    typedef const_pointer	const_iterator;
+    typedef const_iterator	iterator;
+    typedef const cmemlink&	rcself_t;
+public:
+    inline		cmemlink (void)				: m_Data (NULL), m_Size (0) { }
+    inline		cmemlink (const void* p, size_type n)	: m_Data (const_pointer(p)), m_Size (n) { assert (p || !n); }
+    inline		cmemlink (const cmemlink& l)		: m_Data (l.m_Data), m_Size (l.m_Size) {}
+    inline virtual     ~cmemlink (void)				{}
+    void		link (const void* p, size_type n);
+			OVERLOAD_POINTER_AND_SIZE_T_V2(link, const void*)
+    inline void		link (const cmemlink& l)	{ link (l.begin(), l.size()); }
+    inline void		link (const void* first, const void* last)	{ link (first, distance (first, last)); }
+    inline void		relink (const void* p, size_type n);
+    inline virtual void	unlink (void)			{ m_Data = NULL; m_Size = 0; }
+    inline rcself_t	operator= (const cmemlink& l)	{ link (l); return (*this); }
+    bool		operator== (const cmemlink& l) const;
+    void		swap (cmemlink& l);
+    inline size_type	size (void) const		{ return (m_Size); }
+    inline size_type	max_size (void) const		{ return (size()); }
+    inline size_type	readable_size (void) const	{ return (size()); }
+    inline bool		empty (void) const		{ return (!size()); }
+   inline const_pointer	cdata (void) const		{ return (m_Data); }
+    inline iterator	begin (void) const		{ return (iterator (cdata())); }
+    inline iterator	iat (size_type i) const		{ assert (i <= size()); return (begin() + i); }
+    inline iterator	end (void) const		{ return (iat (size())); }
+    inline void		resize (size_type n)		{ m_Size = n; }
+    inline void		read (istream&)			{ assert (!"ustl::cmemlink is a read-only object."); }
+    void		write (ostream& os) const;
+    size_type		stream_size (void) const;
+    void		text_write (ostringstream& os) const;
+    void		write_file (const char* filename, int mode = 0644) const;
+private:
+    const_pointer	m_Data;		///< Pointer to the data block (const)
+    size_type		m_Size;		///< size of the data block
+};
+
+/// A fast alternative to link which can be used when relinking to the same block (i.e. when it is resized)
+inline void cmemlink::relink (const void* p, size_type n)
+{
+    m_Data = reinterpret_cast<const_pointer>(p);
+    m_Size = n;
+}
+
+/// Use with cmemlink-derived classes to link to a static array
+#define static_link(v)	link (VectorBlock(v))
+
+} // namespace ustl
+
+#endif
+
diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/config.h b/media/libdrm/mobile2/src/util/ustl-1.0/config.h
new file mode 100644
index 0000000..e6e4b7f
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/ustl-1.0/config.h
@@ -0,0 +1,296 @@
+// config.h
+//
+// Autogenerated from config.h.in by bsconf.
+//
+
+#ifndef CONFIG_H_01E33670634DAAC779EE5FF41CCBB36F
+#define CONFIG_H_01E33670634DAAC779EE5FF41CCBB36F
+
+#include "uassert.h"
+
+#if PLATFORM_ANDROID
+
+#include <utils/Endian.h>
+
+// Byte order macros, converted in utypes.h
+#define USTL_LITTLE_ENDIAN	__LITTLE_ENDIAN
+#define USTL_BIG_ENDIAN		__BIG_ENDIAN
+#define USTL_BYTE_ORDER		__BYTE_ORDER
+
+#if !defined NDEBUG
+#define NDEBUG
+#endif
+#else /* !PLATFORM_ANDROID */
+// Byte order macros, converted in utypes.h
+#define USTL_LITTLE_ENDIAN	4321
+#define USTL_BIG_ENDIAN		1234
+#define USTL_BYTE_ORDER		USTL_LITTLE_ENDIAN
+#endif
+
+// Define to the one symbol short name of this package.
+#define USTL_NAME	"ustl"
+// Define to the full name and version of this package.
+#define USTL_STRING	"ustl 1.0"
+// Define to the version of this package.
+#define USTL_VERSION	0x100
+// Define to the address where bug reports for this package should be sent.
+#define USTL_BUGREPORT	"Mike Sharov <msharov@users.sourceforge.net>"
+
+/// Define to 1 if you want stream operations to throw exceptions on
+/// insufficient data or insufficient space. All these errors should
+/// be preventable in output code; the input code should verify the
+/// data in a separate step. It slows down stream operations a lot,
+/// but it's your call. By default only debug builds throw.
+///
+#undef WANT_STREAM_BOUNDS_CHECKING
+
+#if !defined(WANT_STREAM_BOUNDS_CHECKING) && !defined(NDEBUG)
+    #define WANT_STREAM_BOUNDS_CHECKING 1
+#endif
+
+/// Define to 1 if you want to build without libstdc++
+#define WITHOUT_LIBSTDCPP 1
+
+/// Define GNU extensions if unavailable.
+#ifndef __GNUC__
+    /// GCC (and some other compilers) define '__attribute__'; ustl is using this
+    /// macro to alert the compiler to flag inconsistencies in printf/scanf-like
+    /// function calls.  Just in case '__attribute__' isn't defined, make a dummy.
+    /// 
+    #ifndef __attribute__
+	#define __attribute__(p)
+    #endif
+#endif
+#if defined(__GNUC__) && __GNUC__ >= 4
+    #define DLL_EXPORT		__attribute__((visibility("default")))
+    #define DLL_LOCAL		__attribute__((visibility("hidden")))
+#else
+    #define DLL_EXPORT
+    #define DLL_LOCAL
+#endif
+#if defined(__GNUC__) && __GNUC__ >= 3 && __i386__
+    /// GCC 3+ supports the prefetch directive, which some CPUs use to improve caching
+    #define prefetch(p,rw,loc)	__builtin_prefetch(p,rw,loc)
+#else
+    #define prefetch(p,rw,loc)
+#endif
+#if !defined(__GNUC__) || __GNUC__ < 3
+    /// __alignof__ returns the recommended alignment for the type
+    #define __alignof__(v)	min(sizeof(v), sizeof(void*))
+#endif
+
+/// Define to 1 if you have the `atexit' function.
+#define HAVE_ATEXIT 1
+
+/// Define to 1 if you have the <assert.h> header file.
+#define HAVE_ASSERT_H 1
+
+/// Define to 1 if you have the <ctype.h> header file.
+#define HAVE_CTYPE_H 1
+
+/// Define to 1 if you have the <errno.h> header file.
+#define HAVE_ERRNO_H 1
+
+/// Define to 1 if you have the <fcntl.h> header file.
+#define HAVE_FCNTL_H 1
+
+/// Define to 1 if you have the <float.h> header file.
+#define HAVE_FLOAT_H 1
+
+/// Define to 1 if you have the <inttypes.h> header file.
+#define HAVE_INTTYPES_H 1
+
+/// Define to 1 if you have the <limits.h> header file.
+#define HAVE_LIMITS_H 1
+
+/// Define to 1 if you have the <locale.h> header file.
+#define HAVE_LOCALE_H 1
+
+/// Define to 1 if your system has a working `malloc' function.
+#define HAVE_MALLOC 1
+
+// Define to 1 if you have the <malloc.h> header file.
+#undef HAVE_MALLOC_H
+
+// Define to 1 if you have the <alloca.h> header file.
+#define HAVE_ALLOCA_H 1
+
+// Define to 1 if you have the `memchr' function.
+#define HAVE_MEMCHR 1
+
+// Define to 1 if you have the `memmove' function.
+#define HAVE_MEMMOVE 1
+
+// Define to 1 if you have the <memory.h> header file.
+#define HAVE_MEMORY_H 1
+
+// Define to 1 if you have the `memset' function.
+#define HAVE_MEMSET 1
+
+// Define to 1 if the system has the type `ptrdiff_t'.
+#define HAVE_PTRDIFF_T 1
+
+// Define to 1 if you have the <signal.h> header file.
+#define HAVE_SIGNAL_H 1
+
+// Define to 1 if you have the __va_copy function
+#define HAVE_VA_COPY 1
+
+// Define to 1 if `stat' has the bug that it succeeds when given the
+// zero-length file name argument.
+/* #undef HAVE_STAT_EMPTY_STRING_BUG */
+
+// Define to 1 if you have the <stdarg.h> header file.
+#define HAVE_STDARG_H 1
+
+// Define to 1 if you have the <stddef.h> header file.
+#define HAVE_STDDEF_H 1
+
+// Define to 1 if you have the <stdint.h> header file.
+#define HAVE_STDINT_H 1
+
+// Define to 1 if you have the <stdio.h> header file.
+#define HAVE_STDIO_H 1
+
+// Define to 1 if you have the <stdlib.h> header file.
+#define HAVE_STDLIB_H 1
+
+// Define to 1 if you have the `strerror' function.
+#define HAVE_STRERROR 1
+
+// Define to 1 if you have the <strings.h> header file.
+#define HAVE_STRINGS_H 1
+
+// Define to 1 if you have the <string.h> header file.
+#define HAVE_STRING_H 1
+
+// Define to 1 if you have the `strrchr' function.
+#define HAVE_STRRCHR 1
+
+// Define to 1 if you have the `strsignal' function.
+#undef HAVE_STRSIGNAL
+
+// Define to 1 if you have the `strtol' function.
+#define HAVE_STRTOL 1
+
+// Define to 1 if you have the <sys/stat.h> header file.
+#define HAVE_SYS_STAT_H 1
+
+// Define to 1 if you have the <sys/types.h> header file.
+#define HAVE_SYS_TYPES_H 1
+
+// Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible.
+#define HAVE_SYS_WAIT_H 1
+
+// Define to 1 if you have the <time.h> header file.
+#define HAVE_TIME_H 1
+
+// Define to 1 if you have the <unistd.h> header file.
+#define HAVE_UNISTD_H 1
+
+// Define to 1 if you have the <math.h> header file.
+#define HAVE_MATH_H 1
+
+// Define to 1 if you have the rintf function. Will use rint otherwise.
+#undef HAVE_RINTF
+
+// STDC_HEADERS is defined to 1 on sane systems.
+#if defined(HAVE_ASSERT_H) && defined(HAVE_CTYPE_H) &&\
+    defined(HAVE_ERRNO_H) && defined(HAVE_FLOAT_H) &&\
+    defined(HAVE_LIMITS_H) && defined(HAVE_LOCALE_H) &&\
+    defined(HAVE_MATH_H) && defined(HAVE_SIGNAL_H) &&\
+    defined(HAVE_STDARG_H) && defined(HAVE_STDDEF_H) &&\
+    defined(HAVE_STDIO_H) && defined(HAVE_STDLIB_H) &&\
+    defined(HAVE_STRING_H) && defined(HAVE_TIME_H)
+#define STDC_HEADERS 1
+#endif
+
+// STDC_HEADERS is defined to 1 on unix systems.
+#if defined(HAVE_FCNTL_H) && defined(HAVE_SYS_STAT_H) && defined(HAVE_UNISTD_H)
+#define STDUNIX_HEADERS 1
+#endif
+
+// Define to 1 if `lstat' dereferences a symlink specified with a trailing slash.
+#define LSTAT_FOLLOWS_SLASHED_SYMLINK 1
+
+// Define to 1 if your compiler treats char as a separate type along with
+// signed char and unsigned char. This will create overloads for char.
+#define HAVE_THREE_CHAR_TYPES 1
+
+// Define as the return type of signal handlers (`int' or `void').
+#define RETSIGTYPE void
+
+// Define to 1 if you have 64 bit types available
+#define HAVE_INT64_T 1
+
+// Define to 1 if you have the long long type
+#undef HAVE_LONG_LONG
+
+// Define to 1 if you want unrolled specializations for fill and copy
+#define WANT_UNROLLED_COPY 1 
+
+// Define to 1 if you want to use MMX/SSE/3dNow! processor instructions
+#undef WANT_MMX
+
+// Define to byte sizes of types
+#define SIZE_OF_CHAR 1
+#define SIZE_OF_SHORT 2
+#define SIZE_OF_INT 4
+#define SIZE_OF_LONG 4
+#define SIZE_OF_LONG_LONG 8
+#define SIZE_OF_POINTER 4
+#define SIZE_OF_SIZE_T 4
+#define SIZE_OF_BOOL SIZE_OF_LONG
+#if SIZE_OF_SIZE_T == SIZE_OF_LONG
+#define SIZE_T_IS_LONG 1
+#else
+#define SIZE_T_IS_LONG 0
+#endif
+
+// Extended CPU capabilities
+#undef CPU_HAS_FPU
+#undef CPU_HAS_EXT_DEBUG
+#undef CPU_HAS_TIMESTAMPC
+#undef CPU_HAS_MSR
+#undef CPU_HAS_CMPXCHG8
+#undef CPU_HAS_APIC
+#undef CPU_HAS_SYSCALL
+#undef CPU_HAS_MTRR
+#undef CPU_HAS_CMOV
+#undef CPU_HAS_FCMOV
+#if WANT_MMX
+#undef CPU_HAS_MMX
+#undef CPU_HAS_FXSAVE
+#undef CPU_HAS_SSE 
+#undef CPU_HAS_SSE2
+#undef CPU_HAS_SSE3
+#undef CPU_HAS_EXT_3DNOW
+#undef CPU_HAS_3DNOW
+#endif
+
+// GCC vector extensions
+#if defined(CPU_HAS_MMX) || defined(CPU_HAS_SSE)
+    #define HAVE_VECTOR_EXTENSIONS 1
+#endif
+
+#if CPU_HAS_SSE && defined(__GNUC__)
+    #define __sse_align	__attribute__((aligned(16)))
+#else
+    #define __sse_align	
+#endif
+
+// Define to empty if `const' does not conform to ANSI C.
+/* #define const */
+
+// Define as `__inline' if that's what the C compiler calls it, or to nothing
+// if it is not supported.
+/* #define inline __inline */
+
+// Define to `long' if <sys/types.h> does not define.
+/* typedef long off_t; */
+
+// Define to `unsigned' if <sys/types.h> does not define.
+/* typedef long size_t; */
+
+#endif	// CONFIG_H_01E33670634DAAC779EE5FF41CCBB36F
+
diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/fstream.cpp b/media/libdrm/mobile2/src/util/ustl-1.0/fstream.cpp
new file mode 100644
index 0000000..06b9691
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/ustl-1.0/fstream.cpp
@@ -0,0 +1,282 @@
+// This file is part of the ustl library, an STL implementation.
+//
+// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
+// This file is free software, distributed under the MIT License.
+//
+// file.cc
+//
+
+#include "fstream.h"
+#include "uassert.h"
+#include "uexception.h"
+#include "uutility.h"
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+
+#if PLATFORM_ANDROID
+#include <stdio.h>
+#endif
+
+namespace ustl {
+
+/// Default constructor.
+fstream::fstream (void)
+: ios_base (),
+  m_fd (-1),
+  m_Filename ()
+{
+}
+
+/// Opens \p filename in \p mode.
+fstream::fstream (const char* filename, openmode mode)
+: ios_base (),
+  m_fd (-1),
+  m_Filename ()
+{
+    open (filename, mode);
+}
+
+/// Attaches to \p nfd of \p filename.
+fstream::fstream (int nfd, const char* filename)
+: ios_base (),
+  m_fd (-1),
+  m_Filename ()
+{
+    attach (nfd, filename);
+}
+
+/// Destructor. Closes if still open, but without throwing.
+fstream::~fstream (void) throw()
+{
+    clear (goodbit);
+    exceptions (goodbit);
+    close();
+    assert (!(rdstate() & badbit) && "close failed in the destructor! This may lead to loss of user data. Please call close() manually and either enable exceptions or check the badbit.");
+}
+
+/// Sets state \p s and throws depending on the exception setting.
+void fstream::set_and_throw (iostate s, const char* op)
+{
+    if (ios_base::set_and_throw (s))
+#if PLATFORM_ANDROID
+        printf("file_exception\n");
+#else /* !PLATFORM_ANDROID */
+	throw file_exception (op, name());
+#endif
+}
+
+/// Attaches to the given \p nfd.
+void fstream::attach (int nfd, const char* filename)
+{
+    assert (filename && "Don't do that");
+    clear (goodbit);
+    if (nfd < 0 && ios_base::set_and_throw (badbit))
+#if PLATFORM_ANDROID
+        printf("file exception\n");
+#else /* !PLATFORM_ANDROID */
+	throw file_exception ("open", filename);
+#endif
+    close();
+    m_fd = nfd;
+    m_Filename = filename;
+}
+
+/// Detaches from the current fd.
+void fstream::detach (void)
+{
+    m_fd = -1;
+    m_Filename.clear();
+}
+
+/// Converts openmode bits into libc open flags.
+/*static*/ int fstream::om_to_flags (openmode m)
+{
+    static const int s_OMFlags [nombits] = {
+	0,		// in
+	O_CREAT,	// out
+	O_APPEND,	// app
+	O_APPEND,	// ate
+	0,		// binary
+	O_TRUNC,	// trunc
+	O_NONBLOCK,	// nonblock
+	0,		// nocreate
+	O_NOCTTY	// noctty
+    };
+    int flags = (m - 1) & O_ACCMODE;	// in and out
+    for (uoff_t i = 0; i < VectorSize(s_OMFlags); ++ i)
+	if (m & (1 << i))
+	    flags |= s_OMFlags[i];
+    if (m & nocreate)
+	flags &= ~O_CREAT;
+    return (flags);
+}
+
+/// \brief Opens \p filename in the given mode.
+/// \warning The string at \p filename must exist until the object is closed.
+void fstream::open (const char* filename, openmode mode, mode_t perms)
+{
+    int nfd = ::open (filename, om_to_flags(mode), perms);
+    attach (nfd, filename);
+}
+
+/// Closes the file and throws on error.
+void fstream::close (void)
+{
+    if (m_fd >= 0 && ::close(m_fd))
+	set_and_throw (badbit | failbit, "close");
+    detach();
+}
+
+/// Moves the current file position to \p n.
+off_t fstream::seek (off_t n, seekdir whence)
+{
+    off_t p = lseek (m_fd, n, whence);
+    if (p < 0)
+	set_and_throw (failbit, "seek");
+    return (p);
+}
+
+/// Returns the current file position.
+off_t fstream::pos (void) const
+{
+    return (lseek (m_fd, 0, SEEK_CUR));
+}
+
+/// Reads \p n bytes into \p p.
+off_t fstream::read (void* p, off_t n)
+{
+    off_t br (0);
+    while (br < n && good())
+	br += readsome (advance (p, br), n - br);
+    return (br);
+}
+
+/// Reads at most \p n bytes into \p p, stopping when it feels like it.
+off_t fstream::readsome (void* p, off_t n)
+{
+    ssize_t brn;
+    do { brn = ::read (m_fd, p, n); } while (brn < 0 && errno == EINTR);
+    if (brn > 0)
+	return (brn);
+    if (brn < 0 && errno != EAGAIN)
+	set_and_throw (failbit, "read");
+    if (!brn && ios_base::set_and_throw (eofbit | failbit))
+#if PLATFORM_ANDROID
+        printf("stream_bounds_exception\n");
+#else /* !PLATFORM_ANDROID */
+        throw stream_bounds_exception ("read", name(), pos(), n, 0);
+#endif
+    return (0);
+}
+
+/// Writes \p n bytes from \p p.
+off_t fstream::write (const void* p, off_t n)
+{
+    off_t btw (n);
+    while (btw) {
+	const off_t bw (n - btw);
+	ssize_t bwn = ::write (m_fd, advance(p,bw), btw);
+	if (bwn > 0)
+	    btw -= bwn;
+	else if (!bwn) {
+	    if (ios_base::set_and_throw (eofbit | failbit))
+#if PLATFORM_ANDROID
+	      printf("stream_bounds_exception\n");
+#else /* !PLATFORM_ANDROID */
+	    throw stream_bounds_exception ("write", name(), pos() - bw, n, bw);
+#endif
+	    break;
+	} else if (errno != EINTR) {
+	    if (errno != EAGAIN)
+		set_and_throw (failbit, "write");
+	    break;
+	}
+    }
+    return (n - btw);
+}
+
+/// Returns the file size.
+off_t fstream::size (void) const
+{
+    struct stat st;
+    st.st_size = 0;
+    stat (st);
+    return (st.st_size);
+}
+
+/// Synchronizes the file's data and status with the disk.
+void fstream::sync (void)
+{
+    if (fsync (m_fd))
+	set_and_throw (failbit, "sync");
+}
+
+/// Get the stat structure.
+void fstream::stat (struct stat& rs) const
+{
+    if (fstat (m_fd, &rs))
+#if PLATFORM_ANDROID
+        printf("file_exception\n");
+#else
+	throw file_exception ("stat", name());
+#endif
+}
+
+/// Calls the given ioctl. Use IOCTLID macro to pass in both \p name and \p request.
+int fstream::ioctl (const char* rname, int request, long argument)
+{
+    int rv = ::ioctl (m_fd, request, argument);
+    if (rv < 0)
+	set_and_throw (failbit, rname);
+    return (rv);
+}
+
+/// Calls the given fcntl. Use FCNTLID macro to pass in both \p name and \p request.
+int fstream::fcntl (const char* rname, int request, long argument)
+{
+    int rv = ::fcntl (m_fd, request, argument);
+    if (rv < 0)
+	set_and_throw (failbit, rname);
+    return (rv);
+}
+
+/// Memory-maps the file and returns a link to it.
+memlink fstream::mmap (off_t n, off_t offset)
+{
+    void* result = ::mmap (NULL, n, PROT_READ | PROT_WRITE, MAP_SHARED, m_fd, offset);
+    if (result == MAP_FAILED)
+	set_and_throw (failbit, "mmap");
+    return (memlink (result, n));
+}
+
+/// Unmaps a memory-mapped area.
+void fstream::munmap (memlink& l)
+{
+    if (::munmap (l.data(), l.size()))
+	set_and_throw (failbit, "munmap");
+    l.unlink();
+}
+
+/// Synchronizes a memory-mapped area.
+void fstream::msync (memlink& l)
+{
+    if (::msync (l.data(), l.size(), MS_ASYNC | MS_INVALIDATE))
+	set_and_throw (failbit, "msync");
+}
+
+void fstream::set_nonblock (bool v)
+{
+    int curf = fcntl (FCNTLID (F_GETFL));
+    if (curf < 0) return;
+    if (v) curf |=  O_NONBLOCK;
+    else   curf &= ~O_NONBLOCK;
+    fcntl (FCNTLID (F_SETFL), curf);
+}
+
+} // namespace ustl
+
diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/fstream.h b/media/libdrm/mobile2/src/util/ustl-1.0/fstream.h
new file mode 100644
index 0000000..cf60bbd
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/ustl-1.0/fstream.h
@@ -0,0 +1,78 @@
+// This file is part of the ustl library, an STL implementation.
+//
+// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
+// This file is free software, distributed under the MIT License.
+//
+// fstream.h
+//
+
+#ifndef FSTREAM_H_056E10F70EAD416443E3B36A2D6B5FA3
+#define FSTREAM_H_056E10F70EAD416443E3B36A2D6B5FA3
+
+#include "uios.h"
+#include "ustring.h"
+
+struct stat;
+
+namespace ustl {
+
+/// \class fstream fstream.h ustl.h
+///
+/// \brief Implements file operations.
+///
+/// This is not implemented as a stream, but rather as a base for one. You
+/// should use ifstream or ofstream if you want flow operators. Otherwise
+/// this only implements functions for binary i/o.
+///
+class fstream : public ios_base {
+public:
+			fstream (void);
+    explicit		fstream (const char* filename, openmode mode = in | out);
+    explicit		fstream (int nfd, const char* filename = string::empty_string);
+		       ~fstream (void) throw();
+    void		open (const char* filename, openmode mode, mode_t perms = 0644);
+    void		attach (int nfd, const char* filename = string::empty_string);
+    void		detach (void);
+    void		close (void);
+    void		sync (void);
+    off_t		read (void* p, off_t n);
+    off_t		readsome (void* p, off_t n);
+    off_t		write (const void* p, off_t n);
+    off_t		size (void) const;
+    off_t		seek (off_t n, seekdir whence = beg);
+    off_t		pos (void) const;
+    void		stat (struct stat& rs) const;
+    int			ioctl (const char* rname, int request, long argument = 0);
+    inline int		ioctl (const char* rname, int request, int argument)	{ return (fstream::ioctl (rname, request, long(argument))); }
+    inline int		ioctl (const char* rname, int request, void* argument)	{ return (fstream::ioctl (rname, request, intptr_t(argument))); }
+    int			fcntl (const char* rname, int request, long argument = 0);
+    inline int		fcntl (const char* rname, int request, int argument)	{ return (fstream::fcntl (rname, request, long(argument))); }
+    inline int		fcntl (const char* rname, int request, void* argument)	{ return (fstream::fcntl (rname, request, intptr_t(argument))); }
+    memlink		mmap (off_t n, off_t offset = 0);
+    void		munmap (memlink& l);
+    void		msync (memlink& l);
+    void		set_nonblock (bool v = true);
+    inline int		fd (void) const		{ return (m_fd); }
+    inline bool		is_open (void) const	{ return (fd() >= 0); }
+    inline off_t	tellg (void) const	{ return (pos()); }
+    inline off_t	tellp (void) const	{ return (pos()); }
+    inline void		seekg (off_t n, seekdir whence = beg)	{ seek (n, whence); }
+    inline void		seekp (off_t n, seekdir whence = beg)	{ seek (n, whence); }
+    inline void		flush (void)		{ sync(); }
+    inline const string& name (void) const	{ return (m_Filename); }
+private:
+   DLL_LOCAL static int	om_to_flags (openmode m);
+    DLL_LOCAL void	set_and_throw (iostate s, const char* op);
+private:
+    int			m_fd;		///< Currently open file descriptor.
+    string		m_Filename;	///< Currently open filename.
+};
+
+/// Argument macro for fstream::ioctl. Use like fs.ioctl (IOCTLID (TCGETS), &ts).
+#define IOCTLID(r)	"ioctl("#r")", r
+#define FCNTLID(r)	"fcntl("#r")", r
+
+}
+
+#endif
+
diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/memblock.cpp b/media/libdrm/mobile2/src/util/ustl-1.0/memblock.cpp
new file mode 100644
index 0000000..721433e
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/ustl-1.0/memblock.cpp
@@ -0,0 +1,216 @@
+// This file is part of the ustl library, an STL implementation.
+//
+// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
+// This file is free software, distributed under the MIT License.
+//
+// memblock.cc
+//
+//	Allocated memory block.
+//
+
+#include "fstream.h"
+#include "mistream.h"
+#include "memblock.h"
+#include "ualgo.h"
+#include "uassert.h"
+#include "umemory.h"
+
+#include <errno.h>
+
+namespace ustl {
+
+/// Allocates 0 bytes for the internal block.
+memblock::memblock (void)
+: memlink (),
+  m_Capacity (0)
+{
+}
+
+/// Allocates \p n bytes for the internal block.
+memblock::memblock (size_type n)
+: memlink (),
+  m_Capacity (0)
+{
+    resize (n);
+}
+
+/// links to \p p, \p n. Data can not be modified and will not be freed.
+memblock::memblock (const void* p, size_type n)
+: memlink (),
+  m_Capacity (0)
+{
+    assign (p, n);
+}
+
+/// Links to what \p b is linked to.
+memblock::memblock (const cmemlink& b)
+: memlink (),
+  m_Capacity (0)
+{
+    assign (b);
+}
+
+/// Links to what \p b is linked to.
+memblock::memblock (const memlink& b)
+: memlink (),
+  m_Capacity (0)
+{
+    assign (b);
+}
+
+/// Links to what \p b is linked to.
+memblock::memblock (const memblock& b)
+: memlink (),
+  m_Capacity (0)
+{
+    assign (b);
+}
+
+/// Frees internal data, if appropriate
+/// Only if the block was allocated using resize, or linked to using Manage,
+/// will it be freed. Also, Derived classes should call DestructBlock from
+/// their destructor, because upstream virtual functions are unavailable at
+/// this point and will not be called automatically.
+///
+memblock::~memblock (void)
+{
+    if (!is_linked())
+	deallocate();
+}
+
+/// resizes the block to \p newSize bytes, reallocating if necessary.
+void memblock::resize (size_type newSize, bool bExact)
+{
+    if (m_Capacity < newSize + minimumFreeCapacity())
+	reserve (newSize, bExact);
+    memlink::resize (newSize);
+}
+
+/// Frees internal data.
+void memblock::deallocate (void) throw()
+{
+    if (m_Capacity) {
+	assert (cdata() && "Internal error: space allocated, but the pointer is NULL");
+	assert (data() && "Internal error: read-only block is marked as allocated space");
+	free (data());
+    }
+    unlink();
+}
+
+/// Assumes control of the memory block \p p of size \p n.
+/// The block assigned using this function will be freed in the destructor.
+void memblock::manage (void* p, size_type n)
+{
+    assert (p || !n);
+    assert (!m_Capacity && "Already managing something. deallocate or unlink first.");
+    link (p, n);
+    m_Capacity = n;
+}
+
+/// "Instantiate" a linked block by allocating and copying the linked data.
+void memblock::copy_link (void)
+{
+    const cmemlink l (*this);
+    if (is_linked())
+	unlink();
+    assign (l);
+}
+ 
+/// Copies data from \p p, \p n.
+void memblock::assign (const void* p, size_type n)
+{
+    assert ((p != (const void*) cdata() || size() == n) && "Self-assignment can not resize");
+    resize (n);
+    copy (p, n);
+}
+
+/// \brief Reallocates internal block to hold at least \p newSize bytes.
+///
+/// Additional memory may be allocated, but for efficiency it is a very
+/// good idea to call reserve before doing byte-by-byte edit operations.
+/// The block size as returned by size() is not altered. reserve will not
+/// reduce allocated memory. If you think you are wasting space, call
+/// deallocate and start over. To avoid wasting space, use the block for
+/// only one purpose, and try to get that purpose to use similar amounts
+/// of memory on each iteration.
+///
+void memblock::reserve (size_type newSize, bool bExact)
+{
+    if ((newSize += minimumFreeCapacity()) <= m_Capacity)
+	return;
+    void* oldBlock (is_linked() ? NULL : data());
+    if (!bExact)
+	newSize = Align (newSize, c_PageSize);
+    pointer newBlock = (pointer) realloc (oldBlock, newSize);
+    if (!newBlock)
+#if PLATFORM_ANDROID
+        printf("bad_alloc\n");
+#else
+	throw bad_alloc (newSize);
+#endif
+    if (!oldBlock && cdata())
+	copy_n (cdata(), min (size() + 1, newSize), newBlock);
+    link (newBlock, size());
+    m_Capacity = newSize;
+}
+
+/// Swaps the contents with \p l
+void memblock::swap (memblock& l)
+{
+    memlink::swap (l);
+    ::ustl::swap (m_Capacity, l.m_Capacity);
+}
+
+/// Shifts the data in the linked block from \p start to \p start + \p n.
+memblock::iterator memblock::insert (iterator start, size_type n)
+{
+    const uoff_t ip = start - begin();
+    assert (ip <= size());
+    resize (size() + n, false);
+    memlink::insert (iat(ip), n);
+    return (iat (ip));
+}
+
+/// Shifts the data in the linked block from \p start + \p n to \p start.
+memblock::iterator memblock::erase (iterator start, size_type n)
+{
+    const uoff_t ep = start - begin();
+    assert (ep + n <= size());
+    memlink::erase (start, n);
+    memlink::resize (size() - n);
+    return (iat (ep));
+}
+
+/// Unlinks object.
+void memblock::unlink (void)
+{
+    memlink::unlink();
+    m_Capacity = 0;
+}
+
+/// Reads the object from stream \p s
+void memblock::read (istream& is)
+{
+    written_size_type n;
+    is >> n;
+    is.verify_remaining ("read", "ustl::memblock", n);
+    resize (n);
+    is.read (data(), writable_size());
+    is.align (alignof (n));
+}
+
+/// Reads the entire file \p "filename".
+void memblock::read_file (const char* filename)
+{
+    fstream f;
+    f.exceptions (fstream::allbadbits);
+    f.open (filename, fstream::in);
+    const off_t fsize (f.size());
+    reserve (fsize);
+    f.read (data(), fsize);
+    f.close();
+    resize (fsize);
+}
+
+} // namespace ustl
+
diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/memblock.h b/media/libdrm/mobile2/src/util/ustl-1.0/memblock.h
new file mode 100644
index 0000000..d85ea0e
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/ustl-1.0/memblock.h
@@ -0,0 +1,74 @@
+// This file is part of the ustl library, an STL implementation.
+//
+// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
+// This file is free software, distributed under the MIT License.
+//
+// memblock.h
+//
+
+#ifndef MEMBLOCK_H_7ED63A891164CC43578E63664D52A196
+#define MEMBLOCK_H_7ED63A891164CC43578E63664D52A196
+
+#include "memlink.h"
+
+namespace ustl {
+
+/// \class memblock memblock.h ustl.h
+/// \ingroup MemoryManagement
+///
+/// \brief Allocated memory block.
+///
+/// Adds memory management capabilities to memlink. Uses malloc and realloc to
+/// maintain the internal pointer, but only if allocated using members of this class,
+/// or if linked to using the Manage() member function. Managed memory is automatically
+/// freed in the destructor.
+///
+class memblock : public memlink {
+public:
+    static const size_type	c_PageSize = 64;	///< The default minimum allocation unit.
+public:
+				memblock (void);
+				memblock (const void* p, size_type n);
+    explicit			memblock (size_type n);
+    explicit			memblock (const cmemlink& b);
+    explicit			memblock (const memlink& b);
+				memblock (const memblock& b);
+    virtual		       ~memblock (void);
+    virtual void		unlink (void);
+    inline void			assign (const cmemlink& l)	{ assign (l.cdata(), l.readable_size()); }
+    inline const memblock&	operator= (const cmemlink& l)	{ assign (l); return (*this); }
+    inline const memblock&	operator= (const memlink& l)	{ assign (l); return (*this); }
+    inline const memblock&	operator= (const memblock& l)	{ assign (l); return (*this); }
+    void			assign (const void* p, size_type n);
+    void			swap (memblock& l);
+    void			reserve (size_type newSize, bool bExact = true);
+    void			resize (size_type newSize, bool bExact = true);
+    iterator			insert (iterator start, size_type size);
+    iterator			erase (iterator start, size_type size);
+    inline void			clear (void)			{ resize (0); }
+    inline bool			is_linked (void) const		{ return (!m_Capacity && cdata()); }
+    inline size_type		max_size (void) const		{ return (is_linked() ? memlink::max_size() : SIZE_MAX); }
+    inline size_type		capacity (void) const		{ return (m_Capacity); }
+    inline void			manage (memlink& l)		{ manage (l.begin(), l.size()); }
+    void			deallocate (void) throw();
+    void			manage (void* p, size_type n);
+    void			copy_link (void);
+    void			read (istream& is);
+    void			read_file (const char* filename);
+protected:
+    inline virtual size_type	minimumFreeCapacity (void) const { return (0); }
+private:
+    size_type			m_Capacity;	///< Number of bytes allocated by Resize.
+};
+
+/// Reads object \p l from stream \p is
+inline istream& operator>> (istream& is, memblock& l)
+{
+    l.read (is);
+    return (is);
+}
+
+} // namespace ustl
+
+#endif
+
diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/memlink.cpp b/media/libdrm/mobile2/src/util/ustl-1.0/memlink.cpp
new file mode 100644
index 0000000..bed6601
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/ustl-1.0/memlink.cpp
@@ -0,0 +1,66 @@
+// This file is part of the ustl library, an STL implementation.
+//
+// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
+// This file is free software, distributed under the MIT License.
+//
+// memlink.cc
+//
+//	A pointer to a sized block of memory.
+//
+
+#include "mistream.h"
+#include "uassert.h"
+#include "ustdxept.h"
+
+#if PLATFORM_ANDROID
+#include <stdio.h>
+#endif
+
+namespace ustl {
+
+/// Reads the object from stream \p s
+void memlink::read (istream& is)
+{
+    written_size_type n;
+    is >> n;
+    is.verify_remaining ("read", "ustl::memlink", n);
+    if (n > size())
+#if PLATFORM_ANDROID
+        printf("length error\n");
+#else
+	throw length_error ("memlink can not increase the size of the linked storage for reading");
+#endif
+    resize (n);
+    is.read (data(), n);
+    is.align (alignof (n));
+}
+
+/// Copies data from \p p, \p n to the linked block starting at \p start.
+void memlink::copy (iterator start, const void* p, size_type n)
+{
+    assert (data() || !n);
+    assert (p || !n);
+    assert (start >= begin() && start + n <= end());
+    if (p)
+	copy_n (const_iterator(p), n, start);
+}
+
+/// Fills the linked block with the given pattern.
+/// \arg start   Offset at which to start filling the linked block
+/// \arg p       Pointer to the pattern.
+/// \arg elSize  Size of the pattern.
+/// \arg elCount Number of times to write the pattern.
+/// Total number of bytes written is \p elSize * \p elCount.
+///
+void memlink::fill (iterator start, const void* p, size_type elSize, size_type elCount)
+{
+    assert (data() || !elCount || !elSize);
+    assert (start >= begin() && start + elSize * elCount <= end());
+    if (elSize == 1)
+	fill_n (start, elCount, *reinterpret_cast<const uint8_t*>(p));
+    else while (elCount--)
+	start = copy_n (const_iterator(p), elSize, start);
+}
+
+} // namespace ustl
+
diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/memlink.h b/media/libdrm/mobile2/src/util/ustl-1.0/memlink.h
new file mode 100644
index 0000000..25d9928
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/ustl-1.0/memlink.h
@@ -0,0 +1,115 @@
+// This file is part of the ustl library, an STL implementation.
+//
+// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
+// This file is free software, distributed under the MIT License.
+//
+// memlink.h
+
+#ifndef MEMLINK_H_798D25827C8E322D2D7E734B169FF5FC
+#define MEMLINK_H_798D25827C8E322D2D7E734B169FF5FC
+
+#include "cmemlink.h"
+#include "ualgo.h"
+#include "uassert.h"
+
+namespace ustl {
+
+/// \class memlink memlink.h ustl.h
+/// \ingroup MemoryManagement
+///
+/// \brief Wrapper for pointer to block with size.
+///
+/// Use this class the way you would a pointer to an allocated unstructured block.
+/// The pointer and block size are available through member functions and cast operator.
+///
+/// Example usage:
+/// \code
+///     void* p = malloc (46721);
+///     memlink a, b;
+///     a.link (p, 46721);
+///     assert (a.size() == 46721));
+///     b = a;
+///     assert (b.size() == 46721));
+///     assert (b.begin() + 34 == a.begin + 34);
+///     assert (0 == memcmp (a, b, 12));
+///     a.fill (673, b, 42, 67);
+///     b.erase (87, 12);
+/// \endcode
+///
+class memlink : public cmemlink {
+public:
+    typedef value_type*			pointer;
+    typedef cmemlink::pointer		const_pointer;
+    typedef cmemlink::const_iterator	const_iterator;
+    typedef pointer			iterator;
+    typedef const memlink&		rcself_t;
+public:
+    inline		memlink (void)				: cmemlink() {}
+    inline		memlink (void* p, size_type n)		: cmemlink (p, n) {}
+    inline		memlink (const void* p, size_type n)	: cmemlink (p, n) {}
+    inline		memlink (rcself_t l)			: cmemlink (l) {}
+    inline explicit	memlink (const cmemlink& l)		: cmemlink (l) {}
+    inline pointer	data (void)				{ return (const_cast<pointer>(cdata())); }
+    inline iterator	begin (void)				{ return (iterator (data())); }
+    inline iterator	iat (size_type i)			{ assert (i <= size()); return (begin() + i); }
+    inline iterator	end (void)				{ return (iat (size())); }
+    inline const_iterator	begin (void) const		{ return (cmemlink::begin()); }
+    inline const_iterator	end (void) const		{ return (cmemlink::end()); }
+    inline const_iterator	iat (size_type i) const		{ return (cmemlink::iat (i)); }
+    size_type		writable_size (void) const		{ return (size()); }
+    inline rcself_t	operator= (const cmemlink& l)		{ cmemlink::operator= (l); return (*this); }
+    inline rcself_t	operator= (rcself_t l)			{ cmemlink::operator= (l); return (*this); }
+    inline void		link (const void* p, size_type n)	{ cmemlink::link (p, n); }
+    inline void		link (void* p, size_type n)		{ cmemlink::link (p, n); }
+    inline void		link (const cmemlink& l)		{ cmemlink::link (l); }
+    inline void		link (memlink& l)			{ cmemlink::link (l); }
+			OVERLOAD_POINTER_AND_SIZE_T_V2(link, void*)
+			OVERLOAD_POINTER_AND_SIZE_T_V2(link, const void*)
+    inline void		link (const void* first, const void* last)	{ link (first, distance (first, last)); }
+    inline void		link (void* first, void* last)		{ link (first, distance (first, last)); }
+    inline void		relink (const void* p, size_type n)	{ cmemlink::relink (p, n); }
+    inline void		relink (void* p, size_type n)		{ cmemlink::relink (p, n); }
+    inline void		copy (const cmemlink& l)		{ copy (begin(), l.cdata(), l.size()); }
+    inline void		copy (const void* p, size_type n)	{ copy (begin(), p, n); }
+    void		copy (iterator offset, const void* p, size_type n);
+    inline void		swap (memlink& l)			{ cmemlink::swap (l); }
+    void		fill (iterator start, const void* p, size_type elsize, size_type elCount = 1);
+    inline void		insert (iterator start, size_type size);
+    inline void		erase (iterator start, size_type size);
+    void		read (istream& is);
+};
+
+/// Shifts the data in the linked block from \p start to \p start + \p n.
+/// The contents of the uncovered bytes is undefined.
+inline void memlink::insert (iterator start, size_type n)
+{
+    assert (data() || !n);
+    assert (cmemlink::begin() || !n);
+    assert (start >= begin() && start + n <= end());
+    rotate (start, end() - n, end());
+}
+
+/// Shifts the data in the linked block from \p start + \p n to \p start.
+/// The contents of the uncovered bytes is undefined.
+inline void memlink::erase (iterator start, size_type n)
+{
+    assert (data() || !n);
+    assert (cmemlink::begin() || !n);
+    assert (start >= begin() && start + n <= end());
+    rotate (start, start + n, end());
+}
+
+/// Reads object \p l from stream \p is
+inline istream& operator>> (istream& is, memlink& l)
+{
+    l.read (is);
+    return (is);
+}
+
+/// Use with memlink-derived classes to allocate and link to stack space.
+#define alloca_link(m,n)	(m).link (alloca (n), (n))
+
+} // namespace ustl
+
+#endif
+
diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/mistream.cpp b/media/libdrm/mobile2/src/util/ustl-1.0/mistream.cpp
new file mode 100644
index 0000000..ad998289
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/ustl-1.0/mistream.cpp
@@ -0,0 +1,242 @@
+// This file is part of the ustl library, an STL implementation.
+//
+// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
+// This file is free software, distributed under the MIT License.
+//
+// mstream.cpp
+//
+//	Helper classes to read and write packed binary streams.
+//
+
+#include "mistream.h"
+#include "sostream.h"
+#include "ualgo.h"
+#include "uassert.h"
+#include "ustring.h"
+
+#if PLATFORM_ANDROID
+#include <stdio.h>
+#endif
+
+namespace ustl {
+
+//--------------------------------------------------------------------
+
+/// \brief Constructs a stream attached to nothing.
+/// A stream attached to nothing is not usable. Call Link() functions
+/// inherited from cmemlink to attach to some memory block.
+///
+istream::istream (void)
+: cmemlink (),
+  m_Pos (0)
+{
+}
+
+/// Attaches the stream to a block at \p p of size \p n.
+istream::istream (const void* p, size_type n)
+: cmemlink (p, n),
+  m_Pos (0)
+{
+}
+
+/// Attaches to the block pointed to by \p source.
+istream::istream (const cmemlink& source)
+: cmemlink (source),
+  m_Pos (0)
+{
+}
+
+/// Attaches to the block pointed to by source of size source.pos()
+istream::istream (const ostream& source)
+: cmemlink (source.begin(), source.pos()),
+  m_Pos (0)
+{
+}
+
+/// Swaps contents with \p is
+void istream::swap (istream& is)
+{
+    cmemlink::swap (is);
+    ::ustl::swap (m_Pos, is.m_Pos);
+}
+
+/// Checks that \p n bytes are available in the stream, or else throws.
+void istream::verify_remaining (const char* op, const char* type, size_t n) const
+{
+    if (remaining() < n)
+#if PLATFORM_ANDROID
+        printf("stream bounds exception\n");
+#else
+	throw stream_bounds_exception (op, type, pos(), n, remaining());
+#endif
+}
+
+/// Reads \p n bytes into \p buffer.
+void istream::read (void* buffer, size_type n)
+{
+#ifdef WANT_STREAM_BOUNDS_CHECKING
+    verify_remaining ("read", "binary data", n);
+#else
+    assert (remaining() >= n && "Reading past end of buffer. Make sure you are reading the right format.");
+#endif
+    copy_n (ipos(), n, reinterpret_cast<value_type*>(buffer));
+    m_Pos += n;
+}
+
+/// Reads a null-terminated string into \p str.
+void istream::read_strz (string& str)
+{
+    const_iterator zp = find (ipos(), end(), string::c_Terminator);
+    if (zp == end())
+	zp = ipos();
+    const size_type strl = distance (ipos(), zp);
+    str.resize (strl);
+    copy (ipos(), zp, str.begin());
+    m_Pos += strl + 1;
+}
+
+/// Reads at most \p n bytes into \p s.
+istream::size_type istream::readsome (void* s, size_type n)
+{
+    if (remaining() < n)
+	underflow (n);
+    const size_type ntr (min (n, remaining()));
+    read (s, ntr);
+    return (ntr);
+}
+
+/// Writes all unread bytes into \p os.
+void istream::write (ostream& os) const
+{
+    os.write (ipos(), remaining());
+}
+
+/// Writes the object to stream \p os.
+void istream::text_write (ostringstream& os) const
+{
+    os.write (ipos(), remaining());
+}
+
+/// Links to \p p of size \p n
+void istream::unlink (void)
+{
+    cmemlink::unlink();
+    m_Pos = 0;
+}
+
+//--------------------------------------------------------------------
+
+/// \brief Constructs a stream attached to nothing.
+/// A stream attached to nothing is not usable. Call Link() functions
+/// inherited from memlink to attach to some memory block.
+///
+ostream::ostream (void)
+: memlink (),
+  m_Pos (0)
+{
+}
+
+/// Attaches the stream to a block at \p p of size \p n.
+ostream::ostream (void* p, size_type n)
+: memlink (p, n),
+  m_Pos (0)
+{
+}
+
+/// Attaches to the block pointed to by \p source.
+ostream::ostream (const memlink& source)
+: memlink (source),
+  m_Pos (0)
+{
+}
+
+/// Links to \p p of size \p n
+void ostream::unlink (void)
+{
+    memlink::unlink();
+    m_Pos = 0;
+}
+
+/// Checks that \p n bytes are available in the stream, or else throws.
+void ostream::verify_remaining (const char* op, const char* type, size_t n) const
+{
+    if (remaining() < n)
+#if PLATFORM_ANDROID
+        printf("stream bounds exception\n");
+#else
+	throw stream_bounds_exception (op, type, pos(), n, remaining());
+#endif
+}
+
+/// Aligns the write pointer on \p grain. The skipped bytes are zeroed.
+void ostream::align (size_type grain)
+{
+    const size_t r = pos() % grain;
+    size_t nb = grain - r;
+    if (!r) nb = 0;
+#ifdef WANT_STREAM_BOUNDS_CHECKING
+    verify_remaining ("align", "padding", nb);
+#else
+    assert (remaining() >= nb && "Buffer overrun. Check your stream size calculations.");
+#endif
+    fill_n (ipos(), nb, '\x0');
+    m_Pos += nb;
+}
+
+/// Writes \p n bytes from \p buffer.
+void ostream::write (const void* buffer, size_type n)
+{
+#ifdef WANT_STREAM_BOUNDS_CHECKING
+    verify_remaining ("write", "binary data", n);
+#else
+    assert (remaining() >= n && "Buffer overrun. Check your stream size calculations.");
+#endif
+    copy_n (const_iterator(buffer), n, ipos());
+    m_Pos += n;
+}
+
+/// Writes \p str as a null-terminated string.
+void ostream::write_strz (const char* str)
+{
+    write (str, strlen(str));
+    iwrite (string::c_Terminator);
+}
+
+/// Writes all available data from \p is.
+void ostream::read (istream& is)
+{
+    is.write (*this);
+    is.seek (is.size());
+}
+
+/// Writes all written data to \p os.
+void ostream::text_write (ostringstream& os) const
+{
+    os.write (begin(), pos());
+}
+
+/// Inserts an empty area of \p size, at \p start.
+void ostream::insert (iterator start, size_type s)
+{
+    memlink::insert (start, s);
+    m_Pos += s;
+}
+
+/// Erases an area of \p size, at \p start.
+void ostream::erase (iterator start, size_type s)
+{
+    m_Pos -= s;
+    memlink::erase (start, s);
+}
+
+/// Swaps with \p os
+void ostream::swap (ostream& os)
+{
+    memlink::swap (os);
+    ::ustl::swap (m_Pos, os.m_Pos);
+}
+
+//--------------------------------------------------------------------
+
+} // namespace ustl
+
diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/mistream.h b/media/libdrm/mobile2/src/util/ustl-1.0/mistream.h
new file mode 100644
index 0000000..0a7aee7
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/ustl-1.0/mistream.h
@@ -0,0 +1,293 @@
+// This file is part of the ustl library, an STL implementation.
+//
+// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
+// This file is free software, distributed under the MIT License.
+//
+// mistream.h
+//
+#ifndef MISTREAM_H_103AEF1F266C04AA1A817D38705983DA
+#define MISTREAM_H_103AEF1F266C04AA1A817D38705983DA
+
+#include "memlink.h"
+#include "uexception.h"
+#include "strmsize.h"
+#include "uassert.h"
+#include "utf8.h"
+#include "uios.h"
+#ifdef WANT_STREAM_BOUNDS_CHECKING
+    #include <typeinfo>
+#endif
+
+namespace ustl {
+
+class ostream;
+class memlink;
+class string;
+
+/// \class istream mistream.h ustl.h
+/// \ingroup BinaryStreams
+///
+/// \brief Helper class to read packed binary streams.
+/// 
+/// This class contains a set of functions to read integral types from an
+/// unstructured memory block. Unpacking binary file data can be done this
+/// way, for instance. aligning the data is your responsibility, and can
+/// be accomplished by proper ordering of reads and by calling the align()
+/// function. Unaligned access is usually slower by orders of magnitude and,
+/// on some architectures, such as PowerPC, can cause your program to crash.
+/// Therefore, all read functions have asserts to check alignment.
+/// Overreading the end of the stream will also cause a crash (an assert in
+/// debug builds). Oh, and don't be intimidated by the size of the inlines
+/// here. In the assembly code the compiler will usually chop everything down
+/// to five instructions each.
+/// 
+/// Alignment rules for your objects:
+///	- Assume your writes start off 4-byte aligned.
+///	- After completion, \ref istream::align the stream to at least 4.
+///	- If data portability between 32bit and 64bit platforms is important
+///	(it often is not, in config files and the like), ensure you are always
+///	using fixed-size types and are aligning to a fixed grain. Avoid writing
+///	8-byte types, and if you do, manually align before doing so.
+///	- Non-default alignment is allowed if you plan to frequently write this
+///	object in array form and alignment would be costly. For example, an
+///	array of uint16_t-sized objects may leave the stream uint16_t aligned
+///	as long as you know about it and will default-align the stream after
+///	writing the array (note: \ref vector will already do this for you)
+/// 
+/// Example code:
+/// \code
+///	memblock b;
+///	b.read_file ("test.file");
+///	ostream is (b);
+///	is >> boolVar >> ios::talign<int>();
+///	is >> intVar >> floatVar;
+///	is.read (binaryData, binaryDataSize);
+///	is.align();
+/// \endcode
+///
+class istream : public cmemlink, public ios_base {
+public:
+			istream (void);
+			istream (const void* p, size_type n);
+    explicit		istream (const cmemlink& source);
+    explicit		istream (const ostream& source);
+    inline iterator	end (void) const			{ return (cmemlink::end()); }
+    inline void		link (const void* p, size_type n)	{ cmemlink::link (p, n); }
+    inline void		link (const cmemlink& l)		{ cmemlink::link (l.cdata(), l.readable_size()); }
+    inline void		link (const void* f, const void* l)	{ cmemlink::link (f, l); }
+			OVERLOAD_POINTER_AND_SIZE_T_V2(link, const void*)
+    inline void		relink (const void* p, size_type n)	{ cmemlink::relink (p, n); m_Pos = 0; }
+    inline void		relink (const cmemlink& l)		{ relink (l.cdata(), l.readable_size()); }
+    virtual void	unlink (void);
+    inline virtual size_type	underflow (size_type = 1)	{ return (remaining()); }
+    inline uoff_t	pos (void) const	{ return (m_Pos); }
+    inline const_iterator ipos (void) const	{ return (begin() + pos()); }
+    inline size_type	remaining (void) const	{ return (size() - pos()); }
+    inline void		seek (uoff_t newPos);
+    inline void		iseek (const_iterator newPos);
+    inline void		skip (size_type nBytes);
+    inline bool		aligned (size_type grain = c_DefaultAlignment) const;
+    void		verify_remaining (const char* op, const char* type, size_t n) const;
+    inline size_type	align_size (size_type grain = c_DefaultAlignment) const;
+    inline void		align (size_type grain = c_DefaultAlignment);
+    void		swap (istream& is);
+    void		read (void* buffer, size_type size);
+    inline void		read (memlink& buf)	{ read (buf.begin(), buf.writable_size()); }
+    void		read_strz (string& str);
+    size_type		readsome (void* s, size_type n);
+    inline void		read (istream&)			{ }
+    void		write (ostream& os) const;
+    void		text_write (ostringstream& os) const;
+    inline size_t	stream_size (void) const	{ return (remaining()); }
+    template <typename T>
+    inline void		iread (T& v);
+    inline void		ungetc (void)		{ seek (pos() - 1); }
+    inline off_t	tellg (void) const	{ return (pos()); }
+    inline void		seekg (off_t p, seekdir d = beg);
+private:
+    uoff_t		m_Pos;		///< The current read position.
+};
+
+//----------------------------------------------------------------------
+
+template <typename T, typename Stream>
+inline size_t required_stream_size (T, const Stream&) { return (1); }
+template <typename T>
+inline size_t required_stream_size (T v, const istream&) { return (stream_size_of(v)); }
+
+template <typename Stream>
+inline bool stream_at_eof (const Stream& stm)	{ return (stm.eof()); }
+template <>
+inline bool stream_at_eof (const istream&)	{ return (false); }
+
+/// \class istream_iterator
+/// \ingroup BinaryStreamIterators
+///
+/// \brief An iterator over an istream to use with uSTL algorithms.
+///
+template <typename T, typename Stream = istream>
+class istream_iterator {
+public:
+    typedef T			value_type;
+    typedef ptrdiff_t		difference_type;
+    typedef const value_type*	pointer;
+    typedef const value_type&	reference;
+    typedef size_t		size_type;
+public:
+				istream_iterator (void)		: m_pis (NULL), m_v() {}
+    explicit			istream_iterator (Stream& is)	: m_pis (&is), m_v() { Read(); }
+ 				istream_iterator (const istream_iterator& i)	: m_pis (i.m_pis), m_v (i.m_v) {}
+    /// Reads and returns the next value.
+    inline const T&		operator* (void)	{ return (m_v); }
+    inline istream_iterator&	operator++ (void)	{ Read(); return (*this); }
+    inline istream_iterator&	operator-- (void)	{ m_pis->seek (m_pis->pos() - 2 * stream_size_of(m_v)); return (operator++()); }
+    inline istream_iterator	operator++ (int)	{ istream_iterator old (*this); operator++(); return (old); }
+    inline istream_iterator	operator-- (int)	{ istream_iterator old (*this); operator--(); return (old); }
+    inline istream_iterator&	operator+= (size_type n)	{ while (n--) operator++(); return (*this); }
+    inline istream_iterator&	operator-= (size_type n)	{ m_pis->seek (m_pis->pos() - (n + 1) * stream_size_of(m_v)); return (operator++()); }
+    inline istream_iterator	operator- (size_type n) const			{ istream_iterator result (*this); return (result -= n); }
+    inline difference_type	operator- (const istream_iterator& i) const	{ return (distance (i.m_pis->pos(), m_pis->pos()) / stream_size_of(m_v)); }
+    inline bool			operator== (const istream_iterator& i) const	{ return ((!m_pis && !i.m_pis) || (m_pis && i.m_pis && m_pis->pos() == i.m_pis->pos())); }
+    inline bool			operator< (const istream_iterator& i) const	{ return (!i.m_pis || (m_pis && m_pis->pos() < i.m_pis->pos())); }
+private:
+    void Read (void)
+    {
+	if (!m_pis)
+	    return;
+	const size_t rs (required_stream_size (m_v, *m_pis));
+	if (m_pis->remaining() < rs && m_pis->underflow (rs) < rs) {
+	    m_pis = NULL;
+	    return;
+	}
+	*m_pis >> m_v;
+	if (stream_at_eof (*m_pis))
+	    m_pis = NULL;
+    }
+private:
+    Stream*	m_pis;		///< The host stream.
+    T		m_v;		///< Last read value; cached to be returnable as a const reference.
+};
+
+//----------------------------------------------------------------------
+
+/// Sets the current read position to \p newPos
+inline void istream::seek (uoff_t newPos)
+{
+#ifdef WANT_STREAM_BOUNDS_CHECKING
+    if (newPos > size())
+	throw stream_bounds_exception ("seekg", "byte", pos(), newPos - pos(), size());
+#else
+    assert (newPos <= size());
+#endif
+    m_Pos = newPos;
+}
+
+/// Sets the current read position to \p newPos
+inline void istream::iseek (const_iterator newPos)
+{
+    seek (distance (begin(), newPos));
+}
+
+/// Sets the current write position to \p p based on \p d.
+inline void istream::seekg (off_t p, seekdir d)
+{
+    switch (d) {
+	case beg:	seek (p); break;
+	case cur:	seek (pos() + p); break;
+	case ios_base::end:	seek (size() - p); break;
+    }
+}
+
+/// Skips \p nBytes without reading them.
+inline void istream::skip (size_type nBytes)
+{
+    seek (pos() + nBytes);
+}
+
+/// Returns the number of bytes to skip to be aligned on \p grain.
+inline istream::size_type istream::align_size (size_type grain) const
+{
+    return (Align (pos(), grain) - pos());
+}
+
+/// Returns \c true if the read position is aligned on \p grain
+inline bool istream::aligned (size_type grain) const
+{
+    assert (uintptr_t(begin()) % grain == 0 && "Streams should be attached aligned at the maximum element grain to avoid bus errors.");
+    return (pos() % grain == 0);
+}
+
+/// aligns the read position on \p grain
+inline void istream::align (size_type grain)
+{
+    seek (Align (pos(), grain));
+}
+
+/// Reads type T from the stream via a direct pointer cast.
+template <typename T>
+inline void istream::iread (T& v)
+{
+    assert (aligned (alignof (T())));
+#ifdef WANT_STREAM_BOUNDS_CHECKING
+    verify_remaining ("read", typeid(v).name(), sizeof(T));
+#else
+    assert (remaining() >= sizeof(T));
+#endif
+    v = *reinterpret_cast<const T*>(ipos());
+    m_Pos += sizeof(T);
+}
+
+#define ISTREAM_OPERATOR(type)	\
+inline istream&	operator>> (istream& is, type& v)	{ is.iread(v); return (is); }
+
+template <typename T>
+ISTREAM_OPERATOR(T*)
+ISTREAM_OPERATOR(int8_t)
+ISTREAM_OPERATOR(uint8_t)
+ISTREAM_OPERATOR(int16_t)
+ISTREAM_OPERATOR(uint16_t)
+ISTREAM_OPERATOR(int32_t)
+ISTREAM_OPERATOR(uint32_t)
+ISTREAM_OPERATOR(float)
+ISTREAM_OPERATOR(double)
+ISTREAM_OPERATOR(wchar_t)
+#if SIZE_OF_BOOL == SIZE_OF_CHAR
+ISTREAM_OPERATOR(bool)
+#else
+inline istream&	operator>> (istream& is, bool& v)
+{ uint8_t v8; is.iread (v8); v = v8; return (is); }
+#endif
+#if HAVE_THREE_CHAR_TYPES
+ISTREAM_OPERATOR(char)
+#endif
+#if HAVE_INT64_T
+ISTREAM_OPERATOR(int64_t)
+ISTREAM_OPERATOR(uint64_t)
+#endif
+#if SIZE_OF_LONG == SIZE_OF_INT
+ISTREAM_OPERATOR(long)
+ISTREAM_OPERATOR(unsigned long)
+#endif
+#if HAVE_LONG_LONG && (!HAVE_INT64_T || SIZE_OF_LONG_LONG > 8)
+ISTREAM_OPERATOR(long long)
+ISTREAM_OPERATOR(unsigned long long)
+#endif
+
+//----------------------------------------------------------------------
+
+typedef istream_iterator<utf8subchar_t> istream_iterator_for_utf8;
+typedef utf8in_iterator<istream_iterator_for_utf8> utf8istream_iterator;
+
+/// Returns a UTF-8 adaptor reading from \p is.
+inline utf8istream_iterator utf8in (istream& is)
+{
+    istream_iterator_for_utf8 si (is);
+    return (utf8istream_iterator (si));
+}
+
+//----------------------------------------------------------------------
+
+} // namespace ustl
+
+#endif
+
diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/mostream.h b/media/libdrm/mobile2/src/util/ustl-1.0/mostream.h
new file mode 100644
index 0000000..fb04196
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/ustl-1.0/mostream.h
@@ -0,0 +1,260 @@
+// This file is part of the ustl library, an STL implementation.
+//
+// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
+// This file is free software, distributed under the MIT License.
+//
+// mostream.h
+
+#ifndef MOSTREAM_H_24A8C5397E0848216573E5670930FC9A
+#define MOSTREAM_H_24A8C5397E0848216573E5670930FC9A
+
+#include "memlink.h"
+#include "uassert.h"
+#include "uexception.h"
+#include "utf8.h"
+#include "uios.h"
+#include <typeinfo>
+
+namespace ustl {
+
+class istream;
+class string;
+
+/// \class ostream mostream.h ustl.h
+/// \ingroup BinaryStreams
+///
+/// \brief Helper class to write packed binary streams.
+///
+/// This class contains a set of functions to write integral types into an
+/// unstructured memory block. Packing binary file data can be done this
+/// way, for instance. aligning the data is your responsibility, and can
+/// be accomplished by proper ordering of writes and by calling \ref ostream::align.
+/// Unaligned access is usually slower by orders of magnitude and,
+/// on some architectures, such as PowerPC, can cause your program to crash.
+/// Therefore, all write functions have asserts to check alignment.
+/// See \ref istream documentation for rules on designing your data format.
+/// Overwriting the end of the stream will also cause a crash (an assert in
+/// debug builds). Oh, and don't be intimidated by the size of the inlines
+/// here. In the assembly code the compiler will usually chop everything down
+/// to five instructions each.
+///
+/// Example code:
+/// \code
+///     memblock b;
+///     ostream os (b);
+///     os << boolVar << ios::talign<int>();
+///     os << intVar << floatVar;
+///     os.write (binaryData, binaryDataSize);
+///     os.align();
+///     b.resize (os.pos());
+///	b.write_file ("test.file");
+/// \endcode
+///
+class ostream : public memlink, public ios_base {
+public:
+			ostream (void);
+			ostream (void* p, size_type n);
+    explicit		ostream (const memlink& source);
+    inline iterator	end (void)			{ return (memlink::end()); }
+    inline const_iterator	end (void) const	{ return (memlink::end()); }
+    inline void		seek (uoff_t newPos);
+    inline void		iseek (const_iterator newPos);
+    inline void		skip (size_type nBytes);
+    inline uoff_t	pos (void) const	{ return (m_Pos); }
+    inline iterator	ipos (void)		{ return (begin() + pos()); }
+    inline const_iterator ipos (void) const	{ return (begin() + pos()); }
+    inline size_type	remaining (void) const;
+    inline bool		aligned (size_type grain = c_DefaultAlignment) const;
+    void		verify_remaining (const char* op, const char* type, size_t n) const;
+    inline size_type	align_size (size_type grain = c_DefaultAlignment) const;
+    void		align (size_type grain = c_DefaultAlignment);
+    void		write (const void* buffer, size_type size);
+    inline void		write (const cmemlink& buf);
+    void		write_strz (const char* str);
+    void		read (istream& is);
+    inline void		write (ostream& os) const	{ os.write (begin(), pos()); }
+    void		text_write (ostringstream& os) const;
+    inline size_t	stream_size (void) const	{ return (pos()); }
+    void		insert (iterator start, size_type size);
+    void		erase (iterator start, size_type size);
+    void		swap (ostream& os);
+    template <typename T>
+    inline void		iwrite (const T& v);
+    inline virtual size_type	overflow (size_type = 1){ return (remaining()); }
+    virtual void	unlink (void);
+    inline void		link (void* p, size_type n)	{ memlink::link (p, n); }
+    inline void		link (memlink& l)		{ memlink::link (l.data(), l.writable_size()); }
+    inline void		link (void* f, void* l)		{ memlink::link (f, l); }
+			OVERLOAD_POINTER_AND_SIZE_T_V2(link, void*)
+    inline void		relink (void* p, size_type n)	{ memlink::relink (p, n); m_Pos = 0; }
+    inline void		relink (memlink& l)		{ relink (l.data(), l.writable_size()); }
+    inline void		seekp (off_t p, seekdir d = beg);
+    inline off_t	tellp (void) const		{ return (pos()); }
+protected:
+    inline void		SetPos (uoff_t newPos)		{ m_Pos = newPos; }
+private:
+    uoff_t		m_Pos;	///< Current write position.
+};
+
+//----------------------------------------------------------------------
+
+/// \class ostream_iterator mostream.h ustl.h
+/// \ingroup BinaryStreamIterators
+///
+/// \brief An iterator over an ostream to use with uSTL algorithms.
+///
+template <typename T, typename Stream = ostream>
+class ostream_iterator {
+public:
+    typedef T			value_type;
+    typedef ptrdiff_t		difference_type;
+    typedef value_type*		pointer;
+    typedef value_type&		reference;
+    typedef ostream::size_type	size_type;
+public:
+    inline explicit		ostream_iterator (Stream& os)
+				    : m_Os (os) {}
+    inline			ostream_iterator (const ostream_iterator& iter)
+				    : m_Os (iter.m_Os) {} 
+    /// Writes \p v into the stream.
+    inline ostream_iterator&	operator= (const T& v)
+				    { m_Os << v; return (*this); }
+    inline ostream_iterator&	operator* (void) { return (*this); }
+    inline ostream_iterator&	operator++ (void) { return (*this); }
+    inline ostream_iterator	operator++ (int) { return (*this); }
+    inline ostream_iterator&	operator+= (size_type n) { m_Os.skip (n); return (*this); }
+    inline bool			operator== (const ostream_iterator& i) const
+				    { return (m_Os.pos() == i.m_Os.pos()); }
+    inline bool			operator< (const ostream_iterator& i) const
+				    { return (m_Os.pos() < i.m_Os.pos()); }
+private:
+    Stream&	m_Os;
+};
+
+//----------------------------------------------------------------------
+
+typedef ostream_iterator<utf8subchar_t> ostream_iterator_for_utf8;
+typedef utf8out_iterator<ostream_iterator_for_utf8> utf8ostream_iterator;
+
+/// Returns a UTF-8 adaptor writing to \p os.
+inline utf8ostream_iterator utf8out (ostream& os)
+{
+    ostream_iterator_for_utf8 si (os);
+    return (utf8ostream_iterator (si));
+}
+
+//----------------------------------------------------------------------
+
+/// Move the write pointer to \p newPos
+inline void ostream::seek (uoff_t newPos)
+{
+#ifdef WANT_STREAM_BOUNDS_CHECKING
+    if (newPos > size())
+	throw stream_bounds_exception ("seekp", "byte", pos(), newPos - pos(), size());
+#else
+    assert (newPos <= size());
+#endif
+    SetPos (newPos);
+}
+
+/// Sets the current write position to \p newPos
+inline void ostream::iseek (const_iterator newPos)
+{
+    seek (distance (begin(), const_cast<iterator>(newPos)));
+}
+
+/// Sets the current write position to \p p based on \p d.
+inline void ostream::seekp (off_t p, seekdir d)
+{
+    switch (d) {
+	case beg:	seek (p); break;
+	case cur:	seek (pos() + p); break;
+	case ios_base::end:	seek (size() - p); break;
+    }
+}
+
+/// Skips \p nBytes without writing anything.
+inline void ostream::skip (size_type nBytes)
+{
+    seek (pos() + nBytes);
+}
+
+/// Returns number of bytes remaining in the write buffer.
+inline ostream::size_type ostream::remaining (void) const
+{
+    return (size() - pos());
+}
+
+/// Returns \c true if the write pointer is aligned on \p grain
+inline bool ostream::aligned (size_type grain) const
+{
+    assert (uintptr_t(begin()) % grain == 0 && "Streams should be attached aligned at the maximum element grain to avoid bus errors.");
+    return (pos() % grain == 0);
+}
+
+/// Returns the number of bytes to skip to be aligned on \p grain.
+inline ostream::size_type ostream::align_size (size_type grain) const
+{
+    return (Align (pos(), grain) - pos());
+}
+
+/// Writes the contents of \p buf into the stream as a raw dump.
+inline void ostream::write (const cmemlink& buf)
+{
+    write (buf.begin(), buf.size());
+}
+
+/// Writes type T into the stream via a direct pointer cast.
+template <typename T>
+inline void ostream::iwrite (const T& v)
+{
+    assert (aligned (alignof (v)));
+#ifdef WANT_STREAM_BOUNDS_CHECKING
+    verify_remaining ("write", typeid(v).name(), sizeof(T));
+#else
+    assert (remaining() >= sizeof(T));
+#endif
+    *reinterpret_cast<T*>(ipos()) = v;
+    SetPos (pos() + sizeof(T));
+}
+
+#define OSTREAM_OPERATOR(type)	\
+inline ostream&	operator<< (ostream& os, type v)	{ os.iwrite(v); return (os); }
+
+template <typename T>
+OSTREAM_OPERATOR(T*)
+OSTREAM_OPERATOR(int8_t)
+OSTREAM_OPERATOR(uint8_t)
+OSTREAM_OPERATOR(int16_t)
+OSTREAM_OPERATOR(uint16_t)
+OSTREAM_OPERATOR(int32_t)
+OSTREAM_OPERATOR(uint32_t)
+OSTREAM_OPERATOR(float)
+OSTREAM_OPERATOR(double)
+OSTREAM_OPERATOR(wchar_t)
+#if SIZE_OF_BOOL == SIZE_OF_CHAR
+OSTREAM_OPERATOR(bool)
+#else
+inline ostream&	operator<< (ostream& os, bool v)
+{ os.iwrite (uint8_t(v)); return (os); }
+#endif
+#if HAVE_THREE_CHAR_TYPES
+OSTREAM_OPERATOR(char)
+#endif
+#if HAVE_INT64_T
+OSTREAM_OPERATOR(int64_t)
+OSTREAM_OPERATOR(uint64_t)
+#endif
+#if SIZE_OF_LONG == SIZE_OF_INT
+OSTREAM_OPERATOR(long)
+OSTREAM_OPERATOR(unsigned long)
+#endif
+#if HAVE_LONG_LONG && (!HAVE_INT64_T || SIZE_OF_LONG_LONG > 8)
+OSTREAM_OPERATOR(long long)
+OSTREAM_OPERATOR(unsigned long long)
+#endif
+
+} // namespace ustl
+
+#endif
+
diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/ofstream.cpp b/media/libdrm/mobile2/src/util/ustl-1.0/ofstream.cpp
new file mode 100644
index 0000000..0948a4d3
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/ustl-1.0/ofstream.cpp
@@ -0,0 +1,163 @@
+// This file is part of the ustl library, an STL implementation.
+//
+// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
+// This file is free software, distributed under the MIT License.
+//
+// ofstream.cc
+//
+
+#include "ofstream.h"
+#include "ustring.h"
+#include "uexception.h"
+#include <unistd.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+namespace ustl {
+
+//----------------------------------------------------------------------
+
+ifstream cin  (STDIN_FILENO);
+ofstream cout (STDOUT_FILENO);
+ofstream cerr (STDERR_FILENO);
+
+//----------------------------------------------------------------------
+
+/// Default constructor.
+ofstream::ofstream (void)
+: ostringstream (),
+  m_File ()
+{
+    reserve (255);
+}
+
+/// Constructs a stream for writing to \p Fd.
+ofstream::ofstream (int Fd)
+: ostringstream (),
+  m_File (Fd)
+{
+    clear (m_File.rdstate());
+    reserve (255);
+}
+
+/// Constructs a stream for writing to \p filename.
+ofstream::ofstream (const char* filename, openmode mode)
+: ostringstream (),
+  m_File (filename, mode)
+{
+    clear (m_File.rdstate());
+}
+
+/// Default destructor.
+ofstream::~ofstream (void)
+{
+#if PLATFORM_ANDROID
+    flush();
+#else /* !PLATFORM_ANDROID */
+    try { flush(); } catch (...) {}
+#endif
+}
+
+/// Flushes the buffer to the file.
+void ofstream::flush (void)
+{
+    while (pos() && overflow (remaining()));
+    m_File.sync();
+    clear (m_File.rdstate());
+}
+
+/// Seeks to \p p based on \p d.
+void ofstream::seekp (off_t p, seekdir d)
+{
+    flush();
+    m_File.seekp (p, d);
+    clear (m_File.rdstate());
+}
+
+/// Called when more buffer space (\p n bytes) is needed.
+ofstream::size_type ofstream::overflow (size_type n)
+{
+    if (eof() || (n > remaining() && n < capacity() - pos()))
+	return (ostringstream::overflow (n));
+    size_type bw = m_File.write (cdata(), pos());
+    clear (m_File.rdstate());
+    erase (begin(), bw);
+    if (remaining() < n)
+	ostringstream::overflow (n);
+    return (remaining());
+}
+
+//----------------------------------------------------------------------
+
+/// Constructs a stream to read from \p Fd.
+ifstream::ifstream (int Fd)
+: istringstream (),
+  m_Buffer (255),
+  m_File (Fd)
+{
+    link (m_Buffer.data(), 0U);
+}
+
+/// Constructs a stream to read from \p filename.
+ifstream::ifstream (const char* filename, openmode mode)
+: istringstream (),
+  m_Buffer (255),
+  m_File (filename, mode)
+{
+    clear (m_File.rdstate());
+    link (m_Buffer.data(), 0U);
+}
+
+/// Reads at least \p n more bytes and returns available bytes.
+ifstream::size_type ifstream::underflow (size_type n)
+{
+    if (eof())
+	return (istringstream::underflow (n));
+
+    const ssize_t freeSpace = m_Buffer.size() - pos();
+    const ssize_t neededFreeSpace = max (n, m_Buffer.size() / 2);
+    const size_t oughtToErase = Align (max (0, neededFreeSpace - freeSpace));
+    const size_t nToErase = min (pos(), oughtToErase);
+    m_Buffer.memlink::erase (m_Buffer.begin(), nToErase);
+    const uoff_t oldPos (pos() - nToErase);
+
+    size_type br = oldPos;
+    if (m_Buffer.size() - br < n) {
+	m_Buffer.resize (br + neededFreeSpace);
+	link (m_Buffer.data(), 0U);
+    }
+    cout.flush();
+
+    while (br - oldPos < n && m_File.good())
+	br += m_File.readsome (m_Buffer.begin() + br, m_Buffer.size() - br);
+    clear (m_File.rdstate());
+
+    m_Buffer[br] = string::c_Terminator;
+    link (m_Buffer.data(), br);
+    seek (oldPos);
+    return (remaining());
+}
+
+/// Flushes the input.
+void ifstream::sync (void)
+{
+    istringstream::sync();
+    underflow (0U);
+    m_File.sync();
+    clear (m_File.rdstate());
+}
+
+/// Seeks to \p p based on \p d.
+void ifstream::seekg (off_t p, seekdir d)
+{
+    m_Buffer.clear();
+    link (m_Buffer);
+    m_File.seekg (p, d);
+    clear (m_File.rdstate());
+}
+
+//----------------------------------------------------------------------
+
+} // namespace ustl
+
diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/ofstream.h b/media/libdrm/mobile2/src/util/ustl-1.0/ofstream.h
new file mode 100644
index 0000000..7780833
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/ustl-1.0/ofstream.h
@@ -0,0 +1,82 @@
+// This file is part of the ustl library, an STL implementation.
+//
+// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
+// This file is free software, distributed under the MIT License.
+//
+// ofstream.h
+//
+
+#ifndef FDOSTREAM_H_5E27FC3D530BF3CA04D6C73F5700EECC
+#define FDOSTREAM_H_5E27FC3D530BF3CA04D6C73F5700EECC
+
+#include "sistream.h"
+#include "sostream.h"
+#include "fstream.h"
+
+namespace ustl {
+
+/// \class ofstream fdostream.h ustl.h
+/// \ingroup DeviceStreams
+/// \brief A string stream that writes to an fd. Implements cout and cerr.
+class ofstream : public ostringstream {
+public:
+			ofstream (void);
+    explicit		ofstream (int Fd);
+    explicit		ofstream (const char* filename, openmode mode = out);
+    virtual	       ~ofstream (void);
+    inline void		open (const char* filename, openmode mode = out) { m_File.open (filename, mode); clear (m_File.rdstate()); }
+    inline void		close (void)		{ m_File.close(); clear (m_File.rdstate()); }
+    inline bool		is_open (void) const	{ return (m_File.is_open()); }
+    inline iostate	exceptions (iostate v)	{ ostringstream::exceptions(v); return (m_File.exceptions(v)); }
+    inline void		setstate (iostate v)	{ ostringstream::setstate(v); m_File.setstate(v); }
+    inline void		clear (iostate v = goodbit)	{ ostringstream::clear(v); m_File.clear(v); }
+    inline off_t	tellp (void) const		{ return (m_File.tellp() + ostringstream::tellp()); }
+    inline int		fd (void) const			{ return (m_File.fd()); }
+    inline void		stat (struct stat& rs) const	{ m_File.stat (rs); }
+    inline void		set_nonblock (bool v = true)	{ m_File.set_nonblock (v); }
+    inline int		ioctl (const char* rname, int request, long argument = 0)	{ return (m_File.ioctl (rname, request, argument)); }
+    inline int		ioctl (const char* rname, int request, int argument)		{ return (m_File.ioctl (rname, request, argument)); }
+    inline int		ioctl (const char* rname, int request, void* argument)		{ return (m_File.ioctl (rname, request, argument)); }
+    void		seekp (off_t p, seekdir d = beg);
+    void		flush (void);
+    virtual size_type	overflow (size_type n = 1);
+private:
+    fstream		m_File;
+};
+
+/// \class ifstream fdostream.h ustl.h
+/// \ingroup DeviceStreams
+/// \brief A string stream that reads from an fd. Implements cin.
+class ifstream : public istringstream {
+public:
+			ifstream (void);
+    explicit		ifstream (int Fd);
+    explicit		ifstream (const char* filename, openmode mode = in);
+    inline void		open (const char* filename, openmode mode = in)	{ m_File.open (filename, mode); clear (m_File.rdstate()); }
+    inline void		close (void)		{ m_File.close(); clear (m_File.rdstate()); }
+    inline bool		is_open (void) const	{ return (m_File.is_open()); }
+    inline iostate	exceptions (iostate v)	{ istringstream::exceptions(v); return (m_File.exceptions(v)); }
+    inline void		setstate (iostate v)	{ istringstream::setstate(v); m_File.setstate(v); }
+    inline void		clear (iostate v = goodbit)	{ istringstream::clear(v); m_File.clear(v); }
+    inline off_t	tellg (void) const		{ return (m_File.tellg() - remaining()); }
+    inline int		fd (void) const			{ return (m_File.fd()); }
+    inline void		stat (struct stat& rs) const	{ m_File.stat (rs); }
+    inline void		set_nonblock (bool v = true)	{ m_File.set_nonblock (v); }
+    inline int		ioctl (const char* rname, int request, long argument = 0)	{ return (m_File.ioctl (rname, request, argument)); }
+    inline int		ioctl (const char* rname, int request, int argument)		{ return (m_File.ioctl (rname, request, argument)); }
+    inline int		ioctl (const char* rname, int request, void* argument)		{ return (m_File.ioctl (rname, request, argument)); }
+    void		seekg (off_t p, seekdir d = beg);
+    void		sync (void);
+    virtual size_type	underflow (size_type n = 1);
+private:
+    string		m_Buffer;
+    fstream		m_File;
+};
+
+extern ofstream cout, cerr;
+extern ifstream cin;
+
+} // namespace ustl
+
+#endif
+
diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/simd.h b/media/libdrm/mobile2/src/util/ustl-1.0/simd.h
new file mode 100644
index 0000000..950efc2
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/ustl-1.0/simd.h
@@ -0,0 +1,465 @@
+// This file is part of the ustl library, an STL implementation.
+//
+// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
+// This file is free software, distributed under the MIT License.
+//
+/// \file simd.h
+/// \brief SIMD-type algorithms, with hardware acceleration, if available.
+///
+/// All algorithms are container-based because iterator syntax is just too
+/// damn verbose and because the specializations need to be able to tell
+/// how many elements are in the container in order to choose proper SIMD
+/// instruction set (i.e.: 4 floats select SSE, while 2 floats select 3dNow!)
+/// Specializations are only for the tuple template because the container
+/// must be of a fixed and compile-time-known size for the compiler to be
+/// able to choose the specialization.
+///
+
+#ifndef SIMD_H_39BE2D970DF4BD00508CCFFB482496F9
+#define SIMD_H_39BE2D970DF4BD00508CCFFB482496F9
+
+#include "uassert.h"
+#include "ulimits.h"
+#if HAVE_MATH_H
+    #include <math.h>
+#endif
+
+#if PLATFORM_ANDROID
+#include <stdio.h>
+#undef CPU_HAS_MMX
+#endif
+
+namespace ustl {
+namespace simd {
+
+//----------------------------------------------------------------------
+// Generic algorithms
+//----------------------------------------------------------------------
+
+/// Applies \p op to each element in \p op1.
+template <typename Ctr, typename UnaryOperation>
+inline void packop (Ctr& op1, UnaryOperation op)
+{
+    foreach (typename Ctr::iterator, i, op1)
+	op (*i);
+}
+
+/// Applies \p op to each element in \p op1 and \p op2 and stores in \p op2.
+template <typename Ctr, typename BinaryOperation>
+inline void packop (const Ctr& op1, Ctr& op2, BinaryOperation op)
+{
+    assert (op2.size() <= op1.size());
+    typename Ctr::const_iterator i1 (op1.begin());
+    typename Ctr::iterator i2 (op2.begin());
+    for (; i2 != op2.end(); ++i1, ++i2)
+	*i2 = op (*i2, *i1);
+}
+
+/// Applies \p op to corresponding elements in \p op1 and \p op2 and stores in \p result.
+template <typename Ctr, typename BinaryOperation>
+inline void packop (const Ctr& op1, const Ctr& op2, Ctr& result, BinaryOperation op)
+{
+    assert (op1.size() <= op2.size() && op1.size() <= result.size());
+    passign (op1, result);
+    packop (op2, result);
+}
+
+/// Copies \p op1 into \p result.
+template <typename Ctr>
+inline void passign (const Ctr& op1, Ctr& result)
+{
+    assert (op1.size() <= result.size());
+    typename Ctr::iterator d (result.begin());
+    foreach (typename Ctr::const_iterator, s, op1)
+	*d++ = *s;
+}
+
+/// Copies \p result.size() elements from \p op1 to \p result.
+template <typename Ctr>
+inline void ipassign (typename Ctr::const_iterator op1, Ctr& result)
+{
+    foreach (typename Ctr::iterator, d, result)
+	*d = *op1++;
+}
+
+template <typename Ctr1, typename Ctr2, typename ConvertFunction>
+inline void pconvert (const Ctr1& op1, Ctr2& op2, ConvertFunction f)
+{
+    assert (op1.size() <= op2.size());
+    typename Ctr1::const_iterator i1 (op1.begin());
+    typename Ctr2::iterator i2 (op2.begin());
+    for (; i1 != op1.end(); ++i1, ++i2)
+	*i2 = f (*i1);
+}
+
+// Functionoids for SIMD operations, like saturation arithmetic, shifts, etc.
+STD_BINARY_FUNCTOR (fpadds, T, ((b > numeric_limits<T>::max() - a) ? numeric_limits<T>::max() : a + b))
+STD_BINARY_FUNCTOR (fpsubs, T, ((a < numeric_limits<T>::min() + b) ? numeric_limits<T>::min() : a - b))
+STD_BINARY_FUNCTOR (fpshl,  T, (a << b))
+STD_BINARY_FUNCTOR (fpshr,  T, (a >> b))
+STD_BINARY_FUNCTOR (fpmin,  T, (min (a, b)))
+STD_BINARY_FUNCTOR (fpmax,  T, (max (a, b)))
+STD_BINARY_FUNCTOR (fpavg,  T, ((a + b + 1) / 2))
+STD_CONVERSION_FUNCTOR (fcast, (D(a)))
+#if HAVE_MATH_H
+STD_UNARY_FUNCTOR (fpreciprocal,T, (1 / a))
+STD_UNARY_FUNCTOR (fpsqrt,	T, (reset_mmx(), T (sqrt (a))))
+STD_UNARY_FUNCTOR (fprecipsqrt,	T, (reset_mmx(), 1 / T(sqrt (a))))
+STD_UNARY_FUNCTOR (fsin,	T, (reset_mmx(), T (sin (a))))
+STD_UNARY_FUNCTOR (fcos,	T, (reset_mmx(), T (cos (a))))
+STD_UNARY_FUNCTOR (ftan,	T, (reset_mmx(), T (tan (a))))
+#if HAVE_RINTF
+STD_CONVERSION_FUNCTOR (fround, (reset_mmx(), D(rintf(a))))
+#else
+STD_CONVERSION_FUNCTOR (fround, (reset_mmx(), D(rint(a))))
+#endif
+template <> inline int32_t fround<double,int32_t>::operator()(const double& a) const { reset_mmx(); return (int32_t(rint(a))); }
+#endif
+template <> inline float fpavg<float>::operator()(const float& a, const float& b) const { return ((a + b) / 2); }
+template <> inline double fpavg<double>::operator()(const double& a, const double& b) const { return ((a + b) / 2); }
+
+#define SIMD_PACKEDOP1(name, operation)		\
+template <typename Ctr>				\
+inline void name (Ctr& op1)			\
+{						\
+    typedef typename Ctr::value_type value_t;	\
+    packop (op1, operation<value_t>());		\
+}
+#define SIMD_PACKEDOP2(name, operation)		\
+template <typename Ctr>				\
+inline void name (const Ctr& op1, Ctr& op2)	\
+{						\
+    typedef typename Ctr::value_type value_t;	\
+    packop (op1, op2, operation<value_t>());	\
+}
+#define SIMD_PACKEDOP3(name, operation)			\
+template <typename Ctr>					\
+inline void name (const Ctr& op1, const Ctr& op2, Ctr& result)	\
+{							\
+    typedef typename Ctr::value_type value_t;		\
+    packop (op1, op2, result, operation<value_t>());	\
+}
+#define SIMD_SINGLEOP1(name, operation)		\
+template <typename T>				\
+inline T name (T op)				\
+{						\
+    operation<T> obj;				\
+    return (obj(op));				\
+}
+#define SIMD_CONVERTOP(name, operation)		\
+template <typename Ctr1, typename Ctr2>		\
+inline void name (const Ctr1& op1, Ctr2& op2)	\
+{						\
+    typedef typename Ctr1::value_type value1_t;	\
+    typedef typename Ctr2::value_type value2_t;	\
+    pconvert (op1, op2, operation<value1_t, value2_t>());\
+}
+
+SIMD_PACKEDOP2 (padd, plus)
+SIMD_PACKEDOP2 (psub, minus)
+SIMD_PACKEDOP2 (pmul, multiplies)
+SIMD_PACKEDOP2 (pdiv, divides)
+SIMD_PACKEDOP2 (pand, bitwise_and)
+SIMD_PACKEDOP2 (por, bitwise_or)
+SIMD_PACKEDOP2 (pxor, bitwise_xor)
+SIMD_PACKEDOP2 (pshl, fpshl)
+SIMD_PACKEDOP2 (pshr, fpshr)
+SIMD_PACKEDOP2 (psubs, fpsubs)
+SIMD_PACKEDOP2 (pmin, fpmin)
+SIMD_PACKEDOP2 (pmax, fpmax)
+SIMD_PACKEDOP2 (pavg, fpavg)
+
+SIMD_PACKEDOP3 (padd, plus)
+SIMD_PACKEDOP3 (psub, minus)
+SIMD_PACKEDOP3 (pmul, multiplies)
+SIMD_PACKEDOP3 (pdiv, divides)
+SIMD_PACKEDOP3 (pand, bitwise_and)
+SIMD_PACKEDOP3 (por, bitwise_or)
+SIMD_PACKEDOP3 (pxor, bitwise_xor)
+SIMD_PACKEDOP3 (pshl, fpshl)
+SIMD_PACKEDOP3 (pshr, fpshr)
+SIMD_PACKEDOP3 (padds, fpadds)
+SIMD_PACKEDOP3 (psubs, fpsubs)
+SIMD_PACKEDOP3 (pmin, fpmin)
+SIMD_PACKEDOP3 (pmax, fpmax)
+SIMD_PACKEDOP3 (pavg, fpavg)
+
+#if HAVE_MATH_H
+SIMD_PACKEDOP1 (precip, fpreciprocal)
+SIMD_PACKEDOP1 (psqrt, fpsqrt)
+SIMD_PACKEDOP1 (precipsqrt, fprecipsqrt)
+SIMD_PACKEDOP1 (psin, fsin)
+SIMD_PACKEDOP1 (pcos, fcos)
+SIMD_PACKEDOP1 (ptan, ftan)
+
+SIMD_SINGLEOP1 (srecip, fpreciprocal)
+SIMD_SINGLEOP1 (ssqrt, fpsqrt)
+SIMD_SINGLEOP1 (srecipsqrt, fprecipsqrt)
+SIMD_SINGLEOP1 (ssin, fsin)
+SIMD_SINGLEOP1 (scos, fcos)
+SIMD_SINGLEOP1 (stan, ftan)
+
+SIMD_CONVERTOP (pround, fround)
+
+template <typename T> inline int32_t sround (T op) { fround<T,int32_t> obj; return (obj (op)); }
+#endif
+
+#undef SIMD_SINGLEOP1
+#undef SIMD_PACKEDOP3
+#undef SIMD_PACKEDOP2
+#undef SIMD_PACKEDOP1
+
+//----------------------------------------------------------------------
+// Vector types to cast tuple data to
+//----------------------------------------------------------------------
+
+#if HAVE_VECTOR_EXTENSIONS && __GNUC__ >= 4
+#define VECTOR_ATTRIBUTE(mode,vs)	__attribute__((vector_size(vs)))
+#else
+#define VECTOR_ATTRIBUTE(mode,vs)
+#endif
+typedef uint8_t v8qi_t VECTOR_ATTRIBUTE (V8QI,8);
+typedef uint16_t v4hi_t VECTOR_ATTRIBUTE (V4HI,8);
+typedef uint16_t v8hi_t VECTOR_ATTRIBUTE (V8HI,16);
+typedef uint32_t v2si_t VECTOR_ATTRIBUTE (V2SI,8);
+typedef uint32_t v4si_t VECTOR_ATTRIBUTE (V4SI,16);
+#if HAVE_INT64_T
+typedef uint64_t v1di_t VECTOR_ATTRIBUTE (V1DI,8);
+#endif
+typedef float v2sf_t VECTOR_ATTRIBUTE (V2SF,8);
+typedef float v4sf_t VECTOR_ATTRIBUTE (V4SF,16);
+typedef double v2df_t VECTOR_ATTRIBUTE (V2DF,16);
+#undef VECTOR_ATTRIBUTE
+
+//----------------------------------------------------------------------
+// Hardware accelerated specializations
+//----------------------------------------------------------------------
+
+#define SIMD_PKOP2_SPEC(n, type, optype)	\
+template <>					\
+inline void packop (const tuple<n,type>& oin, tuple<n,type>& oout, optype<type>)
+#define SIMD_PASSIGN_SPEC(n, type)		\
+template <>					\
+inline void passign (const tuple<n,type>& oin, tuple<n,type>& oout)
+#define SIMD_IPASSIGN_SPEC(n, type)		\
+template <>					\
+inline void ipassign (tuple<n,type>::const_iterator oin, tuple<n,type>& oout)
+#define SIMD_CONVERT_SPEC(n, type1, type2, optype)	\
+template <>					\
+inline void pconvert (const tuple<n,type1>& oin, tuple<n,type2>& oout, optype<type1,type2>)
+
+#if CPU_HAS_MMX
+#define STD_MMX_ARGS	"=m"(oout[0]) : "m"(oin[0]) : "mm0", "st", "memory"
+#define DBL_MMX_ARGS	"=m"(oout[0]), "=m"(oout[2]) : "m"(oin[0]), "m"(oin[2]) : "mm0", "mm1", "st", "st(1)", "memory"
+#define MMX_PKOP2_SPEC(n,type,optype,instruction)	\
+SIMD_PKOP2_SPEC(n,type,optype)		\
+{ asm ("movq %0, %%mm0\n\t" #instruction " %1, %%mm0\n\tmovq %%mm0, %0" : STD_MMX_ARGS); reset_mmx(); }
+#define MMX_DBL_PKOP2_SPEC(n,type,optype,instruction)	\
+SIMD_PKOP2_SPEC(n,type,optype)		\
+{ asm ("movq %0, %%mm0\n\tmovq %1, %%mm1\n\t" #instruction " %2, %%mm0\n\t" #instruction " %3, %%mm1\n\tmovq %%mm0, %0\n\tmovq %%mm1, %1" : DBL_MMX_ARGS); reset_mmx(); }
+#define MMX_PASSIGN_SPEC(n,type)	\
+SIMD_PASSIGN_SPEC(n,type)		\
+{ asm ("movq %1, %%mm0\n\tmovq %%mm0, %0" : STD_MMX_ARGS); reset_mmx(); }
+#define MMX_DBL_PASSIGN_SPEC(n,type)	\
+SIMD_PASSIGN_SPEC(n,type)		\
+{ asm ("movq %2, %%mm0\n\tmovq %3, %%mm1\n\tmovq %%mm0, %0\n\tmovq %%mm1, %1" : DBL_MMX_ARGS); reset_mmx(); }
+#define MMX_IPASSIGN_SPEC(n,type)	\
+SIMD_IPASSIGN_SPEC(n,type)		\
+{ asm ("movq %1, %%mm0\n\tmovq %%mm0, %0" : STD_MMX_ARGS); reset_mmx(); }
+#define MMX_DBL_IPASSIGN_SPEC(n,type)	\
+SIMD_IPASSIGN_SPEC(n,type)		\
+{ asm ("movq %2, %%mm0\n\tmovq %3, %%mm1\n\tmovq %%mm0, %0\n\tmovq %%mm1, %1" : DBL_MMX_ARGS); reset_mmx(); }
+
+MMX_PASSIGN_SPEC(8,uint8_t)
+MMX_PKOP2_SPEC(8,uint8_t,plus,paddb)
+MMX_PKOP2_SPEC(8,uint8_t,minus,psubb)
+MMX_PKOP2_SPEC(8,uint8_t,bitwise_and,pand)
+MMX_PKOP2_SPEC(8,uint8_t,bitwise_or,por)
+MMX_PKOP2_SPEC(8,uint8_t,bitwise_xor,pxor)
+MMX_PKOP2_SPEC(8,uint8_t,fpadds,paddusb)
+MMX_PKOP2_SPEC(8,uint8_t,fpsubs,psubusb)
+
+MMX_PASSIGN_SPEC(8,int8_t)
+MMX_PKOP2_SPEC(8,int8_t,plus,paddb)
+MMX_PKOP2_SPEC(8,int8_t,minus,psubb)
+MMX_PKOP2_SPEC(8,int8_t,bitwise_and,pand)
+MMX_PKOP2_SPEC(8,int8_t,bitwise_or,por)
+MMX_PKOP2_SPEC(8,int8_t,bitwise_xor,pxor)
+MMX_PKOP2_SPEC(8,int8_t,fpadds,paddsb)
+MMX_PKOP2_SPEC(8,int8_t,fpsubs,psubsb)
+
+MMX_PASSIGN_SPEC(4,uint16_t)
+MMX_PKOP2_SPEC(4,uint16_t,plus,paddw)
+MMX_PKOP2_SPEC(4,uint16_t,minus,psubw)
+MMX_PKOP2_SPEC(4,uint16_t,bitwise_and,pand)
+MMX_PKOP2_SPEC(4,uint16_t,bitwise_or,por)
+MMX_PKOP2_SPEC(4,uint16_t,bitwise_xor,pxor)
+/// \todo psllw does not work like other operations, it uses the first element for shift count.
+//MMX_PKOP2_SPEC(4,uint16_t,fpshl,psllw)
+//MMX_PKOP2_SPEC(4,uint16_t,fpshr,psrlw)
+MMX_PKOP2_SPEC(4,uint16_t,fpadds,paddusw)
+MMX_PKOP2_SPEC(4,uint16_t,fpsubs,psubusw)
+
+MMX_PASSIGN_SPEC(4,int16_t)
+MMX_PKOP2_SPEC(4,int16_t,plus,paddw)
+MMX_PKOP2_SPEC(4,int16_t,minus,psubw)
+MMX_PKOP2_SPEC(4,int16_t,bitwise_and,pand)
+MMX_PKOP2_SPEC(4,int16_t,bitwise_or,por)
+MMX_PKOP2_SPEC(4,int16_t,bitwise_xor,pxor)
+//MMX_PKOP2_SPEC(4,int16_t,fpshl,psllw)
+//MMX_PKOP2_SPEC(4,int16_t,fpshr,psrlw)
+MMX_PKOP2_SPEC(4,int16_t,fpadds,paddsw)
+MMX_PKOP2_SPEC(4,int16_t,fpsubs,psubsw)
+
+MMX_PASSIGN_SPEC(2,uint32_t)
+MMX_PKOP2_SPEC(2,uint32_t,plus,paddd)
+MMX_PKOP2_SPEC(2,uint32_t,minus,psubd)
+MMX_PKOP2_SPEC(2,uint32_t,bitwise_and,pand)
+MMX_PKOP2_SPEC(2,uint32_t,bitwise_or,por)
+MMX_PKOP2_SPEC(2,uint32_t,bitwise_xor,pxor)
+//MMX_PKOP2_SPEC(2,uint32_t,fpshl,pslld)
+//MMX_PKOP2_SPEC(2,uint32_t,fpshr,psrld)
+
+MMX_PASSIGN_SPEC(2,int32_t)
+MMX_PKOP2_SPEC(2,int32_t,plus,paddd)
+MMX_PKOP2_SPEC(2,int32_t,minus,psubd)
+MMX_PKOP2_SPEC(2,int32_t,bitwise_and,pand)
+MMX_PKOP2_SPEC(2,int32_t,bitwise_or,por)
+MMX_PKOP2_SPEC(2,int32_t,bitwise_xor,pxor)
+//MMX_PKOP2_SPEC(2,int32_t,fpshl,pslld)
+//MMX_PKOP2_SPEC(2,int32_t,fpshr,psrld)
+
+MMX_DBL_PKOP2_SPEC(4,uint32_t,plus,paddd)
+MMX_DBL_PKOP2_SPEC(4,uint32_t,minus,psubd)
+MMX_DBL_PKOP2_SPEC(4,uint32_t,bitwise_and,pand)
+MMX_DBL_PKOP2_SPEC(4,uint32_t,bitwise_or,por)
+MMX_DBL_PKOP2_SPEC(4,uint32_t,bitwise_xor,pxor)
+//MMX_DBL_PKOP2_SPEC(2,uint32_t,fpshl,pslld)
+//MMX_DBL_PKOP2_SPEC(2,uint32_t,fpshr,psrld)
+
+MMX_DBL_PKOP2_SPEC(4,int32_t,plus,paddd)
+MMX_DBL_PKOP2_SPEC(4,int32_t,minus,psubd)
+MMX_DBL_PKOP2_SPEC(4,int32_t,bitwise_and,pand)
+MMX_DBL_PKOP2_SPEC(4,int32_t,bitwise_or,por)
+MMX_DBL_PKOP2_SPEC(4,int32_t,bitwise_xor,pxor)
+//MMX_DBL_PKOP2_SPEC(2,int32_t,fpshl,pslld)
+//MMX_DBL_PKOP2_SPEC(2,int32_t,fpshr,psrld)
+
+#if CPU_HAS_SSE || CPU_HAS_3DNOW
+MMX_PKOP2_SPEC(8,uint8_t,fpavg,pavgb)
+MMX_PKOP2_SPEC(8,int8_t,fpavg,pavgb)
+MMX_PKOP2_SPEC(4,uint16_t,fpavg,pavgw)
+MMX_PKOP2_SPEC(4,int16_t,fpavg,pavgw)
+MMX_PKOP2_SPEC(8,uint8_t,fpmin,pminub)
+MMX_PKOP2_SPEC(8,uint8_t,fpmax,pmaxub)
+MMX_PKOP2_SPEC(4,int16_t,fpmax,pmaxsw)
+MMX_PKOP2_SPEC(4,int16_t,fpmin,pminsw)
+#endif // CPU_HAS_SSE || CPU_HAS_3DNOW
+
+#if CPU_HAS_3DNOW
+MMX_PASSIGN_SPEC(2,float)
+MMX_PKOP2_SPEC(2,float,plus,pfadd)
+MMX_PKOP2_SPEC(2,float,minus,pfsub)
+MMX_PKOP2_SPEC(2,float,multiplies,pfmul)
+MMX_PKOP2_SPEC(2,float,fpmin,pfmin)
+MMX_PKOP2_SPEC(2,float,fpmax,pfmax)
+#ifndef CPU_HAS_SSE
+MMX_DBL_PKOP2_SPEC(4,float,plus,pfadd)
+MMX_DBL_PKOP2_SPEC(4,float,minus,pfsub)
+MMX_DBL_PKOP2_SPEC(4,float,multiplies,pfmul)
+MMX_DBL_PKOP2_SPEC(4,float,fpmin,pfmin)
+MMX_DBL_PKOP2_SPEC(4,float,fpmax,pfmax)
+#endif
+#endif // CPU_HAS_3DNOW
+
+MMX_IPASSIGN_SPEC(8,uint8_t)
+MMX_IPASSIGN_SPEC(4,uint16_t)
+MMX_IPASSIGN_SPEC(2,uint32_t)
+MMX_IPASSIGN_SPEC(2,float)
+
+#ifndef CPU_HAS_SSE
+MMX_DBL_PASSIGN_SPEC(4,float)
+MMX_DBL_PASSIGN_SPEC(4,uint32_t)
+MMX_DBL_PASSIGN_SPEC(4,int32_t)
+MMX_DBL_IPASSIGN_SPEC(4,float)
+MMX_DBL_IPASSIGN_SPEC(4,uint32_t)
+MMX_DBL_IPASSIGN_SPEC(4,int32_t)
+#endif
+
+#undef MMX_IPASSIGN_SPEC
+#undef MMX_PASSIGN_SPEC
+#undef MMX_PKOP2_SPEC
+#undef STD_MMX_ARGS
+#endif // CPU_HAS_MMX
+
+#if CPU_HAS_SSE
+#define STD_SSE_ARGS	"=m"(oout[0]) : "m"(oin[0]) : "xmm0", "memory"
+#define SSE_PKOP2_SPEC(n,type,optype,instruction)	\
+SIMD_PKOP2_SPEC(n,type,optype)		\
+{ asm ("movups %0, %%xmm0\n\tmovups %1, %%xmm1\n\t" #instruction " %%xmm1, %%xmm0\n\tmovups %%xmm0, %0" : STD_SSE_ARGS);}
+#define SSE_PASSIGN_SPEC(n,type)			\
+SIMD_PASSIGN_SPEC(n,type)		\
+{ asm ("movups %1, %%xmm0\n\tmovups %%xmm0, %0" : STD_SSE_ARGS);}
+#define SSE_IPASSIGN_SPEC(n,type)	\
+SIMD_IPASSIGN_SPEC(n,type)		\
+{ asm ("movups %1, %%xmm0\n\tmovups %%xmm0, %0" : STD_SSE_ARGS);}
+SSE_PASSIGN_SPEC(4,float)
+SSE_PASSIGN_SPEC(4,int32_t)
+SSE_PASSIGN_SPEC(4,uint32_t)
+SSE_PKOP2_SPEC(4,float,plus,addps)
+SSE_PKOP2_SPEC(4,float,minus,subps)
+SSE_PKOP2_SPEC(4,float,multiplies,mulps)
+SSE_PKOP2_SPEC(4,float,divides,divps)
+SSE_PKOP2_SPEC(4,float,bitwise_and,andps)
+SSE_PKOP2_SPEC(4,float,bitwise_or,orps)
+SSE_PKOP2_SPEC(4,float,bitwise_xor,xorps)
+SSE_PKOP2_SPEC(4,float,fpmax,maxps)
+SSE_PKOP2_SPEC(4,float,fpmin,minps)
+
+SIMD_CONVERT_SPEC(4,float,int32_t,fround) {
+    asm ("cvtps2pi %2, %%mm0\n\t"
+	 "cvtps2pi %3, %%mm1\n\t"
+	 "movq %%mm0, %0\n\t"
+	 "movq %%mm1, %1"
+	 : DBL_MMX_ARGS);
+    reset_mmx();
+}
+SIMD_CONVERT_SPEC(4,int32_t,float,fround) {
+    asm ("cvtpi2ps %2, %%xmm0\n\t"
+	 "shufps $0x4E,%%xmm0,%%xmm0\n\t"
+	 "cvtpi2ps %1, %%xmm0\n\t"
+	 "movups %%xmm0, %0"
+	 : "=m"(oout[0]) : "m"(oin[0]), "m"(oin[2]) : "xmm0", "memory");
+}
+template <> inline int32_t fround<float,int32_t>::operator()(const float& a) const {
+    register int32_t rv;
+    asm ("movss %1, %%xmm0\n\t"
+	 "cvtss2si %%xmm0, %0"
+	 : "=r"(rv) : "m"(a) : "xmm0" );
+    return (rv);
+}
+template <> inline uint32_t fround<float,uint32_t>::operator()(const float& a) const {
+    register uint32_t rv;
+    asm ("movss %1, %%xmm0\n\t"
+	 "cvtss2si %%xmm0, %0"
+	 : "=r"(rv) : "m"(a) : "xmm0" );
+    return (rv);
+}
+
+SSE_IPASSIGN_SPEC(4,float)
+SSE_IPASSIGN_SPEC(4,int32_t)
+SSE_IPASSIGN_SPEC(4,uint32_t)
+
+#undef SSE_IPASSIGN_SPEC
+#undef SSE_PASSIGN_SPEC
+#undef SSE_PKOP2_SPEC
+#undef STD_SSE_ARGS
+#endif // CPU_HAS_SSE
+
+#undef SIMD_PACKEDOP_SPEC
+
+} // namespace simd
+} // namespace ustl
+
+#endif
+
diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/sistream.cpp b/media/libdrm/mobile2/src/util/ustl-1.0/sistream.cpp
new file mode 100644
index 0000000..8a20ddf
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/ustl-1.0/sistream.cpp
@@ -0,0 +1,237 @@
+// This file is part of the ustl library, an STL implementation.
+//
+// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
+// This file is free software, distributed under the MIT License.
+//
+// sistream.cc
+//
+
+#include "sistream.h"
+#include "sostream.h"
+#include "uassert.h"
+#include "ustring.h"
+
+namespace ustl {
+
+const char ios_base::c_DefaultDelimiters [istringstream::c_MaxDelimiters] = " \t\n\r;:,.?";
+
+/// Default constructor.
+istringstream::istringstream (void)
+: istream (),
+  m_Base (0)
+{
+    set_delimiters (c_DefaultDelimiters);
+}
+
+istringstream::istringstream (const void* p, size_type n)
+: istream (),
+  m_Base (0)
+{
+    link (p, n);
+    set_delimiters (c_DefaultDelimiters);
+}
+
+istringstream::istringstream (const cmemlink& source)
+: istream (),
+  m_Base (0)
+{
+    link (source);
+    set_delimiters (c_DefaultDelimiters);
+}
+
+/// Sets delimiters to the contents of \p delimiters.
+void istringstream::set_delimiters (const char* delimiters)
+{
+    fill (VectorRange (m_Delimiters), '\0');
+    strncpy (m_Delimiters, delimiters, VectorSize(m_Delimiters)-1);
+}
+
+inline bool istringstream::is_delimiter (char c) const
+{
+    return (memchr (m_Delimiters, c, VectorSize(m_Delimiters)-1));
+}
+
+char istringstream::skip_delimiters (void)
+{
+    char c = m_Delimiters[0];
+    while (is_delimiter(c) && (remaining() || underflow()))
+	istream::iread (c);
+    return (c);
+}
+
+void istringstream::iread (int8_t& v)
+{
+    v = skip_delimiters();
+}
+
+typedef istringstream::iterator issiter_t;
+template <typename T>
+inline void str_to_num (issiter_t i, issiter_t* iend, uint8_t base, T& v)
+    { v = strtol (i, const_cast<char**>(iend), base); }
+template <> inline void str_to_num (issiter_t i, issiter_t* iend, uint8_t, double& v)
+    { v = strtod (i, const_cast<char**>(iend)); }
+#ifdef HAVE_LONG_LONG
+template <> inline void str_to_num (issiter_t i, issiter_t* iend, uint8_t base, long long& v)
+    { v = strtoll (i, const_cast<char**>(iend), base); }
+#endif
+
+template <typename T>
+inline void istringstream::read_number (T& v)
+{
+    v = 0;
+    if (skip_delimiters() == m_Delimiters[0])
+	return;
+    ungetc();
+    iterator ilast;
+    do {
+	str_to_num<T> (ipos(), &ilast, m_Base, v);
+    } while (ilast == end() && underflow());
+    skip (distance (ipos(), ilast));
+}
+
+void istringstream::iread (int32_t& v)		{ read_number (v); }
+void istringstream::iread (double& v)		{ read_number (v); } 
+#if HAVE_INT64_T
+void istringstream::iread (int64_t& v)		{ read_number (v); }
+#endif
+#if HAVE_LONG_LONG && (!HAVE_INT64_T || SIZE_OF_LONG_LONG > 8)
+void istringstream::iread (long long& v)	{ read_number (v); }
+#endif
+
+void istringstream::iread (wchar_t& v)
+{
+    if ((v = skip_delimiters()) == wchar_t(m_Delimiters[0]))
+	return;
+    size_t cs = Utf8SequenceBytes (v) - 1;
+    if (remaining() >= cs || underflow(cs) >= cs) {
+	ungetc();
+	v = *utf8in (ipos());
+	skip (cs + 1);
+    }
+}
+
+void istringstream::iread (bool& v)
+{
+    static const char tf[2][8] = { "false", "true" };
+    char c = skip_delimiters();
+    v = (c == 't' || c == '1');
+    if (c != tf[v][0])
+	return;
+    for (const char* tv = tf[v]; c == *tv && (remaining() || underflow()); ++tv)
+	istream::iread (c);
+    ungetc();
+}
+
+void istringstream::iread (string& v)
+{
+    v.clear();
+    char prevc, quoteChar = 0, c = skip_delimiters();
+    if (c == '\"' || c == '\'')
+	quoteChar = c;
+    else
+	v += c;
+    while (remaining() || underflow()) {
+	prevc = c;
+	istream::iread (c);
+	if (!quoteChar && is_delimiter(c))
+	    break;
+	if (prevc == '\\') {
+	    switch (c) {
+		case 't':	c = '\t'; break;
+		case 'n':	c = '\n'; break;
+		case 'r':	c = '\r'; break;
+		case 'b':	c = '\b'; break;
+		case 'E':	c = 27;   break; // ESC sequence
+		case '\"':	c = '\"'; break;
+		case '\'':	c = '\''; break;
+		case '\\':	c = '\\'; break;
+	    };
+	    v.end()[-1] = c;
+	} else {
+	    if (c == quoteChar)
+		break;
+	    v += c;
+	}
+    }
+}
+
+void istringstream::read (void* buffer, size_type sz)
+{
+    if (remaining() < sz && underflow(sz) < sz)
+#ifdef WANT_STREAM_BOUNDS_CHECKING
+	verify_remaining ("read", "", sz);
+#else
+	assert (remaining() >= size());
+#endif
+    istream::read (buffer, sz);
+}
+
+void istringstream::read (memlink& buf)
+{
+    if (remaining() < buf.size() && underflow(buf.size()) < buf.size())
+#ifdef WANT_STREAM_BOUNDS_CHECKING
+	verify_remaining ("read", "", buf.size());
+#else
+	assert (remaining() >= buf.size());
+#endif
+    istream::read (buf);
+}
+
+/// Reads one character from the stream.
+int istringstream::get (void)
+{
+    int8_t v = 0;
+    if (remaining() || underflow())
+	istream::iread (v);
+    return (v);
+}
+
+/// Reads characters into \p s until \p delim is found (but not stored or extracted)
+void istringstream::get (string& s, char delim)
+{
+    getline (s, delim);
+    if (!s.empty() && pos() > 0 && ipos()[-1] == delim)
+	ungetc();
+}
+
+/// Reads characters into \p p,n until \p delim is found (but not stored or extracted)
+void istringstream::get (char* p, size_type n, char delim)
+{
+    assert (p && !n && "A non-empty buffer is required by this implementation");
+    string s;
+    get (s, delim);
+    const size_t ntc (min (n - 1, s.size()));
+    memcpy (p, s.data(), ntc);
+    p[ntc] = 0;
+}
+
+/// Reads characters into \p s until \p delim is extracted (but not stored)
+void istringstream::getline (string& s, char delim)
+{
+    char oldDelim [VectorSize(m_Delimiters)];
+    copy (VectorRange (m_Delimiters), oldDelim);
+    fill (VectorRange (m_Delimiters), '\0');
+    m_Delimiters[0] = delim;
+    iread (s);
+    copy (VectorRange (oldDelim), m_Delimiters);
+}
+
+/// Reads characters into \p p,n until \p delim is extracted (but not stored)
+void istringstream::getline (char* p, size_type n, char delim)
+{
+    assert (p && !n && "A non-empty buffer is required by this implementation");
+    string s;
+    getline (s, delim);
+    const size_t ntc (min (n - 1, s.size()));
+    memcpy (p, s.data(), ntc);
+    p[ntc] = 0;
+}
+
+/// Extract until \p delim or \p n chars have been read.
+void istringstream::ignore (size_type n, char delim)
+{
+    while (n-- && (remaining() || underflow()) && get() != delim);
+}
+
+} // namespace ustl
+
diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/sistream.h b/media/libdrm/mobile2/src/util/ustl-1.0/sistream.h
new file mode 100644
index 0000000..924f43b
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/ustl-1.0/sistream.h
@@ -0,0 +1,133 @@
+// This file is part of the ustl library, an STL implementation.
+//
+// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
+// This file is free software, distributed under the MIT License.
+//
+// sistream.h
+//
+
+#ifndef SISTREAM_H_0CCA102229A49F5D65EE852E62B27CE2
+#define SISTREAM_H_0CCA102229A49F5D65EE852E62B27CE2
+
+#include "mistream.h"
+#include "uassert.h"
+#include "ustring.h"
+
+namespace ustl {
+
+/// \class istringstream sistream.h ustl.h
+/// \ingroup TextStreams
+///
+/// \brief A stream that reads textual data from a memory block.
+///
+class istringstream : public istream {
+public:
+    static const size_type	c_MaxDelimiters = 16;	///< Maximum number of word delimiters.
+public:
+    				istringstream (void);
+				istringstream (const void* p, size_type n);
+    explicit			istringstream (const cmemlink& source);
+    void			iread (int8_t& v);
+    void			iread (int32_t& v);
+    void			iread (double& v);
+    void			iread (bool& v);
+    void			iread (wchar_t& v);
+    void			iread (string& v);
+#ifdef HAVE_INT64_T
+    void			iread (int64_t& v);
+#endif
+#if HAVE_LONG_LONG && (!HAVE_INT64_T || SIZE_OF_LONG_LONG > 8)
+    void			iread (long long& v);
+#endif
+    inline string		str (void) const	{ string s; s.link (*this); return (s); }
+    inline void			str (const string& s)	{ link (s); }
+    int				get (void);
+    inline void			get (char& c)	{ c = get(); }
+    void			get (char* p, size_type n, char delim = '\n');
+    void			get (string& s, char delim = '\n');
+    void			getline (char* p, size_type n, char delim = '\n');
+    void			getline (string& s, char delim = '\n');
+    void			ignore (size_type n, char delim = '\0');
+    inline char			peek (void)	{ int8_t v; iread (v); ungetc(); return (v); }
+    inline void			putback (char)	{ ungetc(); }
+    inline void			unget (void)	{ ungetc(); }
+    void			set_delimiters (const char* delimiters);
+    inline void			set_base (short base);
+    inline void			set_decimal_separator (char)	{ }
+    inline void			set_thousand_separator (char)	{ }
+    void			read (void* buffer, size_type size);
+    void			read (memlink& buf);
+    inline void			read_strz (string& str);
+    inline void			sync (void)	{ skip (remaining()); }
+protected:
+    char			skip_delimiters (void);
+private:
+    inline bool			is_delimiter (char c) const;
+    template <typename T> void	read_number (T& v);
+private:
+    char			m_Delimiters [c_MaxDelimiters];
+    uint8_t			m_Base;
+};
+
+/// Sets the numeric base used to read numbers.
+inline void istringstream::set_base (short base)
+{
+    m_Base = base;
+}
+
+/// Reads a null-terminated character stream. This is not allowed in this class.
+inline void istringstream::read_strz (string&)
+{
+    assert (!"Reading nul characters is not allowed from text streams");
+}
+
+/// Reads one type as another.
+template <typename RealT, typename CastT>
+inline void _cast_read (istringstream& is, RealT& v)
+{
+    CastT cv;
+    is.iread (cv);
+    v = RealT (cv);
+}
+
+inline istringstream& operator>> (istringstream& is, int8_t& v)	{ is.iread (v); return (is); }
+inline istringstream& operator>> (istringstream& is, int32_t& v){ is.iread (v); return (is); }
+inline istringstream& operator>> (istringstream& is, double& v)	{ is.iread (v); return (is); }
+inline istringstream& operator>> (istringstream& is, bool& v)	{ is.iread (v); return (is); }
+inline istringstream& operator>> (istringstream& is, wchar_t& v){ is.iread (v); return (is); }
+inline istringstream& operator>> (istringstream& is, string& v)	{ is.iread (v); return (is); }
+#if HAVE_INT64_T
+inline istringstream& operator>> (istringstream& is, int64_t& v){ is.iread (v); return (is); }
+#endif
+#if HAVE_LONG_LONG && (!HAVE_INT64_T || SIZE_OF_LONG_LONG > 8)
+inline istringstream& operator>> (istringstream& is, long long& v) { is.iread (v); return (is); }
+#endif
+
+#define ISTRSTREAM_CAST_OPERATOR(RealT, CastT)			\
+inline istringstream& operator>> (istringstream& is, RealT& v)	\
+{ _cast_read<RealT,CastT>(is, v); return (is); }
+
+ISTRSTREAM_CAST_OPERATOR (uint8_t,	int8_t)
+ISTRSTREAM_CAST_OPERATOR (int16_t,	int32_t)
+ISTRSTREAM_CAST_OPERATOR (uint16_t,	int32_t)
+ISTRSTREAM_CAST_OPERATOR (uint32_t,	int32_t)
+ISTRSTREAM_CAST_OPERATOR (float,	double)
+#if HAVE_THREE_CHAR_TYPES
+ISTRSTREAM_CAST_OPERATOR (char,		int8_t)
+#endif
+#if HAVE_INT64_T
+ISTRSTREAM_CAST_OPERATOR (uint64_t,	int64_t)
+#endif
+#if SIZE_OF_LONG == SIZE_OF_INT
+ISTRSTREAM_CAST_OPERATOR (long,		int)
+ISTRSTREAM_CAST_OPERATOR (unsigned long,int)
+#endif
+#if HAVE_LONG_LONG && (!HAVE_INT64_T || SIZE_OF_LONG_LONG > 8)
+ISTRSTREAM_CAST_OPERATOR (unsigned long long, long long)
+#endif
+#undef ISTRSTREAM_CAST_OPERATOR
+
+} // namespace ustl
+
+#endif
+
diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/sostream.cpp b/media/libdrm/mobile2/src/util/ustl-1.0/sostream.cpp
new file mode 100644
index 0000000..96f0976
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/ustl-1.0/sostream.cpp
@@ -0,0 +1,193 @@
+// This file is part of the ustl library, an STL implementation.
+//
+// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
+// This file is free software, distributed under the MIT License.
+//
+// sostream.h
+//
+
+#include "mistream.h"	// for istream_iterator, referenced in utf8.h
+#include "sostream.h"
+#include "uassert.h"
+#include "ulimits.h"
+#include "ustring.h"
+#include <stdio.h>
+
+namespace ustl {
+
+/// Creates an output string stream linked to the given memory area.
+ostringstream::ostringstream (void* p, size_t n)
+: ostream (),
+  m_Buffer (),
+  m_Flags (0),
+  m_Width (0),
+  m_Base (10),
+  m_Precision (2)
+{
+    link (p, n);
+}
+
+/// Creates an output string stream, initializing the buffer with v.
+ostringstream::ostringstream (const string& v)
+: ostream (),
+  m_Buffer (v),
+  m_Flags (0),
+  m_Width (0),
+  m_Base (10),
+  m_Precision (2)
+{
+    ostream::link (m_Buffer);
+}
+
+/// Copies \p s to the internal buffer.
+void ostringstream::str (const string& s)
+{
+    m_Buffer = s;
+    ostream::link (m_Buffer);
+    SetPos (m_Buffer.size());
+}
+
+/// Writes a single character into the stream.
+void ostringstream::iwrite (uint8_t v)
+{
+    if (remaining() >= 1 || overflow() >= 1)
+	ostream::iwrite (v);
+}
+
+/// Writes \p buf of size \p bufSize through the internal buffer.
+void ostringstream::write_buffer (const char* buf, size_type bufSize)
+{
+    size_type btw = 0, written = 0;
+    while ((written += btw) < bufSize && (remaining() || overflow(bufSize - written)))
+	write (buf + written, btw = min (remaining(), bufSize - written));
+}
+
+/// Simple decimal encoding of \p n into \p fmt.
+inline char* ostringstream::encode_dec (char* fmt, uint32_t n) const
+{
+    do {
+	*fmt++ = '0' + n % 10;
+    } while (n /= 10);
+    return (fmt);
+}
+
+/// Generates a sprintf format string for the given type.
+void ostringstream::fmtstring (char* fmt, const char* typestr, bool bInteger) const
+{
+    *fmt++ = '%';
+    if (m_Width)
+	fmt = encode_dec (fmt, m_Width);
+    if (m_Flags & left)
+	*fmt++ = '-';
+    if (!bInteger) {
+	*fmt++ = '.';
+	fmt = encode_dec (fmt, m_Precision);
+    }
+    while (*typestr)
+	*fmt++ = *typestr++;
+    if (bInteger) {
+	if (m_Base == 16)
+	    fmt[-1] = 'X';
+	else if (m_Base == 8)
+	    fmt[-1] = 'o';
+    } else {
+	if (m_Flags & scientific)
+	    fmt[-1] = 'E';
+    }
+    *fmt = 0;
+}
+
+/// Writes \p v into the stream as utf8
+void ostringstream::iwrite (wchar_t v)
+{
+    char buffer [8];
+    *utf8out(buffer) = v;
+    write_buffer (buffer, Utf8Bytes(v));
+}
+
+/// Writes value \p v into the stream as text.
+void ostringstream::iwrite (bool v)
+{
+    static const char tf[2][8] = { "false", "true" };
+    write_buffer (tf[v], 5 - v);
+}
+
+/// Equivalent to a vsprintf on the string.
+int ostringstream::vformat (const char* fmt, va_list args)
+{
+#if HAVE_VA_COPY
+    va_list args2;
+#else
+    #define args2 args
+    #undef __va_copy
+    #define __va_copy(x,y)
+#endif
+    size_t rv, space;
+    do {
+	space = remaining();
+	__va_copy (args2, args);
+	rv = vsnprintf (ipos(), space, fmt, args2);
+	if (ssize_t(rv) < 0)
+	    rv = space;
+    } while (rv >= space && rv < overflow(rv + 1));
+    SetPos (pos() + min (rv, space));
+    return (rv);
+}
+
+/// Equivalent to a sprintf on the string.
+int ostringstream::format (const char* fmt, ...)
+{
+    va_list args;
+    va_start (args, fmt);
+    const int rv = vformat (fmt, args);
+    va_end (args);
+    return (rv);
+}
+
+/// Links to string \p l as resizable.
+void ostringstream::link (void* p, size_t n)
+{
+    assert ((p || !n) && "The output string buffer must not be read-only");
+    ostream::link (p, n);
+    m_Buffer.link (p, n);
+}
+
+/// Writes the contents of \p buffer of \p size into the stream.
+void ostringstream::write (const void* buffer, size_type sz)
+{
+    if (remaining() < sz && overflow(sz) < sz)
+	return;
+    ostream::write (buffer, sz);
+}
+
+/// Writes the contents of \p buf into the stream.
+void ostringstream::write (const cmemlink& buf)
+{
+    if (remaining() < buf.size() && overflow(buf.size()) < buf.size())
+	return;
+    ostream::write (buf);
+}
+
+/// Flushes the internal buffer by truncating it at the current position.
+void ostringstream::flush (void)
+{
+    m_Buffer.resize (pos());
+}
+
+/// Attempts to create more output space. Returns remaining().
+ostringstream::size_type ostringstream::overflow (size_type n)
+{
+    if (n > remaining()) {
+	const uoff_t oldPos (pos());
+	m_Buffer.reserve (oldPos + n, false);
+	m_Buffer.resize (oldPos + n);
+	ostream::link (m_Buffer);
+	SetPos (oldPos);
+    }
+    verify_remaining ("write", "text", n);
+    return (remaining());
+}
+
+} // namespace ustl
+
+
diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/sostream.h b/media/libdrm/mobile2/src/util/ustl-1.0/sostream.h
new file mode 100644
index 0000000..11dc328
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/ustl-1.0/sostream.h
@@ -0,0 +1,158 @@
+// This file is part of the ustl library, an STL implementation.
+//
+// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
+// This file is free software, distributed under the MIT License.
+//
+// sostream.h
+//
+
+#ifndef SOSTREAM_H_5323DC8C26E181D43278F2F53FDCF19F
+#define SOSTREAM_H_5323DC8C26E181D43278F2F53FDCF19F
+
+#include "uassert.h"
+#include "ustring.h"
+#include "mostream.h"
+
+namespace ustl {
+
+class string;
+
+/// \class ostringstream sostream.h ustl.h
+/// \ingroup TextStreams
+///
+/// \brief This stream writes textual data into a memory block.
+///
+class ostringstream : public ostream {
+public:
+				ostringstream (const string& v = string::empty_string);
+				ostringstream (void* p, size_t n);
+    void			iwrite (uint8_t v);
+    void			iwrite (wchar_t v);
+    inline void			iwrite (int v)			{ iformat (v); }
+    inline void			iwrite (unsigned int v)		{ iformat (v); }
+    inline void			iwrite (long int v)		{ iformat (v); }
+    inline void			iwrite (unsigned long int v)	{ iformat (v); }
+    inline void			iwrite (float v)		{ iformat (v); }
+    inline void			iwrite (double v)		{ iformat (v); }
+    void			iwrite (bool v);
+    inline void			iwrite (const char* s)		{ write_buffer (s, strlen(s)); }
+    inline void			iwrite (const string& v)	{ write_buffer (v.begin(), v.size()); }
+    inline void			iwrite (fmtflags f);
+#if HAVE_LONG_LONG
+    inline void			iwrite (long long v)		{ iformat (v); }
+    inline void			iwrite (unsigned long long v)	{ iformat (v); }
+#endif
+    inline size_type		max_size (void) const		{ return (m_Buffer.max_size()); }
+    inline void			put (char c)			{ iwrite (uint8_t(c)); }
+    int				vformat (const char* fmt, va_list args);
+    int				format (const char* fmt, ...) __attribute__((__format__(__printf__, 2, 3)));
+    inline void			set_base (uint16_t b)		{ m_Base = b; }
+    inline void			set_width (uint16_t w)		{ m_Width = w; }
+    inline void			set_decimal_separator (char)	{ }
+    inline void			set_thousand_separator (char)	{ }
+    inline void			set_precision (uint16_t v)	{ m_Precision = v; }
+    void			link (void* p, size_type n);
+    inline void			link (memlink& l)		{ link (l.data(), l.writable_size()); }
+    inline const string&	str (void)			{ flush(); return (m_Buffer); }
+    void			str (const string& s);
+    void			write (const void* buffer, size_type size);
+    void			write (const cmemlink& buf);
+    inline void			write_strz (const char*)	{ assert (!"Writing nul characters into a text stream is not allowed"); }
+    void			flush (void);
+    virtual size_type		overflow (size_type n = 1);
+protected:
+    void			write_buffer (const char* buf, size_type bufSize);
+    inline void			reserve (size_type n)		{ m_Buffer.reserve (n, false); }
+    inline size_type		capacity (void) const		{ return (m_Buffer.capacity()); }
+private:
+    inline char*		encode_dec (char* fmt, uint32_t n) const;
+    void			fmtstring (char* fmt, const char* typestr, bool bInteger) const;
+    template <typename T>
+    void			iformat (T v);
+private:
+    string			m_Buffer;		///< The output buffer.
+    uint32_t			m_Flags;		///< See ios_base::fmtflags.
+    uint16_t			m_Width;		///< Field width.
+    uint8_t			m_Base;			///< Numeric base for writing numbers.
+    uint8_t			m_Precision;		///< Number of digits after the decimal separator.
+};
+
+//----------------------------------------------------------------------
+
+template <typename T>
+inline const char* printf_typestring (const T&)	{ return (""); }
+#define PRINTF_TYPESTRING_SPEC(type,str)	\
+template <> inline const char* printf_typestring (const type&)	{ return (str); }
+PRINTF_TYPESTRING_SPEC (int,		"d")
+PRINTF_TYPESTRING_SPEC (unsigned int,	"u")
+PRINTF_TYPESTRING_SPEC (long,		"ld")
+PRINTF_TYPESTRING_SPEC (unsigned long,	"lu")
+PRINTF_TYPESTRING_SPEC (float,		"f")
+PRINTF_TYPESTRING_SPEC (double,		"lf")
+#if HAVE_LONG_LONG
+PRINTF_TYPESTRING_SPEC (long long,	"lld")
+PRINTF_TYPESTRING_SPEC (unsigned long long, "llu")
+#endif
+#undef PRINTF_TYPESTRING_SPEC
+
+template <typename T>
+void ostringstream::iformat (T v)
+{
+    char fmt [16];
+    fmtstring (fmt, printf_typestring(v), numeric_limits<T>::is_integer);
+    format (fmt, v);
+}
+
+/// Sets the flag \p f in the stream.
+inline void ostringstream::iwrite (fmtflags f)
+{
+    switch (f) {
+	case oct:	set_base (8);	break;
+	case dec:	set_base (10);	break;
+	case hex:	set_base (16);	break;
+	case left:	m_Flags |= left; m_Flags &= ~right; break;
+	case right:	m_Flags |= right; m_Flags &= ~left; break;
+	default:	m_Flags |= f;	break;
+    }
+}
+
+//----------------------------------------------------------------------
+
+#define OSTRSTREAM_OPERATOR(RealT, CastT)			\
+inline ostringstream& operator<< (ostringstream& os, RealT v)	\
+{ os.iwrite ((CastT) v); return (os); }
+
+template <typename T>
+OSTRSTREAM_OPERATOR (T*,		unsigned long int)
+OSTRSTREAM_OPERATOR (const void*,	unsigned long int)
+OSTRSTREAM_OPERATOR (void*,		unsigned long int)
+OSTRSTREAM_OPERATOR (const char*,	const char*)
+OSTRSTREAM_OPERATOR (char*,		const char*)
+OSTRSTREAM_OPERATOR (uint8_t*,		const char*)
+OSTRSTREAM_OPERATOR (const uint8_t*,	const char*)
+OSTRSTREAM_OPERATOR (const string&,	const string&)
+OSTRSTREAM_OPERATOR (ios_base::fmtflags,ios_base::fmtflags)
+OSTRSTREAM_OPERATOR (int8_t,		uint8_t)
+OSTRSTREAM_OPERATOR (uint8_t,		uint8_t)
+OSTRSTREAM_OPERATOR (short int,		int)
+OSTRSTREAM_OPERATOR (unsigned short,	unsigned int)
+OSTRSTREAM_OPERATOR (int,		int)
+OSTRSTREAM_OPERATOR (unsigned int,	unsigned int)
+OSTRSTREAM_OPERATOR (long,		long)
+OSTRSTREAM_OPERATOR (unsigned long,	unsigned long)
+OSTRSTREAM_OPERATOR (float,		float)
+OSTRSTREAM_OPERATOR (double,		double)
+OSTRSTREAM_OPERATOR (bool,		bool)
+OSTRSTREAM_OPERATOR (wchar_t,		wchar_t)
+#if HAVE_THREE_CHAR_TYPES
+OSTRSTREAM_OPERATOR (char,		uint8_t)
+#endif
+#if HAVE_LONG_LONG
+OSTRSTREAM_OPERATOR (long long,		long long)
+OSTRSTREAM_OPERATOR (unsigned long long, unsigned long long)
+#endif
+
+} // namespace ustl
+
+#endif
+
diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/strmsize.h b/media/libdrm/mobile2/src/util/ustl-1.0/strmsize.h
new file mode 100644
index 0000000..5888e15
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/ustl-1.0/strmsize.h
@@ -0,0 +1,135 @@
+// This file is part of the ustl library, an STL implementation.
+//
+// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
+// This file is free software, distributed under the MIT License.
+//
+/// \file strmsize.h
+/// \brief This file contains stream_size_of functions for basic types and *STREAMABLE macros.
+/// stream_size_of functions return the size of the object's data that is written or
+/// read from a stream.
+//
+
+#ifndef STRMSIZE_H_052FF16B2D8A608761BF10333D065073
+#define STRMSIZE_H_052FF16B2D8A608761BF10333D065073
+
+#include "uassert.h"
+
+namespace ustl {
+
+/// Returns the size of the given object. Overloads for standard types are available.
+template <typename T>
+inline size_t stream_size_of (T*)	{ return (sizeof(T*));		}
+#ifndef DOXYGEN_SHOULD_IGNORE_THIS
+inline size_t stream_size_of (int8_t)	{ return (sizeof(int8_t));	}
+inline size_t stream_size_of (uint8_t)	{ return (sizeof(uint8_t));	}
+inline size_t stream_size_of (int16_t)	{ return (sizeof(int16_t));	}
+inline size_t stream_size_of (uint16_t)	{ return (sizeof(uint16_t));	}
+inline size_t stream_size_of (int32_t)	{ return (sizeof(int32_t));	}
+inline size_t stream_size_of (uint32_t)	{ return (sizeof(uint32_t));	}
+inline size_t stream_size_of (float)	{ return (sizeof(float));	}
+inline size_t stream_size_of (double)	{ return (sizeof(double));	}
+inline size_t stream_size_of (bool)	{ return (sizeof(uint8_t));	}
+inline size_t stream_size_of (wchar_t)	{ return (sizeof(wchar_t));	}
+#if HAVE_THREE_CHAR_TYPES
+inline size_t stream_size_of (char)	{ return (sizeof(char));	}
+#endif
+#if HAVE_INT64_T
+inline size_t stream_size_of (int64_t)	{ return (sizeof(int64_t));	}
+inline size_t stream_size_of (uint64_t)	{ return (sizeof(uint64_t));	}
+#endif
+#if SIZE_OF_LONG == SIZE_OF_INT
+inline size_t stream_size_of (long v)			{ return (sizeof (v));	}
+inline size_t stream_size_of (unsigned long v)		{ return (sizeof (v));	}
+#endif
+#if HAVE_LONG_LONG && (!HAVE_INT64_T || SIZE_OF_LONG_LONG > 8)
+inline size_t stream_size_of (long long v)		{ return (sizeof (v));	}
+inline size_t stream_size_of (unsigned long long v)	{ return (sizeof (v));	}
+#endif
+#endif // DOXYGEN_SHOULD_IGNORE_THIS
+
+} // namespace ustl
+
+/// Declares that T is not written to istream/ostream.
+#define NOT_STREAMABLE(T)	\
+    namespace ustl {		\
+	inline istream& operator>> (istream& is, T&)		{ return (is); }	\
+	inline ostream& operator<< (ostream& os, const T&)	{ return (os); }	\
+	inline size_t stream_size_of (const T&)			{ return (0); }		\
+    }
+
+//
+// Extra overloads in this macro are needed because it is the one used for
+// marshalling pointers. Passing a pointer to stream_size_of creates a
+// conversion ambiguity between converting to const pointer& and converting
+// to bool; the compiler always chooses the bool conversion (because it
+// requires 1 conversion instead of 2 for the other choice). There is little
+// point in adding the overloads to other macros, since they are never used
+// for pointers.
+//
+/// Declares that T is to be written as is into binary streams.
+#define INTEGRAL_STREAMABLE(T)	\
+    namespace ustl {		\
+	inline istream& operator>> (istream& is, T& v)		{ is.iread(v);  return (is); }	\
+	inline ostream& operator<< (ostream& os, const T& v)	{ os.iwrite(v); return (os); }	\
+	inline ostream& operator<< (ostream& os, T& v)		{ os.iwrite(v); return (os); }	\
+	inline size_t stream_size_of (const T& v)		{ return (sizeof(v)); }		\
+	inline size_t stream_size_of (T& v)			{ return (sizeof(v)); }		\
+    }
+
+#ifdef NDEBUG
+    #define STD_STREAMABLE_SZCHK_BEGIN
+    #define STD_STREAMABLE_SZCHK_END
+#else
+    #define STD_STREAMABLE_SZCHK_BEGIN		\
+	assert (os.aligned (alignof (v)));	\
+	const uoff_t vStart (os.pos())
+    #define STD_STREAMABLE_SZCHK_END		\
+	if (os.pos() - vStart != v.stream_size()) \
+	    throw stream_bounds_exception ("write", typeid(v).name(), vStart, os.pos() - vStart, v.stream_size())
+#endif
+
+/// Declares that T contains read, write, and stream_size methods.
+#define STD_STREAMABLE(T)	\
+    namespace ustl {		\
+	inline istream& operator>> (istream& is, T& v)		{ assert (is.aligned (alignof (v))); v.read (is);  return (is); }	\
+	inline ostream& operator<< (ostream& os, const T& v)	{ STD_STREAMABLE_SZCHK_BEGIN; v.write (os); STD_STREAMABLE_SZCHK_END; return (os); }	\
+	inline size_t stream_size_of (const T& v)		{ return (v.stream_size()); }	\
+    }
+
+/// Declares that T is to be cast into TSUB for streaming.
+#define CAST_STREAMABLE(T,TSUB)	\
+    namespace ustl {		\
+	inline istream& operator>> (istream& is, T& v)		{ TSUB sv; is >> sv; v = (T)(sv); return (is); }	\
+	inline ostream& operator<< (ostream& os, const T& v)	{ os << TSUB(v); return (os); }			\
+	inline size_t stream_size_of (const T& v)		{ return (sizeof(TSUB(v))); }				\
+    }
+
+/// Placed into a class it declares the methods required by STD_STREAMABLE. Syntactic sugar.
+#define DECLARE_STD_STREAMABLE			\
+    public:					\
+	void	read (istream& is);		\
+	void	write (ostream& os) const;	\
+	size_t	stream_size (void) const
+
+/// Declares \p T to be writable to text streams. Reading is not implemented because you should not do it.
+#define TEXT_STREAMABLE(T)	\
+    namespace ustl {		\
+	inline ostringstream& operator<< (ostringstream& os, const T& v)	\
+	    { v.text_write (os); return (os); }	\
+    }
+
+/// Specifies that \p T is printed by using it as an index into \p Names string array.
+#define LOOKUP_TEXT_STREAMABLE(T,Names,nNames)	\
+    namespace ustl {		\
+	inline ostringstream& operator<< (ostringstream& os, const T& v)	\
+	{				\
+	    if (uoff_t(v) < (nNames))	\
+		os << Names[v];		\
+	    else			\
+		os << uoff_t(v);	\
+	    return (os);		\
+	}				\
+    }
+
+#endif
+
diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/ualgo.h b/media/libdrm/mobile2/src/util/ustl-1.0/ualgo.h
new file mode 100644
index 0000000..47b66d0
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/ustl-1.0/ualgo.h
@@ -0,0 +1,677 @@
+// This file is part of the ustl library, an STL implementation.
+//
+// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
+// This file is free software, distributed under the MIT License.
+//
+// ualgo.h
+//
+// Implementation of STL algorithms.
+//
+// The function prototypes are copied
+// exactly from the SGI version of STL documentation along with comments about
+// their use. The code is NOT the same, though the functionality usually is.
+//
+
+#ifndef UALGO_H_711AB4214D417A51166694D47A662D6E
+#define UALGO_H_711AB4214D417A51166694D47A662D6E
+
+#include "upair.h"
+#include "ualgobase.h"
+#include "ufunction.h"
+#include "upredalgo.h"
+#include "umemory.h"
+#include <stdlib.h>	// for rand()
+
+namespace ustl {
+
+/// Swaps corresponding elements of [first, last) and [result,)
+/// \ingroup SwapAlgorithms
+///
+template <typename ForwardIterator1, typename ForwardIterator2>
+inline ForwardIterator2 swap_ranges (ForwardIterator1 first, ForwardIterator2 last, ForwardIterator2 result)
+{
+    for (; first != last; ++first, ++result)
+	iter_swap (first, result);
+    return (result);
+}
+
+/// Returns the first iterator i in the range [first, last) such that
+/// *i == value. Returns last if no such iterator exists. 
+/// \ingroup SearchingAlgorithms
+///
+template <typename InputIterator, typename EqualityComparable>
+inline InputIterator find (InputIterator first, InputIterator last, const EqualityComparable& value)
+{
+    while (first != last && !(*first == value))
+	++ first;
+    return (first);
+}
+
+/// Returns the first iterator such that *i == *(i + 1)
+/// \ingroup SearchingAlgorithms
+///
+template <typename ForwardIterator>
+ForwardIterator adjacent_find (ForwardIterator first, ForwardIterator last)
+{
+    if (first != last)
+	for (ForwardIterator prev = first; ++first != last; ++ prev)
+	    if (*prev == *first)
+		return (prev);
+    return (last);
+}
+
+/// Returns the pointer to the first pair of unequal elements.
+/// \ingroup SearchingAlgorithms
+///
+template <typename InputIterator>
+pair<InputIterator,InputIterator>
+mismatch (InputIterator first1, InputIterator last1, InputIterator first2)
+{
+    while (first1 != last1 && *first1 == *first2)
+	++ first1, ++ first2;
+    return (make_pair (first1, first2));
+}
+
+/// \brief Returns true if two ranges are equal.
+/// This is an extension, present in uSTL and SGI STL.
+/// \ingroup SearchingAlgorithms
+///
+template <typename InputIterator>
+inline bool equal (InputIterator first1, InputIterator last1, InputIterator first2)
+{
+    return (mismatch (first1, last1, first2).first == last1);
+}
+
+/// Count finds the number of elements in [first, last) that are equal
+/// to value. More precisely, the first version of count returns the
+/// number of iterators i in [first, last) such that *i == value.
+/// \ingroup SearchingAlgorithms
+///
+template <typename InputIterator, typename EqualityComparable>
+inline size_t count (InputIterator first, InputIterator last, const EqualityComparable& value)
+{
+    size_t total = 0;
+    for (; first != last; ++first)
+	if (*first == value)
+	    ++ total;
+    return (total);
+}
+
+///
+/// The first version of transform performs the operation op(*i) for each
+/// iterator i in the range [first, last), and assigns the result of that
+/// operation to *o, where o is the corresponding output iterator. That is,
+/// for each n such that 0 <= n < last - first, it performs the assignment
+/// *(result + n) = op(*(first + n)).
+/// The return value is result + (last - first).
+/// \ingroup MutatingAlgorithms
+/// \ingroup PredicateAlgorithms
+///
+template <typename InputIterator, typename OutputIterator, typename UnaryFunction>
+inline OutputIterator transform (InputIterator first, InputIterator last, OutputIterator result, UnaryFunction op)
+{
+    for (; first != last; ++result, ++first)
+	*result = op (*first);
+    return (result);
+}
+
+///
+/// The second version of transform is very similar, except that it uses a
+/// Binary Function instead of a Unary Function: it performs the operation
+/// op(*i1, *i2) for each iterator i1 in the range [first1, last1) and assigns
+/// the result to *o, where i2 is the corresponding iterator in the second
+/// input range and where o is the corresponding output iterator. That is,
+/// for each n such that 0 <= n < last1 - first1, it performs the assignment
+/// *(result + n) = op(*(first1 + n), *(first2 + n).
+/// The return value is result + (last1 - first1).
+/// \ingroup MutatingAlgorithms
+/// \ingroup PredicateAlgorithms
+///
+template <typename InputIterator1, typename InputIterator2, typename OutputIterator, typename BinaryFunction>
+inline OutputIterator transform (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, OutputIterator result, BinaryFunction op)
+{
+    for (; first1 != last1; ++result, ++first1, ++first2)
+	*result = op (*first1, *first2);
+    return (result);
+}
+
+/// Replace replaces every element in the range [first, last) equal to
+/// old_value with new_value. That is: for every iterator i,
+/// if *i == old_value then it performs the assignment *i = new_value.
+/// \ingroup MutatingAlgorithms
+///
+template <typename ForwardIterator, typename T>
+inline void replace (ForwardIterator first, ForwardIterator last, const T& old_value, const T& new_value)
+{
+    for (; first != last; ++first)
+	if (*first == old_value)
+	    *first = new_value;
+}
+
+/// Replace_copy copies elements from the range [first, last) to the range
+/// [result, result + (last-first)), except that any element equal to old_value
+/// is not copied; new_value is copied instead. More precisely, for every
+/// integer n such that 0 <= n < last-first, replace_copy performs the
+/// assignment *(result+n) = new_value if *(first+n) == old_value, and
+/// *(result+n) = *(first+n) otherwise.
+/// \ingroup MutatingAlgorithms
+///
+template <typename InputIterator, typename OutputIterator, typename T>
+inline OutputIterator replace_copy (InputIterator first, InputIterator last, OutputIterator result, const T& old_value, const T& new_value)
+{
+    for (; first != last; ++result, ++first)
+        *result = (*first == old_value) ? new_value : *first;
+}
+
+/// Generate assigns the result of invoking gen, a function object that
+/// takes no arguments, to each element in the range [first, last).
+/// \ingroup GeneratorAlgorithms
+/// \ingroup PredicateAlgorithms
+///
+template <typename ForwardIterator, typename Generator>
+inline void generate (ForwardIterator first, ForwardIterator last, Generator gen)
+{
+    for (; first != last; ++first)
+	*first = gen();
+}
+
+/// Generate_n assigns the result of invoking gen, a function object that
+/// takes no arguments, to each element in the range [first, first+n).
+/// The return value is first + n.
+/// \ingroup GeneratorAlgorithms
+/// \ingroup PredicateAlgorithms
+///
+template <typename OutputIterator, typename Generator>
+inline OutputIterator generate_n (OutputIterator first, size_t n, Generator gen)
+{
+    for (uoff_t i = 0; i != n; ++i, ++first)
+	*first = gen();
+    return (first);
+}
+
+/// \brief Reverse reverses a range.
+/// That is: for every i such that 0 <= i <= (last - first) / 2),
+/// it exchanges *(first + i) and *(last - (i + 1)).
+/// \ingroup MutatingAlgorithms
+///
+template <typename BidirectionalIterator>
+inline void reverse (BidirectionalIterator first, BidirectionalIterator last)
+{
+    for (; distance (first, --last) > 0; ++first)
+	iter_swap (first, last);
+}
+
+/// \brief Reverses [first,last) and writes it to \p output.
+/// \ingroup MutatingAlgorithms
+///
+template <typename BidirectionalIterator, typename OutputIterator>
+inline OutputIterator reverse_copy (BidirectionalIterator first, BidirectionalIterator last, OutputIterator result)
+{
+    for (; first != last; ++result)
+	*result = *--last;
+    return (result);
+}
+
+/// \brief Exchanges ranges [first, middle) and [middle, last)
+/// \ingroup MutatingAlgorithms
+///
+template <typename ForwardIterator>
+ForwardIterator rotate (ForwardIterator first, ForwardIterator middle, ForwardIterator last)
+{
+    if (first == middle || middle == last)
+	return (first);
+    reverse (first, middle);
+    reverse (middle, last);
+    for (;first != middle && middle != last; ++first)
+	iter_swap (first, --last);
+    reverse (first, (first == middle ? last : middle));
+    return (first);
+}
+
+/// Specialization for pointers, which can be treated identically.
+template <typename T>
+inline T* rotate (T* first, T* middle, T* last)
+{
+    rotate_fast (first, middle, last);
+    return (first);
+}
+ 
+
+/// \brief Exchanges ranges [first, middle) and [middle, last) into \p result.
+/// \ingroup MutatingAlgorithms
+///
+template <typename ForwardIterator, typename OutputIterator>
+inline OutputIterator rotate_copy (ForwardIterator first, ForwardIterator middle, ForwardIterator last, OutputIterator result)
+{
+    return (copy (first, middle, copy (middle, last, result)));
+}
+
+/// \brief Combines two sorted ranges.
+/// \ingroup SortingAlgorithms
+///
+template <typename InputIterator1, typename InputIterator2, typename OutputIterator>
+OutputIterator merge (InputIterator1 first1, InputIterator1 last1,
+		      InputIterator2 first2, InputIterator2 last2, OutputIterator result)
+{
+    for (; first1 != last1 && first2 != last2; ++result) {
+	if (*first1 < *first2)
+	    *result = *first1++;
+	else
+	    *result = *first2++;
+    }
+    if (first1 < last1)
+	return (copy (first1, last1, result));
+    else
+	return (copy (first2, last2, result));
+}
+
+/// Combines two sorted ranges from the same container.
+/// \ingroup SortingAlgorithms
+///
+template <typename InputIterator>
+void inplace_merge (InputIterator first, InputIterator middle, InputIterator last)
+{
+    for (; middle != last; ++first) {
+	while (*first < *middle)
+	    ++ first;
+	reverse (first, middle);
+	reverse (first, ++middle);
+    }
+}
+
+/// Remove_copy copies elements that are not equal to value from the range
+/// [first, last) to a range beginning at result. The return value is the
+/// end of the resulting range. This operation is stable, meaning that the
+/// relative order of the elements that are copied is the same as in the
+/// range [first, last).
+/// \ingroup MutatingAlgorithms
+///
+template <typename InputIterator, typename OutputIterator, typename T>
+OutputIterator remove_copy (InputIterator first, InputIterator last, OutputIterator result, const T& value)
+{
+    for (; first != last; ++first) {
+	if (!(*first == value)) {
+	    *result = *first;
+	    ++ result;
+	}
+    }
+    return (result);
+}
+
+/// Remove_copy copies elements pointed to by iterators in [rfirst, rlast)
+/// from the range [first, last) to a range beginning at result. The return
+/// value is the end of the resulting range. This operation is stable, meaning
+/// that the relative order of the elements that are copied is the same as in the
+/// range [first, last). Range [rfirst, rlast) is assumed to be sorted.
+/// This algorithm is a uSTL extension.
+/// \ingroup MutatingAlgorithms
+///
+template <typename InputIterator, typename OutputIterator, typename RInputIterator>
+OutputIterator remove_copy (InputIterator first, InputIterator last, OutputIterator result, RInputIterator rfirst, RInputIterator rlast)
+{
+    for (; first != last; ++first) {
+	while (rfirst != rlast && *rfirst < first)
+	    ++ rfirst;
+	if (rfirst == rlast || first != *rfirst) {
+	    *result = *first;
+	    ++ result;
+	}
+    }
+    return (result);
+}
+
+/// Remove removes from the range [first, last) all elements that are equal to
+/// value. That is, remove returns an iterator new_last such that the range
+/// [first, new_last) contains no elements equal to value. [1] The iterators
+/// in the range [new_last, last) are all still dereferenceable, but the
+/// elements that they point to are unspecified. Remove is stable, meaning
+/// that the relative order of elements that are not equal to value is
+/// unchanged.
+/// \ingroup MutatingAlgorithms
+///
+template <typename ForwardIterator, typename T>
+inline ForwardIterator remove (ForwardIterator first, ForwardIterator last, const T& value)
+{
+    return (remove_copy (first, last, first, value));
+}
+
+/// Unique_copy copies elements from the range [first, last) to a range
+/// beginning with result, except that in a consecutive group of duplicate
+/// elements only the first one is copied. The return value is the end of
+/// the range to which the elements are copied. This behavior is similar
+/// to the Unix filter uniq.
+/// \ingroup MutatingAlgorithms
+///
+template <typename InputIterator, typename OutputIterator>
+OutputIterator unique_copy (InputIterator first, InputIterator last, OutputIterator result)
+{
+    if (first != last) {
+	*result = *first;
+	while (++first != last)
+	    if (!(*first == *result))
+		*++result = *first;
+	++ result;
+    }
+    return (result);
+}
+
+/// Every time a consecutive group of duplicate elements appears in the range
+/// [first, last), the algorithm unique removes all but the first element.
+/// That is, unique returns an iterator new_last such that the range [first,
+/// new_last) contains no two consecutive elements that are duplicates.
+/// The iterators in the range [new_last, last) are all still dereferenceable,
+/// but the elements that they point to are unspecified. Unique is stable,
+/// meaning that the relative order of elements that are not removed is
+/// unchanged.
+/// \ingroup MutatingAlgorithms
+///
+template <typename ForwardIterator>
+inline ForwardIterator unique (ForwardIterator first, ForwardIterator last)
+{
+    return (unique_copy (first, last, first));
+}
+
+/// Returns the furthermost iterator i in [first, last) such that,
+/// for every iterator j in [first, i), *j < value
+/// Assumes the range is sorted.
+/// \ingroup SearchingAlgorithms
+///
+template <typename ForwardIterator, typename LessThanComparable>
+ForwardIterator lower_bound (ForwardIterator first, ForwardIterator last, const LessThanComparable& value)
+{
+    ForwardIterator mid;
+    while (first != last) {
+	mid = advance (first, distance (first,last) / 2);
+	if (*mid < value)
+	    first = mid + 1;
+	else
+	    last = mid;
+    }
+    return (first);
+}
+
+/// Performs a binary search inside the sorted range.
+/// \ingroup SearchingAlgorithms
+///
+template <typename ForwardIterator, typename LessThanComparable>
+inline ForwardIterator binary_search (ForwardIterator first, ForwardIterator last, const LessThanComparable& value)
+{
+    ForwardIterator found = lower_bound (first, last, value);
+    return ((found == last || value < *found) ? last : found);
+}
+
+/// Returns the furthermost iterator i in [first,last) such that for
+/// every iterator j in [first,i), value < *j is false.
+/// \ingroup SearchingAlgorithms
+///
+template <typename ForwardIterator, typename LessThanComparable>
+ForwardIterator upper_bound (ForwardIterator first, ForwardIterator last, const LessThanComparable& value)
+{
+    ForwardIterator mid;
+    while (first != last) {
+	mid = advance (first, distance (first,last) / 2);
+	if (value < *mid)
+	    last = mid;
+	else
+	    first = mid + 1;
+    }
+    return (last);
+}
+
+/// Returns pair<lower_bound,upper_bound>
+/// \ingroup SearchingAlgorithms
+///
+template <typename ForwardIterator, typename LessThanComparable>
+inline pair<ForwardIterator,ForwardIterator> equal_range (ForwardIterator first, ForwardIterator last, const LessThanComparable& value)
+{
+    pair<ForwardIterator,ForwardIterator> rv;
+    rv.second = rv.first = lower_bound (first, last, value);
+    while (rv.second != last && !(value < *(rv.second)))
+	++ rv.second;
+    return (rv);
+}
+
+/// Randomly permute the elements of the container.
+/// \ingroup GeneratorAlgorithms
+///
+template <typename RandomAccessIterator>
+void random_shuffle (RandomAccessIterator first, RandomAccessIterator last)
+{
+    for (; first != last; ++ first)
+	iter_swap (first, first + (rand() % distance (first, last)));
+}
+
+/// \brief Generic compare function adaptor to pass to qsort
+/// \ingroup FunctorObjects
+template <typename ConstPointer, typename Compare>
+int qsort_adapter (const void* p1, const void* p2)
+{
+    ConstPointer i1 = reinterpret_cast<ConstPointer>(p1);
+    ConstPointer i2 = reinterpret_cast<ConstPointer>(p2);
+    Compare comp;
+    return (comp (*i1, *i2) ? -1 : (comp (*i2, *i1) ? 1 : 0));
+}
+
+/// Sorts the container
+/// \ingroup SortingAlgorithms
+/// \ingroup PredicateAlgorithms
+///
+template <typename RandomAccessIterator, typename Compare>
+void sort (RandomAccessIterator first, RandomAccessIterator last, Compare)
+{
+    typedef typename iterator_traits<RandomAccessIterator>::value_type value_type;
+    typedef typename iterator_traits<RandomAccessIterator>::const_pointer const_pointer;
+    qsort (first, distance (first, last), sizeof(value_type),
+	   &qsort_adapter<const_pointer, Compare>);
+}
+
+/// Sorts the container
+/// \ingroup SortingAlgorithms
+///
+template <typename RandomAccessIterator>
+inline void sort (RandomAccessIterator first, RandomAccessIterator last)
+{
+    typedef typename iterator_traits<RandomAccessIterator>::value_type value_type;
+    sort (first, last, less<value_type>());
+}
+
+/// Sorts the container preserving order of equal elements.
+/// \ingroup SortingAlgorithms
+/// \ingroup PredicateAlgorithms
+///
+template <typename RandomAccessIterator, typename Compare>
+void stable_sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp)
+{
+    for (RandomAccessIterator j, i = first; ++i < last;) { // Insertion sort
+	for (j = i; j-- > first && !comp(*j, *i););
+	rotate (++j, i, i + 1);
+    }
+}
+
+/// Sorts the container
+/// \ingroup SortingAlgorithms
+///
+template <typename RandomAccessIterator>
+inline void stable_sort (RandomAccessIterator first, RandomAccessIterator last)
+{
+    typedef typename iterator_traits<RandomAccessIterator>::value_type value_type;
+    stable_sort (first, last, less<value_type>());
+}
+
+/// \brief Searches for the first subsequence [first2,last2) in [first1,last1)
+/// \ingroup SearchingAlgorithms
+template <typename ForwardIterator1, typename ForwardIterator2>
+inline ForwardIterator1 search (ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2)
+{
+    typedef typename iterator_traits<ForwardIterator1>::value_type value_type;
+    return (search (first1, last1, first2, last2, equal_to<value_type>()));
+}
+
+/// \brief Searches for the last subsequence [first2,last2) in [first1,last1)
+/// \ingroup SearchingAlgorithms
+template <typename ForwardIterator1, typename ForwardIterator2>
+inline ForwardIterator1 find_end (ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2)
+{
+    typedef typename iterator_traits<ForwardIterator1>::value_type value_type;
+    return (find_end (first1, last1, first2, last2, equal_to<value_type>()));
+}
+
+/// \brief Searches for the first occurence of \p count \p values in [first, last)
+/// \ingroup SearchingAlgorithms
+template <typename Iterator, typename T>
+inline Iterator search_n (Iterator first, Iterator last, size_t count, const T& value)
+{
+    typedef typename iterator_traits<Iterator>::value_type value_type;
+    return (search_n (first, last, count, value, equal_to<value_type>()));
+}
+
+/// \brief Searches [first1,last1) for the first occurrence of an element from [first2,last2)
+/// \ingroup SearchingAlgorithms
+template <typename InputIterator, typename ForwardIterator>
+inline InputIterator find_first_of (InputIterator first1, InputIterator last1, ForwardIterator first2, ForwardIterator last2)
+{
+    typedef typename iterator_traits<InputIterator>::value_type value_type;
+    return (find_first_of (first1, last1, first2, last2, equal_to<value_type>()));
+}
+
+/// \brief Returns true if [first2,last2) is a subset of [first1,last1)
+/// \ingroup ConditionAlgorithms
+/// \ingroup SetAlgorithms
+template <typename InputIterator1, typename InputIterator2>
+inline bool includes (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2)
+{
+    typedef typename iterator_traits<InputIterator1>::value_type value_type;
+    return (includes (first1, last1, first2, last2, less<value_type>()));
+}
+
+/// \brief Merges [first1,last1) with [first2,last2)
+///
+/// Result will contain every element that is in either set. If duplicate
+/// elements are present, max(n,m) is placed in the result.
+///
+/// \ingroup SetAlgorithms
+template <typename InputIterator1, typename InputIterator2, typename OutputIterator>
+inline OutputIterator set_union (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result)
+{
+    typedef typename iterator_traits<InputIterator1>::value_type value_type;
+    return (set_union (first1, last1, first2, last2, result, less<value_type>()));
+}
+
+/// \brief Creates a set containing elements shared by the given ranges.
+/// \ingroup SetAlgorithms
+template <typename InputIterator1, typename InputIterator2, typename OutputIterator>
+inline OutputIterator set_intersection (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result)
+{
+    typedef typename iterator_traits<InputIterator1>::value_type value_type;
+    return (set_intersection (first1, last1, first2, last2, result, less<value_type>()));
+}
+
+/// \brief Removes from [first1,last1) elements present in [first2,last2)
+/// \ingroup SetAlgorithms
+template <typename InputIterator1, typename InputIterator2, typename OutputIterator>
+inline OutputIterator set_difference (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result)
+{
+    typedef typename iterator_traits<InputIterator1>::value_type value_type;
+    return (set_difference (first1, last1, first2, last2, result, less<value_type>()));
+}
+
+/// \brief Performs union of sets A-B and B-A.
+/// \ingroup SetAlgorithms
+template <typename InputIterator1, typename InputIterator2, typename OutputIterator>
+inline OutputIterator set_symmetric_difference (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result)
+{
+    typedef typename iterator_traits<InputIterator1>::value_type value_type;
+    return (set_symmetric_difference (first1, last1, first2, last2, result, less<value_type>()));
+}
+
+/// \brief Returns true if the given range is sorted.
+/// \ingroup ConditionAlgorithms
+template <typename ForwardIterator>
+inline bool is_sorted (ForwardIterator first, ForwardIterator last)
+{
+    typedef typename iterator_traits<ForwardIterator>::value_type value_type;
+    return (is_sorted (first, last, less<value_type>()));
+}
+
+/// \brief Compares two given containers like strcmp compares strings.
+/// \ingroup ConditionAlgorithms
+template <typename InputIterator1, typename InputIterator2>
+inline bool lexicographical_compare (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2)
+{
+    typedef typename iterator_traits<InputIterator1>::value_type value_type;
+    return (lexicographical_compare (first1, last1, first2, last2, less<value_type>()));
+}
+
+/// \brief Creates the next lexicographical permutation of [first,last).
+/// Returns false if no further permutations can be created.
+/// \ingroup GeneratorAlgorithms
+template <typename BidirectionalIterator>
+inline bool next_permutation (BidirectionalIterator first, BidirectionalIterator last)
+{
+    typedef typename iterator_traits<BidirectionalIterator>::value_type value_type;
+    return (next_permutation (first, last, less<value_type>()));
+}
+
+/// \brief Creates the previous lexicographical permutation of [first,last).
+/// Returns false if no further permutations can be created.
+/// \ingroup GeneratorAlgorithms
+template <typename BidirectionalIterator>
+inline bool prev_permutation (BidirectionalIterator first, BidirectionalIterator last)
+{
+    typedef typename iterator_traits<BidirectionalIterator>::value_type value_type;
+    return (prev_permutation (first, last, less<value_type>()));
+}
+
+/// \brief Returns iterator to the max element in [first,last)
+/// \ingroup SearchingAlgorithms
+template <typename ForwardIterator>
+inline ForwardIterator max_element (ForwardIterator first, ForwardIterator last)
+{
+    typedef typename iterator_traits<ForwardIterator>::value_type value_type;
+    return (max_element (first, last, less<value_type>()));
+}
+
+/// \brief Returns iterator to the min element in [first,last)
+/// \ingroup SearchingAlgorithms
+template <typename ForwardIterator>
+inline ForwardIterator min_element (ForwardIterator first, ForwardIterator last)
+{
+    typedef typename iterator_traits<ForwardIterator>::value_type value_type;
+    return (min_element (first, last, less<value_type>()));
+}
+
+/// \brief Makes [first,middle) a part of the sorted array.
+/// Contents of [middle,last) is undefined. This implementation just calls stable_sort.
+/// \ingroup SortingAlgorithms
+template <typename RandomAccessIterator>
+inline void partial_sort (RandomAccessIterator first, RandomAccessIterator middle, RandomAccessIterator last)
+{
+    typedef typename iterator_traits<RandomAccessIterator>::value_type value_type;
+    partial_sort (first, middle, last, less<value_type>());
+}
+
+/// \brief Puts \p nth element into its sorted position.
+/// In this implementation, the entire array is sorted. I can't think of any
+/// use for it where the time gained would be useful.
+/// \ingroup SortingAlgorithms
+/// \ingroup SearchingAlgorithms
+///
+template <typename RandomAccessIterator>
+inline void nth_element (RandomAccessIterator first, RandomAccessIterator nth, RandomAccessIterator last)
+{
+    partial_sort (first, nth, last);
+}
+
+/// \brief Like partial_sort, but outputs to [result_first,result_last)
+/// \ingroup SortingAlgorithms
+template <typename InputIterator, typename RandomAccessIterator>
+inline RandomAccessIterator partial_sort_copy (InputIterator first, InputIterator last, RandomAccessIterator result_first, RandomAccessIterator result_last)
+{
+    typedef typename iterator_traits<InputIterator>::value_type value_type;
+    return (partial_sort_copy (first, last, result_first, result_last, less<value_type>()));
+}
+
+} // namespace ustl
+
+#endif
+
diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/ualgobase.cpp b/media/libdrm/mobile2/src/util/ustl-1.0/ualgobase.cpp
new file mode 100644
index 0000000..9764cd1
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/ustl-1.0/ualgobase.cpp
@@ -0,0 +1,293 @@
+// This file is part of the ustl library, an STL implementation.
+//
+// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
+// This file is free software, distributed under the MIT License.
+//
+// ualgobase.cc
+//
+// Copy and fill optimizations are here.
+//
+
+#ifndef NDEBUG	// Optimized code here. asserts slow it down, and are checked elsewhere.
+#define NDEBUG
+#endif
+
+#include "ualgo.h"
+
+#undef CPU_HAS_MMX
+
+namespace ustl {
+
+// Generic version for implementing fill_nX_fast on non-i386 architectures.
+template <typename T> inline void stosv (T*& p, size_t n, T v)
+    { while (n--) *p++ = v; }
+
+#if defined(__i386__) || defined(__x86_64__)
+
+//----------------------------------------------------------------------
+// Copy functions
+//----------------------------------------------------------------------
+
+#if __GNUC__ >= 3
+static inline void movsb_dir_up (void) __attribute__((always_inline));
+static inline void movsb_dir_down (void) __attribute__((always_inline));
+static inline void movsb (const void*& src, size_t nBytes, void*& dest) __attribute__((always_inline));
+static inline void movsd (const void*& src, size_t nWords, void*& dest) __attribute__((always_inline));
+#endif
+
+static inline void movsb_dir_up (void) { asm volatile ("cld"); }
+static inline void movsb_dir_down (void) { asm volatile ("std"); }
+
+static inline void movsb (const void*& src, size_t nBytes, void*& dest)
+{
+    asm volatile ("rep;\n\tmovsb"
+	: "=&S"(src), "=&D"(dest), "=&c"(nBytes)
+	: "0"(src), "1"(dest), "2"(nBytes)
+	: "memory");
+}
+
+static inline void movsd (const void*& src, size_t nWords, void*& dest)
+{
+    asm volatile ("rep;\n\tmovsl"
+	: "=&S"(src), "=&D"(dest), "=&c"(nWords)
+	: "0"(src), "1"(dest), "2"(nWords)
+	: "memory");
+}
+
+template <> inline void stosv (uint8_t*& p, size_t n, uint8_t v)
+{ asm volatile ("rep;\n\tstosb" : "=&D"(p), "=c"(n) : "0"(p), "1"(n), "a"(v) : "memory"); }
+template <> inline void stosv (uint16_t*& p, size_t n, uint16_t v)
+{ asm volatile ("rep;\n\tstosw" : "=&D"(p), "=c"(n) : "0"(p), "1"(n), "a"(v) : "memory"); }
+template <> inline void stosv (uint32_t*& p, size_t n, uint32_t v)
+{ asm volatile ("rep;\n\tstosl" : "=&D"(p), "=c"(n) : "0"(p), "1"(n), "a"(v) : "memory"); }
+
+#if CPU_HAS_MMX
+#define MMX_ALIGN	16U	// Data must be aligned on this grain
+#define MMX_BS		32U	// Assembly routines copy data this many bytes at a time.
+
+static inline void simd_block_copy (const void* src, void* dest) __attribute__((always_inline));
+static inline void simd_block_store (uint8_t* dest) __attribute__((always_inline));
+static inline void simd_block_cleanup (void) __attribute__((always_inline));
+
+static inline void simd_block_copy (const void* src, void* dest)
+{
+    const char* csrc ((const char*) src);
+    char* cdest ((char*) dest);
+    #if CPU_HAS_SSE
+    asm (
+	"movaps\t%2, %%xmm0	\n\t"
+	"movaps\t%3, %%xmm1	\n\t"
+	"movntps\t%%xmm0, %0	\n\t"
+	"movntps\t%%xmm1, %1"
+	: "=m"(cdest[0]), "=m"(cdest[16])
+	: "m"(csrc[0]), "m"(csrc[16])
+	: "xmm0", "xmm1");
+    #else
+    asm (
+	"movq	%4, %%mm0	\n\t"
+	"movq	%5, %%mm1	\n\t"
+	"movq	%6, %%mm2	\n\t"
+	"movq	%7, %%mm3	\n\t"
+	"movq	%%mm0, %0	\n\t"
+	"movq	%%mm1, %1	\n\t"
+	"movq	%%mm2, %2	\n\t"
+	"movq	%%mm3, %3"
+	: "=m"(cdest[0]), "=m"(cdest[8]), "=m"(cdest[16]), "=m"(cdest[24])
+	: "m"(csrc[0]), "m"(csrc[8]), "m"(csrc[16]), "m"(csrc[24])
+	: "mm0", "mm1", "mm2", "mm3", "st", "st(1)", "st(2)", "st(3)");
+    #endif
+}
+
+static inline void simd_block_store (uint8_t* dest)
+{
+    #if CPU_HAS_SSE
+    asm volatile (
+	"movntq %%mm0, %0\n\t"
+	"movntq %%mm0, %1\n\t"
+	"movntq %%mm0, %2\n\t"
+	"movntq %%mm0, %3"
+	: "=m"(dest[0]), "=m"(dest[8]), "=m"(dest[16]), "=m"(dest[24]));
+    #else
+    asm volatile (
+	"movq %%mm0, %0	\n\t"
+	"movq %%mm0, %1	\n\t"
+	"movq %%mm0, %2	\n\t"
+	"movq %%mm0, %3"
+	: "=m"(dest[0]), "=m"(dest[8]), "=m"(dest[16]), "=m"(dest[24]));
+    #endif
+}
+
+static inline void simd_block_cleanup (void)
+{
+    #if !CPU_HAS_SSE
+	simd::reset_mmx();
+    #endif
+    asm volatile ("sfence");
+}
+
+/// The fastest optimized raw memory copy.
+void copy_n_fast (const void* src, size_t nBytes, void* dest)
+{
+    movsb_dir_up();
+    size_t nHeadBytes = Align(uintptr_t(src), MMX_ALIGN) - uintptr_t(src);
+    nHeadBytes = min (nHeadBytes, nBytes);
+    movsb (src, nHeadBytes, dest);
+    nBytes -= nHeadBytes;
+    if (!(uintptr_t(dest) % MMX_ALIGN)) {
+	const size_t nMiddleBlocks = nBytes / MMX_BS;
+	for (uoff_t i = 0; i < nMiddleBlocks; ++ i) {
+	    prefetch (advance (src, 512), 0, 0);
+	    simd_block_copy (src, dest);
+	    src = advance (src, MMX_BS);
+	    dest = advance (dest, MMX_BS);
+	}
+	simd_block_cleanup();
+	nBytes %= MMX_BS;
+    }
+    movsb (src, nBytes, dest);
+}
+#endif // CPU_HAS_MMX
+
+/// The fastest optimized backwards raw memory copy.
+void copy_backward_fast (const void* first, const void* last, void* result)
+{
+    prefetch (first, 0, 0);
+    prefetch (result, 1, 0);
+    size_t nBytes (distance (first, last));
+    movsb_dir_down();
+    size_t nHeadBytes = uintptr_t(last) % 4;
+    last = advance (last, -1);
+    result = advance (result, -1);
+    movsb (last, nHeadBytes, result);
+    nBytes -= nHeadBytes;
+    if (uintptr_t(result) % 4 == 3) {
+	const size_t nMiddleBlocks = nBytes / 4;
+	last = advance (last, -3);
+	result = advance (result, -3);
+	movsd (last, nMiddleBlocks, result);
+	nBytes %= 4;
+    }
+    movsb (last, nBytes, result);
+    movsb_dir_up();
+}
+#endif // __i386__
+
+//----------------------------------------------------------------------
+// Fill functions
+//----------------------------------------------------------------------
+
+#if CPU_HAS_MMX
+template <typename T> inline void build_block (T) {}
+template <> inline void build_block (uint8_t v)
+{
+    asm volatile (
+	"movd %0, %%mm0\n\tpunpcklbw %%mm0, %%mm0\n\tpshufw $0, %%mm0, %%mm0"
+	: : "g"(uint32_t(v)) : "mm0");
+}
+template <> inline void build_block (uint16_t v)
+{
+    asm volatile (
+	"movd %0, %%mm0\n\tpshufw $0, %%mm0, %%mm0"
+	: : "g"(uint32_t(v)) : "mm0");
+}
+template <> inline void build_block (uint32_t v)
+{
+    asm volatile (
+	"movd %0, %%mm0\n\tpunpckldq %%mm0, %%mm0"
+	: : "g"(uint32_t(v)) : "mm0");
+}
+
+static inline void simd_block_fill_loop (uint8_t*& dest, size_t count)
+{
+    prefetch (advance (dest, 512), 1, 0);
+    for (uoff_t i = 0; i < count; ++ i, dest += MMX_BS)
+	simd_block_store (dest);
+    simd_block_cleanup();
+    simd::reset_mmx();
+}
+
+template <typename T>
+inline void fill_n_fast (T* dest, size_t count, T v)
+{
+    size_t nHead = Align(uintptr_t(dest), MMX_ALIGN) - uintptr_t(dest) / sizeof(T);
+    nHead = min (nHead, count);
+    stosv (dest, nHead, v);
+    count -= nHead;
+    build_block (v);
+    simd_block_fill_loop ((uint8_t*&) dest, count * sizeof(T) / MMX_BS);
+    count %= MMX_BS;
+    stosv (dest, count, v);
+}
+
+void fill_n8_fast (uint8_t* dest, size_t count, uint8_t v)
+    { fill_n_fast (dest, count, v); }
+void fill_n16_fast (uint16_t* dest, size_t count, uint16_t v)
+    { fill_n_fast (dest, count, v); }
+void fill_n32_fast (uint32_t* dest, size_t count, uint32_t v)
+    { fill_n_fast (dest, count, v); }
+#else
+void fill_n8_fast (uint8_t* dest, size_t count, uint8_t v) { memset (dest, v, count); }
+void fill_n16_fast (uint16_t* dest, size_t count, uint16_t v) { stosv (dest, count, v); }
+void fill_n32_fast (uint32_t* dest, size_t count, uint32_t v) { stosv (dest, count, v); }
+#endif // CPU_HAS_MMX
+
+/// Exchanges ranges [first, middle) and [middle, last)
+void rotate_fast (void* first, void* middle, void* last)
+{
+#ifdef HAVE_ALLOCA_H
+    const size_t half1 (distance (first, middle)), half2 (distance (middle, last));
+    const size_t hmin (min (half1, half2));
+  if (!hmin) {
+	return;
+  }
+    void* buf = alloca (hmin);
+    if (buf) {
+	if (half2 < half1) {
+	    copy_n_fast (middle, half2, buf);
+	    copy_backward_fast (first, middle, last);
+	    copy_n_fast (buf, half2, first);
+	} else {
+	    copy_n_fast (first, half1, buf);
+	    copy_n_fast (middle, half2, first);
+	    copy_n_fast (buf, half1, advance (first, half2));
+	}
+    } else
+#else
+    if (first == middle || middle == last) {
+	return;
+    }
+#endif
+    {
+	char* f = (char*) first;
+	char* m = (char*) middle;
+	char* l = (char*) last;
+	reverse (f, m);
+	reverse (m, l);
+	while (f != m && m != l)
+	    iter_swap (f++, --l);
+	reverse (f, (f == m ? l : m));
+    }
+}
+
+#if __GNUC__ < 4
+size_t popcount (uint32_t v)
+{
+    const uint32_t w = v - ((v >> 1) & 0x55555555); // Algorithm from AMD optimization guide
+    const uint32_t x = (w & 0x33333333) + ((w >> 2) & 0x33333333);
+    return (((x + (x >> 4) & 0x0F0F0F0F) * 0x01010101) >> 24);
+}
+
+#if HAVE_INT64_T
+/// \brief Returns the number of 1s in \p v in binary.
+size_t popcount (uint64_t v)
+{
+    v -= (v >> 1) & UINT64_C(0x5555555555555555);		// Algorithm from Wikipedia
+    v = (v & UINT64_C(0x3333333333333333)) + ((v >> 2) & UINT64_C(0x3333333333333333));
+    v = (v + (v >> 4)) & UINT64_C(0x0F0F0F0F0F0F0F0F);
+    return ((v * UINT64_C(0x0101010101010101)) >> 56);
+}
+#endif	// HAVE_INT64_T
+#endif	// !__GNUC__
+
+} // namespace ustl
+
diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/ualgobase.h b/media/libdrm/mobile2/src/util/ustl-1.0/ualgobase.h
new file mode 100644
index 0000000..38c1a72
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/ustl-1.0/ualgobase.h
@@ -0,0 +1,334 @@
+// This file is part of the ustl library, an STL implementation.
+//
+// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
+// This file is free software, distributed under the MIT License.
+//
+// ualgobase.h
+//
+// Implementation of STL algorithms.
+//
+// The function prototypes are copied
+// exactly from the SGI version of STL documentation along with comments about
+// their use. The code is NOT the same, though the functionality usually is.
+//
+
+#ifndef UALGOBASE_H_683A0BE77546133C4CE0E3622CFAA2EB
+#define UALGOBASE_H_683A0BE77546133C4CE0E3622CFAA2EB
+
+#include "uutility.h"
+#include <string.h>
+
+#if PLATFORM_ANDROID
+#include <stdio.h>
+#undef CPU_HAS_MMX
+#endif
+
+namespace ustl {
+
+/// Assigns the contents of a to b and the contents of b to a.
+/// This is used as a primitive operation by many other algorithms. 
+/// \ingroup SwapAlgorithms
+///
+template <typename Assignable> 
+inline void swap (Assignable& a, Assignable& b)
+{
+    Assignable tmp = a;
+    a = b;
+    b = tmp;
+}
+
+/// Equivalent to swap (*a, *b)
+/// \ingroup SwapAlgorithms
+///
+template <typename Iterator> 
+inline void iter_swap (Iterator a, Iterator b)
+{
+    swap (*a, *b);
+}
+
+/// Copy copies elements from the range [first, last) to the range
+/// [result, result + (last - first)). That is, it performs the assignments
+/// *result = *first, *(result + 1) = *(first + 1), and so on. [1] Generally,
+/// for every integer n from 0 to last - first, copy performs the assignment
+/// *(result + n) = *(first + n). Assignments are performed in forward order,
+/// i.e. in order of increasing n. 
+/// \ingroup MutatingAlgorithms
+///
+template <typename InputIterator, typename OutputIterator>
+inline OutputIterator copy (InputIterator first, InputIterator last, OutputIterator result)
+{
+    for (; first != last; ++result, ++first)
+	*result = *first;
+    return (result);
+}
+
+/// Copy_n copies elements from the range [first, first + n) to the range
+/// [result, result + n). That is, it performs the assignments
+/// *result = *first, *(result + 1) = *(first + 1), and so on. Generally,
+/// for every integer i from 0 up to (but not including) n, copy_n performs
+/// the assignment *(result + i) = *(first + i). Assignments are performed
+/// in forward order, i.e. in order of increasing n.
+/// \ingroup MutatingAlgorithms
+///
+template <typename InputIterator, typename OutputIterator>
+inline OutputIterator copy_n (InputIterator first, size_t count, OutputIterator result)
+{
+    for (; count; --count, ++result, ++first)
+	*result = *first;
+    return (result);
+}
+
+/// \brief Copy copies elements from the range (last, first] to result.
+/// \ingroup MutatingAlgorithms
+/// Copies elements starting at last, decrementing both last and result.
+///
+template <typename InputIterator, typename OutputIterator>
+inline OutputIterator copy_backward (InputIterator first, InputIterator last, OutputIterator result)
+{
+    while (first != last)
+	*--result = *--last;
+    return (result);
+}
+
+/// For_each applies the function object f to each element in the range
+/// [first, last); f's return value, if any, is ignored. Applications are
+/// performed in forward order, i.e. from first to last. For_each returns
+/// the function object after it has been applied to each element.
+/// \ingroup MutatingAlgorithms
+///
+template <typename InputIterator, typename UnaryFunction>
+inline UnaryFunction for_each (InputIterator first, InputIterator last, UnaryFunction f)
+{
+    for (; first != last; ++first)
+	f (*first);
+    return (f);
+}
+
+/// Fill assigns the value value to every element in the range [first, last).
+/// That is, for every iterator i in [first, last),
+/// it performs the assignment *i = value.
+/// \ingroup GeneratorAlgorithms
+///
+template <typename ForwardIterator, typename T>
+inline void fill (ForwardIterator first, ForwardIterator last, const T& value)
+{
+    for (; first != last; ++first)
+	*first = value;
+}
+
+/// Fill_n assigns the value value to every element in the range
+/// [first, first+count). That is, for every iterator i in [first, first+count),
+/// it performs the assignment *i = value. The return value is first + count.
+/// \ingroup GeneratorAlgorithms
+///
+template <typename OutputIterator, typename T>
+inline OutputIterator fill_n (OutputIterator first, size_t count, const T& value)
+{
+    for (; count; --count, ++first)
+	*first = value;
+    return (first);
+}
+
+#if CPU_HAS_MMX
+extern "C" void copy_n_fast (const void* src, size_t count, void* dest);
+#else
+inline void copy_n_fast (const void* src, size_t count, void* dest)
+{ memcpy (dest, src, count); }
+#endif
+#if __i386__ || __x86_64__
+extern "C" void copy_backward_fast (const void* first, const void* last, void* result);
+#else
+inline void copy_backward_fast (const void* first, const void* last, void* result)
+{
+    const size_t nBytes (distance (first, last));
+    memmove (advance (result, -nBytes), first, nBytes);
+}
+#endif
+extern "C" void fill_n8_fast (uint8_t* dest, size_t count, uint8_t v);
+extern "C" void fill_n16_fast (uint16_t* dest, size_t count, uint16_t v);
+extern "C" void fill_n32_fast (uint32_t* dest, size_t count, uint32_t v);
+extern "C" void rotate_fast (void* first, void* middle, void* last);
+
+#if __GNUC__ >= 4
+/// \brief Computes the number of 1 bits in a number.
+/// \ingroup ConditionAlgorithms
+inline size_t popcount (uint32_t v)	{ return (__builtin_popcount (v)); }
+#if HAVE_INT64_T
+inline size_t popcount (uint64_t v)	{ return (__builtin_popcountll (v)); }
+#endif
+#else
+size_t popcount (uint32_t v);
+#if HAVE_INT64_T
+size_t popcount (uint64_t v);
+#endif	// HAVE_INT64_T
+#endif	// __GNUC__
+
+//----------------------------------------------------------------------
+// Optimized versions for standard types
+//----------------------------------------------------------------------
+
+#if WANT_UNROLLED_COPY
+
+template <typename T>
+inline T* unrolled_copy (const T* first, size_t count, T* result)
+{
+    copy_n_fast (first, count * sizeof(T), result);
+    return (advance (result, count));
+}
+
+template <>
+inline uint8_t* copy_backward (const uint8_t* first, const uint8_t* last, uint8_t* result)
+{
+    copy_backward_fast (first, last, result);
+    return (result);
+}
+
+template <typename T>
+inline T* unrolled_fill (T* result, size_t count, T value)
+{
+    for (; count; --count, ++result)
+	*result = value;
+    return (result);
+}
+template <> inline uint8_t* unrolled_fill (uint8_t* result, size_t count, uint8_t value)
+    { fill_n8_fast (result, count, value); return (advance (result, count)); }
+template <> inline uint16_t* unrolled_fill (uint16_t* result, size_t count, uint16_t value)
+    { fill_n16_fast (result, count, value); return (advance (result, count)); }
+template <> inline uint32_t* unrolled_fill (uint32_t* result, size_t count, uint32_t value)
+    { fill_n32_fast (result, count, value); return (advance (result, count)); }
+template <> inline float* unrolled_fill (float* result, size_t count, float value)
+    { fill_n32_fast ((uint32_t*) result, count, noalias(uint32_t(),&value)); return (advance (result, count)); }
+
+#if CPU_HAS_MMX
+#define UNROLLED_COPY_SPECIALIZATION(type)						\
+template <> inline type* copy (const type* first, const type* last, type* result)	\
+{ return (unrolled_copy (first, distance (first, last), result)); }			\
+template <> inline type* copy_n (const type* first, size_t count, type* result)		\
+{ return (unrolled_copy (first, count, result)); }
+#define UNROLLED_FILL_SPECIALIZATION(type)						\
+template <> inline void fill (type* first, type* last, const type& value)		\
+{ unrolled_fill (first, distance (first, last), value); }				\
+template <> inline type* fill_n (type* first, size_t count, const type& value)		\
+{ return (unrolled_fill (first, count, value)); }
+UNROLLED_COPY_SPECIALIZATION(uint8_t)
+UNROLLED_FILL_SPECIALIZATION(uint8_t)
+UNROLLED_COPY_SPECIALIZATION(uint16_t)
+UNROLLED_FILL_SPECIALIZATION(uint16_t)
+UNROLLED_COPY_SPECIALIZATION(uint32_t)
+UNROLLED_FILL_SPECIALIZATION(uint32_t)
+UNROLLED_COPY_SPECIALIZATION(float)
+UNROLLED_FILL_SPECIALIZATION(float)
+#undef UNROLLED_FILL_SPECIALIZATION
+#undef UNROLLED_COPY_SPECIALIZATION
+#endif // WANT_UNROLLED_COPY
+#endif // CPU_HAS_MMX
+
+// Specializations for void* and char*, aliasing the above optimized versions.
+//
+// All these need duplication with const and non-const arguments, since
+// otherwise the compiler will default to the unoptimized version for
+// pointers not const in the caller's context, such as local variables.
+// These are all inline, but they sure slow down compilation... :(
+//
+#define COPY_ALIAS_FUNC(ctype, type, alias_type)			\
+template <> inline type* copy (ctype* first, ctype* last, type* result)	\
+{ return ((type*) copy ((const alias_type*) first, (const alias_type*) last, (alias_type*) result)); }
+#if WANT_UNROLLED_COPY
+#if HAVE_THREE_CHAR_TYPES
+COPY_ALIAS_FUNC(const char, char, uint8_t)
+COPY_ALIAS_FUNC(char, char, uint8_t)
+#endif
+COPY_ALIAS_FUNC(const int8_t, int8_t, uint8_t)
+COPY_ALIAS_FUNC(int8_t, int8_t, uint8_t)
+COPY_ALIAS_FUNC(uint8_t, uint8_t, uint8_t)
+COPY_ALIAS_FUNC(const int16_t, int16_t, uint16_t)
+COPY_ALIAS_FUNC(int16_t, int16_t, uint16_t)
+COPY_ALIAS_FUNC(uint16_t, uint16_t, uint16_t)
+#if CPU_HAS_MMX || (SIZE_OF_LONG > 4)
+COPY_ALIAS_FUNC(const int32_t, int32_t, uint32_t)
+COPY_ALIAS_FUNC(int32_t, int32_t, uint32_t)
+COPY_ALIAS_FUNC(uint32_t, uint32_t, uint32_t)
+#endif
+#endif
+COPY_ALIAS_FUNC(const void, void, uint8_t)
+COPY_ALIAS_FUNC(void, void, uint8_t)
+#undef COPY_ALIAS_FUNC
+#define COPY_BACKWARD_ALIAS_FUNC(ctype, type, alias_type)				\
+template <> inline type* copy_backward (ctype* first, ctype* last, type* result)	\
+{ return ((type*) copy_backward ((const alias_type*) first, (const alias_type*) last, (alias_type*) result)); }
+#if WANT_UNROLLED_COPY
+#if HAVE_THREE_CHAR_TYPES
+COPY_BACKWARD_ALIAS_FUNC(char, char, uint8_t)
+#endif
+COPY_BACKWARD_ALIAS_FUNC(uint8_t, uint8_t, uint8_t)
+COPY_BACKWARD_ALIAS_FUNC(int8_t, int8_t, uint8_t)
+COPY_BACKWARD_ALIAS_FUNC(uint16_t, uint16_t, uint8_t)
+COPY_BACKWARD_ALIAS_FUNC(const uint16_t, uint16_t, uint8_t)
+COPY_BACKWARD_ALIAS_FUNC(int16_t, int16_t, uint8_t)
+COPY_BACKWARD_ALIAS_FUNC(const int16_t, int16_t, uint8_t)
+#endif
+COPY_BACKWARD_ALIAS_FUNC(void, void, uint8_t)
+COPY_BACKWARD_ALIAS_FUNC(const void, void, uint8_t)
+#undef COPY_BACKWARD_ALIAS_FUNC
+#define FILL_ALIAS_FUNC(type, alias_type, v_type)				\
+template <> inline void fill (type* first, type* last, const v_type& value)	\
+{ fill ((alias_type*) first, (alias_type*) last, (const alias_type&) value); }
+FILL_ALIAS_FUNC(void, uint8_t, char)
+FILL_ALIAS_FUNC(void, uint8_t, uint8_t)
+#if WANT_UNROLLED_COPY
+#if HAVE_THREE_CHAR_TYPES
+FILL_ALIAS_FUNC(char, uint8_t, char)
+FILL_ALIAS_FUNC(char, uint8_t, uint8_t)
+#endif
+FILL_ALIAS_FUNC(int8_t, uint8_t, int8_t)
+FILL_ALIAS_FUNC(int16_t, uint16_t, int16_t)
+#if CPU_HAS_MMX || (SIZE_OF_LONG > 4)
+FILL_ALIAS_FUNC(int32_t, uint32_t, int32_t)
+#endif
+#endif
+#undef FILL_ALIAS_FUNC
+#define COPY_N_ALIAS_FUNC(ctype, type, alias_type)					\
+template <> inline type* copy_n (ctype* first, size_t count, type* result)	\
+{ return ((type*) copy_n ((const alias_type*) first, count, (alias_type*) result)); }
+COPY_N_ALIAS_FUNC(const void, void, uint8_t)
+COPY_N_ALIAS_FUNC(void, void, uint8_t)
+#if WANT_UNROLLED_COPY
+#if HAVE_THREE_CHAR_TYPES
+COPY_N_ALIAS_FUNC(const char, char, uint8_t)
+COPY_N_ALIAS_FUNC(char, char, uint8_t)
+#endif
+COPY_N_ALIAS_FUNC(int8_t, int8_t, uint8_t)
+COPY_N_ALIAS_FUNC(uint8_t, uint8_t, uint8_t)
+COPY_N_ALIAS_FUNC(const int8_t, int8_t, uint8_t)
+COPY_N_ALIAS_FUNC(int16_t, int16_t, uint16_t)
+COPY_N_ALIAS_FUNC(uint16_t, uint16_t, uint16_t)
+COPY_N_ALIAS_FUNC(const int16_t, int16_t, uint16_t)
+#if CPU_HAS_MMX || (SIZE_OF_LONG > 4)
+COPY_N_ALIAS_FUNC(int32_t, int32_t, uint32_t)
+COPY_N_ALIAS_FUNC(uint32_t, uint32_t, uint32_t)
+COPY_N_ALIAS_FUNC(const int32_t, int32_t, uint32_t)
+#endif
+#endif
+#undef COPY_N_ALIAS_FUNC
+#define FILL_N_ALIAS_FUNC(type, alias_type, v_type)				\
+template <> inline type* fill_n (type* first, size_t n, const v_type& value)	\
+{ return ((type*) fill_n ((alias_type*) first, n, (const alias_type&) value)); }
+FILL_N_ALIAS_FUNC(void, uint8_t, char)
+FILL_N_ALIAS_FUNC(void, uint8_t, uint8_t)
+#if WANT_UNROLLED_COPY
+#if HAVE_THREE_CHAR_TYPES
+FILL_N_ALIAS_FUNC(char, uint8_t, char)
+FILL_N_ALIAS_FUNC(char, uint8_t, uint8_t)
+#endif
+FILL_N_ALIAS_FUNC(int8_t, uint8_t, int8_t)
+FILL_N_ALIAS_FUNC(int16_t, uint16_t, int16_t)
+#if CPU_HAS_MMX || (SIZE_OF_LONG > 4)
+FILL_N_ALIAS_FUNC(int32_t, uint32_t, int32_t)
+#endif
+#endif
+#undef FILL_N_ALIAS_FUNC
+
+} // namespace ustl
+
+#endif
+
diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/uassert.h b/media/libdrm/mobile2/src/util/ustl-1.0/uassert.h
new file mode 100644
index 0000000..a9fde46
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/ustl-1.0/uassert.h
@@ -0,0 +1,21 @@
+// uassert.h
+
+#ifndef UASSERT_H
+#define UASSERT_H
+
+#if PLATFORM_ANDROID
+#include <stdio.h>
+
+#undef assert
+#define assert(x) _uassert((x), #x, __FILE__, __LINE__)
+
+static void _uassert(int x, const char *xstr, const char *file, int line) {
+  if (!x) {
+    printf("assert %s failed at %s:%d\n", xstr, file, line);
+  }
+}
+#else
+#include <assert.h>
+#endif
+
+#endif
diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/ubitset.cpp b/media/libdrm/mobile2/src/util/ustl-1.0/ubitset.cpp
new file mode 100644
index 0000000..21b5a7a
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/ustl-1.0/ubitset.cpp
@@ -0,0 +1,38 @@
+// This file is part of the ustl library, an STL implementation.
+//
+// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
+// This file is free software, distributed under the MIT License.
+//
+// ubitset.cc
+//
+
+#include "ubitset.h"
+
+namespace ustl {
+
+/// Copies bits from \p v of size \p n into \p buf as MSB "1011001..." LSB
+/// If \p buf is too small, MSB bits will be truncated.
+void convert_to_bitstring (const bitset_value_type* v, size_t n, string& buf)
+{
+    string::iterator stri = buf.end();
+    for (size_t i = 0; i < n && stri > buf.begin(); ++ i)
+	for (bitset_value_type b = 1; b && stri > buf.begin(); b <<= 1)
+	    *--stri = (v[i] & b) ? '1' : '0';
+}
+
+/// Copies bits from \p buf as MSB "1011001..." LSB into \p v of size \p n.
+void convert_from_bitstring (const string& buf, bitset_value_type* v, size_t n)
+{
+    string::const_iterator stri = buf.end();
+    for (size_t i = 0; i < n; ++ i) {
+	for (bitset_value_type b = 1; b; b <<= 1) {
+	    if (stri == buf.begin() || *--stri == '0')
+		v[i] &= ~b;
+	    else
+		v[i] |= b;
+	}
+    }
+}
+
+} // namespace ustl
+
diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/ubitset.h b/media/libdrm/mobile2/src/util/ustl-1.0/ubitset.h
new file mode 100644
index 0000000..4f53a95
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/ustl-1.0/ubitset.h
@@ -0,0 +1,131 @@
+// This file is part of the ustl library, an STL implementation.
+//
+// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
+// This file is free software, distributed under the MIT License.
+//
+// ubitset.h
+//
+#ifndef UBITSET_H_7B6450EC1400CBA45DCE0127739F82EE
+#define UBITSET_H_7B6450EC1400CBA45DCE0127739F82EE
+
+#include "uassert.h"
+#include "ustring.h"
+#include "ufunction.h"
+
+namespace ustl {
+
+typedef uint32_t	bitset_value_type;
+
+void convert_to_bitstring (const bitset_value_type* v, size_t n, string& buf);
+void convert_from_bitstring (const string& buf, bitset_value_type* v, size_t n);
+
+/// \class bitset ubitset.h ustl.h
+/// \ingroup Sequences
+///
+/// \brief bitset is a fixed-size block of memory with addressable bits.
+///
+/// Normally used for state flags; allows setting and unsetting of individual
+/// bits as well as bitwise operations on the entire set. The interface is
+/// most like that of unsigned integers, and is intended to be used as such.
+/// If you were using begin() and end() functions in STL's bitset, you would
+/// not be able to do the same thing here, because those functions return
+/// host type iterators, not bits.
+///
+template <size_t Size>
+class bitset {
+public:
+    typedef bitset_value_type	value_type;
+    typedef value_type*		pointer;
+    typedef const value_type*	const_pointer;
+    typedef pointer		iterator;
+    typedef const_pointer	const_iterator;
+    typedef size_t		difference_type;
+    typedef size_t		size_type;
+private:
+    static const size_t s_WordBits	= BitsInType (value_type);
+    static const size_t	s_nWords	= Size / s_WordBits + ((Size % s_WordBits) != 0);
+    static const size_t	s_nBits		= s_nWords * s_WordBits;
+private:
+    inline value_type&		BitRef (uoff_t n)	{ assert (n < Size); return (m_Bits [n / s_WordBits]); }
+    inline const value_type	BitRef (uoff_t n) const	{ assert (n < Size); return (m_Bits [n / s_WordBits]); }
+    inline const value_type	Mask (uoff_t n) const	{ assert (n < Size); return (1 << (n % s_WordBits)); }
+public:
+    inline		bitset (value_type v = 0)	{ fill_n (m_Bits, s_nWords, 0); m_Bits[0] = v; }
+    inline		bitset (const string& buf)	{ convert_from_bitstring (buf, m_Bits, s_nWords); }
+    inline void		flip (uoff_t n)			{ BitRef(n) ^= Mask(n); }
+    inline void		reset (void)			{ fill_n (m_Bits, s_nWords, 0); }
+    inline void		clear (void)			{ fill_n (m_Bits, s_nWords, 0); }
+    inline void		set (void)			{ fill_n (m_Bits, s_nWords, -1); }
+    inline bitset	operator~ (void) const		{ bitset rv (*this); rv.flip(); return (rv); }
+    inline size_type	size (void) const		{ return (Size); }
+    inline size_type	capacity (void) const		{ return (s_nBits); }
+    inline const bool	test (uoff_t n) const		{ return (BitRef(n) & Mask(n)); }
+    inline const bool	operator[] (uoff_t n) const	{ return (test(n)); }
+  inline const_iterator	begin (void) const		{ return (m_Bits); }
+    inline iterator	begin (void)			{ return (m_Bits); }
+  inline const_iterator	end (void) const		{ return (m_Bits + s_nWords); }
+    inline iterator	end (void)			{ return (m_Bits + s_nWords); }
+ 			/// Returns the value_type with the equivalent bits. If size() > 1, you'll get only the first BitsInType(value_type) bits.
+    inline const value_type	to_value (void) const		{ return (m_Bits[0]); }
+    			/// Flips all the bits in the set.
+    inline void		flip (void) { transform (begin(), end(), begin(), bitwise_not<value_type>()); }
+			/// Sets or clears bit \p n.
+    inline void		set (uoff_t n, bool val = true)
+			{
+			    value_type& br (BitRef (n));
+			    const value_type mask (Mask (n));
+			    const value_type bOn (br | mask), bOff (br & ~mask);
+			    br = val ? bOn : bOff;
+			}
+			// Sets the value of the bitrange \p first through \p last to the equivalent number of bits from \p v.
+    inline void		set (uoff_t first, uoff_t DebugArg(last), value_type v)
+			{
+#if !PLATFORM_ANDROID
+			    assert (size_t (distance (first, last)) <= s_WordBits && "Bit ranges must be 32 bits or smaller");
+			    assert (first / s_WordBits == last / s_WordBits && "Bit ranges can not cross dword (4 byte) boundary");
+			    assert ((v & BitMask(value_type,distance(first,last))) == v && "The value is too large to fit in the given bit range");
+#endif
+			    BitRef(first) |= v << (first % s_WordBits);
+			}
+    			/// Clears the bit \p n.
+    inline void		reset (uoff_t n)		{ set (n, false); }
+			/// Returns a string with bits MSB "001101001..." LSB.
+    inline string	to_string (void) const
+			{
+			    string rv (Size, '0');
+			    convert_to_bitstring (m_Bits, s_nWords, rv);
+			    return (rv);
+			}
+    inline value_type	at (uoff_t n) const		{ return (test(n)); }
+			/// Returns the value in bits \p first through \p last.
+    inline value_type	at (uoff_t first, uoff_t last) const
+			{
+			    assert (size_t (distance (first, last)) <= s_WordBits && "Bit ranges must be 32 bits or smaller");
+			    assert (first / s_WordBits == last / s_WordBits && "Bit ranges can not cross dword (4 byte) boundary");
+			    return ((BitRef(first) >> (first % s_WordBits)) & BitMask(value_type,distance(first, last)));
+			}
+    inline bool		any (void) const	{ value_type sum = 0; foreach (const_iterator, i, *this) sum |= *i; return (sum); }
+    inline bool		none (void) const	{ return (!any()); }
+    inline size_t	count (void) const	{ size_t sum = 0; foreach (const_iterator, i, *this) sum += popcount(*i); return (sum); }
+    inline bool		operator== (const bitset<Size>& v) const
+			    { return (s_nWords == 1 ? (m_Bits[0] == v.m_Bits[0]) : equal (begin(), end(), v.begin())); }
+    inline const bitset	operator& (const bitset<Size>& v)
+			    { bitset<Size> result; transform (begin(), end(), v.begin(), result.begin(), bitwise_and<value_type>()); return (result); }
+    inline const bitset	operator| (const bitset<Size>& v)
+			    { bitset<Size> result; transform (begin(), end(), v.begin(), result.begin(), bitwise_or<value_type>()); return (result); }
+    inline const bitset	operator^ (const bitset<Size>& v)
+			    { bitset<Size> result; transform (begin(), end(), v.begin(), result.begin(), bitwise_xor<value_type>()); return (result); }
+   inline const bitset&	operator&= (const bitset<Size>& v)
+			    { transform (begin(), end(), v.begin(), begin(), bitwise_and<value_type>()); return (*this); }
+   inline const bitset&	operator|= (const bitset<Size>& v)
+			    { transform (begin(), end(), v.begin(), begin(), bitwise_or<value_type>()); return (*this); }
+   inline const bitset&	operator^= (const bitset<Size>& v)
+			    { transform (begin(), end(), v.begin(), begin(), bitwise_xor<value_type>()); return (*this); }
+private:
+    value_type		m_Bits [s_nWords];
+};
+
+} // namespace ustl
+
+#endif
+
diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/uctralgo.h b/media/libdrm/mobile2/src/util/ustl-1.0/uctralgo.h
new file mode 100644
index 0000000..57f637d
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/ustl-1.0/uctralgo.h
@@ -0,0 +1,482 @@
+// This file is part of the ustl library, an STL implementation.
+//
+// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
+// This file is free software, distributed under the MIT License.
+//
+// \file uctralgo.h
+//
+// \brief Implementation of STL algorithms with container shortcuts.
+//
+// The function prototypes are copied
+// exactly from the SGI version of STL documentation along with comments about
+// their use. The code is NOT the same, though the functionality usually is.
+//
+
+#ifndef UCTRALGO_H_0D1AEDFA74B09791489FE25B1EC644B0
+#define UCTRALGO_H_0D1AEDFA74B09791489FE25B1EC644B0
+
+#include "uassert.h"
+
+namespace ustl {
+
+/// Copy copies elements from the range [first, last) to the range
+/// [result, result + (last - first)). That is, it performs the assignments
+/// *result = *first, *(result + 1) = *(first + 1), and so on. [1] Generally,
+/// for every integer n from 0 to last - first, copy performs the assignment
+/// *(result + n) = *(first + n). Assignments are performed in forward order,
+/// i.e. in order of increasing n. 
+/// \ingroup MutatingAlgorithms
+///
+template <typename Container, typename OutputIterator>
+inline OutputIterator copy (const Container& ctr, OutputIterator result)
+{
+    return (copy (ctr.begin(), ctr.end(), result));
+}
+
+/// Copy_if copies elements from the range [first, last) to the range
+/// [result, result + (last - first)) if pred(*i) returns true.
+/// \ingroup MutatingAlgorithms
+///
+template <typename Container, typename OutputIterator, typename Predicate>
+inline OutputIterator copy_if (Container& ctr, OutputIterator result, Predicate pred)
+{
+    return (copy_if (ctr.begin(), ctr.end(), result, pred));
+}
+
+/// For_each applies the function object f to each element in the range
+/// [first, last); f's return value, if any, is ignored. Applications are
+/// performed in forward order, i.e. from first to last. For_each returns
+/// the function object after it has been applied to each element.
+/// \ingroup MutatingAlgorithms
+///
+template <typename Container, typename UnaryFunction>
+inline UnaryFunction for_each (Container& ctr, UnaryFunction f)
+{
+    return (for_each (ctr.begin(), ctr.end(), f));
+}
+
+/// For_each applies the function object f to each element in the range
+/// [first, last); f's return value, if any, is ignored. Applications are
+/// performed in forward order, i.e. from first to last. For_each returns
+/// the function object after it has been applied to each element.
+/// \ingroup MutatingAlgorithms
+///
+template <typename Container, typename UnaryFunction>
+inline UnaryFunction for_each (const Container& ctr, UnaryFunction f)
+{
+    return (for_each (ctr.begin(), ctr.end(), f));
+}
+
+/// Returns the first iterator i in the range [first, last) such that
+/// *i == value. Returns last if no such iterator exists. 
+/// \ingroup SearchingAlgorithms
+///
+template <typename Container, typename EqualityComparable>
+inline typename Container::const_iterator find (const Container& ctr, const EqualityComparable& value)
+{
+    return (find (ctr.begin(), ctr.end(), value));
+}
+template <typename Container, typename EqualityComparable>
+inline typename Container::iterator find (Container& ctr, const EqualityComparable& value)
+{
+    return (find (ctr.begin(), ctr.end(), value));
+}
+
+/// Returns the first iterator i in the range [first, last) such that
+/// pred(*i) is true. Returns last if no such iterator exists.
+/// \ingroup SearchingAlgorithms
+///
+template <typename Container, typename Predicate>
+inline typename Container::const_iterator find_if (const Container& ctr, Predicate pred)
+{
+    return (find_if (ctr.begin(), ctr.end(), pred));
+}
+template <typename Container, typename Predicate>
+inline typename Container::iterator find_if (Container& ctr, Predicate pred)
+{
+    return (find_if (ctr.begin(), ctr.end(), pred));
+}
+
+/// Count finds the number of elements in [first, last) that are equal
+/// to value. More precisely, the first version of count returns the
+/// number of iterators i in [first, last) such that *i == value.
+/// \ingroup ConditionAlgorithms
+///
+template <typename Container, typename EqualityComparable>
+inline size_t count (const Container& ctr, const EqualityComparable& value)
+{
+    return (count (ctr.begin(), ctr.end(), value));
+}
+
+/// Count_if finds the number of elements in [first, last) that satisfy the
+/// predicate pred. More precisely, the first version of count_if returns the
+/// number of iterators i in [first, last) such that pred(*i) is true.
+/// \ingroup ConditionAlgorithms
+///
+template <typename Container, typename Predicate>
+inline size_t count_if (const Container& ctr, Predicate pred)
+{
+    return (count_if (ctr.begin(), ctr.end(), pred));
+}
+
+/// The first version of transform performs the operation op(*i) for each
+/// iterator i in the range [first, last), and assigns the result of that
+/// operation to *o, where o is the corresponding output iterator. That is,
+/// for each n such that 0 <= n < last - first, it performs the assignment
+/// *(result + n) = op(*(first + n)).
+/// The return value is result + (last - first).
+/// \ingroup MutatingAlgorithms
+///
+template <typename Container, typename UnaryFunction>
+inline void transform (Container& ctr, UnaryFunction op)
+{
+    transform (ctr.begin(), ctr.end(), ctr.begin(), op);
+}
+
+/// The first version of transform performs the operation op(*i) for each
+/// iterator i in the range [first, last), and assigns the result of that
+/// operation to *o, where o is the corresponding output iterator. That is,
+/// for each n such that 0 <= n < last - first, it performs the assignment
+/// *(result + n) = op(*(first + n)).
+/// The return value is result + (last - first).
+/// \ingroup MutatingAlgorithms
+///
+template <typename Container, typename OutputIterator, typename UnaryFunction>
+inline OutputIterator transform (Container& ctr, OutputIterator result, UnaryFunction op)
+{
+    return (transform (ctr.begin(), ctr.end(), result, op));
+}
+
+/// The second version of transform is very similar, except that it uses a
+/// Binary Function instead of a Unary Function: it performs the operation
+/// op(*i1, *i2) for each iterator i1 in the range [first1, last1) and assigns
+/// the result to *o, where i2 is the corresponding iterator in the second
+/// input range and where o is the corresponding output iterator. That is,
+/// for each n such that 0 <= n < last1 - first1, it performs the assignment
+/// *(result + n) = op(*(first1 + n), *(first2 + n).
+/// The return value is result + (last1 - first1).
+/// \ingroup MutatingAlgorithms
+///
+template <typename Container, typename InputIterator, typename OutputIterator, typename BinaryFunction>
+inline OutputIterator transform (Container& ctr, InputIterator first, OutputIterator result, BinaryFunction op)
+{
+    return (transform (ctr.begin(), ctr.end(), first, result, op));
+}
+
+/// Replace replaces every element in the range [first, last) equal to
+/// old_value with new_value. That is: for every iterator i,
+/// if *i == old_value then it performs the assignment *i = new_value.
+/// \ingroup MutatingAlgorithms
+///
+template <typename Container, typename T>
+inline void replace (Container& ctr, const T& old_value, const T& new_value)
+{
+    replace (ctr.begin(), ctr.end(), old_value, new_value);
+}
+
+/// Replace_if replaces every element in the range [first, last) for which
+/// pred returns true with new_value. That is: for every iterator i, if
+/// pred(*i) is true then it performs the assignment *i = new_value.
+/// \ingroup MutatingAlgorithms
+///
+template <typename Container, typename Predicate, typename T>
+inline void replace_if (Container& ctr, Predicate pred, const T& new_value)
+{
+    replace_if (ctr.begin(), ctr.end(), pred, new_value);
+}
+
+/// Replace_copy copies elements from the range [first, last) to the range
+/// [result, result + (last-first)), except that any element equal to old_value
+/// is not copied; new_value is copied instead. More precisely, for every
+/// integer n such that 0 <= n < last-first, replace_copy performs the
+/// assignment *(result+n) = new_value if *(first+n) == old_value, and
+/// *(result+n) = *(first+n) otherwise.
+/// \ingroup MutatingAlgorithms
+///
+template <typename Container, typename OutputIterator, typename T>
+inline OutputIterator replace_copy (const Container& ctr, OutputIterator result, const T& old_value, const T& new_value)
+{
+    return (replace_copy (ctr.begin(), ctr.end(), result, old_value, new_value));
+}
+
+/// Replace_copy_if copies elements from the range [first, last) to the range
+/// [result, result + (last-first)), except that any element for which pred is
+/// true is not copied; new_value is copied instead. More precisely, for every
+/// integer n such that 0 <= n < last-first, replace_copy_if performs the
+/// assignment *(result+n) = new_value if pred(*(first+n)),
+/// and *(result+n) = *(first+n) otherwise.
+/// \ingroup MutatingAlgorithms
+///
+template <typename Container, typename OutputIterator, typename Predicate, typename T>
+inline OutputIterator replace_copy_if (const Container& ctr, OutputIterator result, Predicate pred, const T& new_value) 
+{
+    return (replace_copy_if (ctr.begin(), ctr.end(), result, pred, new_value));
+}
+
+/// Fill assigns the value value to every element in the range [first, last).
+/// That is, for every iterator i in [first, last),
+/// it performs the assignment *i = value.
+/// \ingroup GeneratorAlgorithms
+///
+template <typename Container, typename T>
+inline void fill (Container& ctr, const T& value)
+{
+    fill (ctr.begin(), ctr.end(), value);
+}
+
+/// Generate assigns the result of invoking gen, a function object that
+/// takes no arguments, to each element in the range [first, last).
+/// \ingroup GeneratorAlgorithms
+///
+template <typename Container, typename Generator>
+inline void generate (Container& ctr, Generator gen)
+{
+    generate (ctr.begin(), ctr.end(), gen);
+}
+
+/// Randomly permute the elements of the container.
+/// \ingroup GeneratorAlgorithms
+///
+template <typename Container>
+inline void random_shuffle (Container& ctr)
+{
+    random_shuffle (ctr.begin(), ctr.end());
+}
+
+/// Remove_copy copies elements that are not equal to value from the range
+/// [first, last) to a range beginning at result. The return value is the
+/// end of the resulting range. This operation is stable, meaning that the
+/// relative order of the elements that are copied is the same as in the
+/// range [first, last).
+/// \ingroup MutatingAlgorithms
+///
+template <typename Container, typename OutputIterator, typename T>
+inline OutputIterator remove_copy (const Container& ctr, OutputIterator result, const T& value)
+{
+    return (remove_copy (ctr.begin(), ctr.end(), result, value));
+}
+
+/// Remove_copy_if copies elements from the range [first, last) to a range
+/// beginning at result, except that elements for which pred is true are not
+/// copied. The return value is the end of the resulting range. This operation
+/// is stable, meaning that the relative order of the elements that are copied
+/// is the same as in the range [first, last).
+/// \ingroup MutatingAlgorithms
+///
+template <typename Container, typename OutputIterator, typename Predicate>
+inline OutputIterator remove_copy_if (const Container& ctr, OutputIterator result, Predicate pred)
+{
+    return (remove_copy_if (ctr.begin(), ctr.end(), result, pred));
+}
+
+/// Remove removes from the range [first, last) all elements that are equal to
+/// value. That is, remove returns an iterator new_last such that the range
+/// [first, new_last) contains no elements equal to value. Remove is stable,
+/// meaning that the relative order of elements that are not equal to value is
+/// unchanged.
+/// \ingroup MutatingAlgorithms
+///
+template <typename Container, typename T>
+inline void remove (Container& ctr, const T& value)
+{
+    ctr.erase (remove_copy (ctr.begin(), ctr.end(), ctr.begin(), value), ctr.end());
+}
+
+/// Remove removes from the range [first, last) all elements that have an iterator
+/// in range [rfirst, rlast). The range is assumed to be sorted. That is, remove
+/// returns an iterator new_last such that the range [first, new_last) contains
+/// no elements whose iterators are in [rfirst, rlast). Remove is stable,
+/// meaning that the relative order of elements that are not equal to value is
+/// unchanged. This version of the algorithm is a uSTL extension.
+/// \ingroup MutatingAlgorithms
+///
+template <typename Container, typename ForwardIterator>
+inline void remove (Container& ctr, ForwardIterator rfirst, ForwardIterator rlast)
+{
+    ctr.erase (remove_copy (ctr.begin(), ctr.end(), ctr.begin(), rfirst, rlast), ctr.end());
+}
+
+/// Remove_if removes from the range [first, last) every element x such that
+/// pred(x) is true. That is, remove_if returns an iterator new_last such that
+/// the range [first, new_last) contains no elements for which pred is true.
+/// The iterators in the range [new_last, last) are all still dereferenceable,
+/// but the elements that they point to are unspecified. Remove_if is stable,
+/// meaning that the relative order of elements that are not removed is
+/// unchanged.
+/// \ingroup MutatingAlgorithms
+///
+template <typename Container, typename Predicate>
+inline void remove_if (Container& ctr, Predicate pred)
+{
+    ctr.erase (remove_copy_if (ctr.begin(), ctr.end(), ctr.begin(), pred), ctr.end());
+}
+
+/// Unique_copy copies elements from the range [first, last) to a range
+/// beginning with result, except that in a consecutive group of duplicate
+/// elements only the first one is copied. The return value is the end of
+/// the range to which the elements are copied. This behavior is similar
+/// to the Unix filter uniq.
+/// \ingroup MutatingAlgorithms
+///
+template <typename Container, typename OutputIterator>
+inline OutputIterator unique_copy (const Container& ctr, OutputIterator result)
+{
+    return (unique_copy (ctr.begin(), ctr.end(), result));
+}
+
+/// Every time a consecutive group of duplicate elements appears in the range
+/// [first, last), the algorithm unique removes all but the first element.
+/// That is, unique returns an iterator new_last such that the range [first,
+/// new_last) contains no two consecutive elements that are duplicates.
+/// The iterators in the range [new_last, last) are all still dereferenceable,
+/// but the elements that they point to are unspecified. Unique is stable,
+/// meaning that the relative order of elements that are not removed is
+/// unchanged.
+/// \ingroup MutatingAlgorithms
+///
+template <typename Container>
+inline void unique (Container& ctr)
+{
+    ctr.erase (unique_copy (ctr.begin(), ctr.end(), ctr.begin()), ctr.end());
+}
+
+/// Every time a consecutive group of duplicate elements appears in the range
+/// [first, last), the algorithm unique removes all but the first element.
+/// That is, unique returns an iterator new_last such that the range [first,
+/// new_last) contains no two consecutive elements that are duplicates.
+/// The iterators in the range [new_last, last) are all still dereferenceable,
+/// but the elements that they point to are unspecified. Unique is stable,
+/// meaning that the relative order of elements that are not removed is
+/// unchanged.
+/// \ingroup MutatingAlgorithms
+///
+template <typename Container, typename BinaryPredicate>
+inline void unique (Container& ctr, BinaryPredicate binary_pred)
+{
+    ctr.erase (unique_copy (ctr.begin(), ctr.end(), ctr.begin(), binary_pred), ctr.end());
+}
+
+/// Reverse reverses a range.
+/// That is: for every i such that 0 <= i <= (last - first) / 2),
+/// it exchanges *(first + i) and *(last - (i + 1)).
+/// \ingroup MutatingAlgorithms
+///
+template <typename Container>
+inline void reverse (Container& ctr)
+{
+    reverse (ctr.begin(), ctr.end());
+}
+
+/// Exchanges ranges [first, middle) and [middle, last)
+/// \ingroup MutatingAlgorithms
+///
+template <typename Container>
+inline void rotate (Container& ctr, off_t offset)
+{
+    assert (size_t(offset > 0 ? offset : -offset) < ctr.size());
+    if (offset > 0)
+	rotate (ctr.begin(), ctr.end() - offset, ctr.end());
+    else
+	rotate (ctr.begin(), ctr.begin() - offset, ctr.end());
+}
+
+/// Returns the furthermost iterator i in [first, last) such that,
+/// for every iterator j in [first, i), *j < value
+/// Assumes the range is sorted.
+/// \ingroup SearchingAlgorithms
+///
+template <typename Container, typename LessThanComparable>
+inline typename Container::const_iterator lower_bound (const Container& ctr, const LessThanComparable& value)
+{
+    return (lower_bound (ctr.begin(), ctr.end(), value));
+}
+template <typename Container, typename LessThanComparable>
+inline typename Container::iterator lower_bound (Container& ctr, const LessThanComparable& value)
+{
+    return (lower_bound (ctr.begin(), ctr.end(), value));
+}
+
+/// Returns the furthermost iterator i in [first,last) such that for
+/// every iterator j in [first,i), value < *j is false.
+/// \ingroup SearchingAlgorithms
+///
+template <typename Container, typename LessThanComparable>
+inline typename Container::const_iterator upper_bound (const Container& ctr, const LessThanComparable& value)
+{
+    return (upper_bound (ctr.begin(), ctr.end(), value));
+}
+template <typename Container, typename LessThanComparable>
+inline typename Container::iterator upper_bound (Container& ctr, const LessThanComparable& value)
+{
+    return (upper_bound (ctr.begin(), ctr.end(), value));
+}
+
+/// Performs a binary search for \p value.
+/// Assumes the range is sorted.
+/// \ingroup SearchingAlgorithms
+///
+template <typename Container>
+inline typename Container::const_iterator binary_search (const Container& ctr, const typename Container::value_type& value)
+{
+    return (binary_search (ctr.begin(), ctr.end(), value));
+}
+template <typename Container>
+inline typename Container::iterator binary_search (Container& ctr, const typename Container::value_type& value)
+{
+    return (binary_search (ctr.begin(), ctr.end(), value));
+}
+
+/// Returns pair<lower_bound,upper_bound>
+/// \ingroup SearchingAlgorithms
+///
+template <typename Container, typename LessThanComparable>
+inline pair<typename Container::const_iterator,typename Container::const_iterator> equal_range (const Container& ctr, const LessThanComparable& value)
+{
+    return (equal_range (ctr.begin(), ctr.end(), value));
+}
+template <typename Container, typename LessThanComparable>
+inline pair<typename Container::iterator,typename Container::iterator> equal_range (Container& ctr, const LessThanComparable& value)
+{
+    return (equal_range (ctr.begin(), ctr.end(), value));
+}
+
+/// Sorts the container
+/// \ingroup SortingAlgorithms
+///
+template <typename Container>
+inline void sort (Container& ctr)
+{
+    sort (ctr.begin(), ctr.end());
+}
+
+/// Sorts the container
+/// \ingroup SortingAlgorithms
+///
+template <typename Container, typename Compare>
+inline void sort (Container& ctr, Compare comp)
+{
+    sort (ctr.begin(), ctr.end(), comp);
+}
+
+/// Sorts the container
+/// \ingroup SortingAlgorithms
+///
+template <typename Container>
+inline void stable_sort (Container& ctr)
+{
+    stable_sort (ctr.begin(), ctr.end());
+}
+
+/// Sorts the container
+/// \ingroup SortingAlgorithms
+///
+template <typename Container, typename Compare>
+inline void stable_sort (Container& ctr, Compare comp)
+{
+    stable_sort (ctr.begin(), ctr.end(), comp);
+}
+
+} // namespace ustl
+
+#endif
+
diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/uctrstrm.h b/media/libdrm/mobile2/src/util/ustl-1.0/uctrstrm.h
new file mode 100644
index 0000000..39ddcdd
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/ustl-1.0/uctrstrm.h
@@ -0,0 +1,177 @@
+// This file is part of the ustl library, an STL implementation.
+//
+// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
+// This file is free software, distributed under the MIT License.
+//
+/// \file uctrstrm.h
+///
+/// \brief Serialization templates for standard containers.
+/// Because containers are templates, a single operator>> is impossible.
+/// Making virtual read/write is also impossible because not all containers
+/// contain serializable elements. Therefore, use the macros in this file.
+///
+
+#ifndef UCTRSTRM_H_75B2C3EA4980DDDC6B6DFFF767A3B7AC
+#define UCTRSTRM_H_75B2C3EA4980DDDC6B6DFFF767A3B7AC
+
+#include "mistream.h"
+#include "sostream.h"
+#include "uiosfunc.h"
+
+namespace ustl {
+
+//----------------------------------------------------------------------
+// Macros for easily declaring a container streamable.
+//----------------------------------------------------------------------
+
+/// \brief Declares container template \p type streamable.
+///
+/// Use TEMPLATE_TYPE and TEMPLATE_DECL macros to pass in templated
+/// type with commas and the template declaration.
+///
+#define STD_TEMPLATE_CTR_STREAMABLE(type, template_decl)	\
+    template_decl						\
+    inline istream& operator>> (istream& is, type& v)		\
+    { return (container_read (is, v)); } 			\
+    template_decl						\
+    inline ostream& operator<< (ostream& os, const type& v)	\
+    { return (container_write (os, v)); } 			\
+    template_decl						\
+    inline ostringstream& operator<< (ostringstream& os, const type& v)	\
+    { return (container_text_write (os, v)); }			\
+    template_decl						\
+    inline size_t stream_size_of (const type& v)		\
+    { return (container_stream_size (v)); }
+
+/// \brief Declares non-resizable container template \p type streamable.
+#define STD_TEMPLATE_NR_CTR_STREAMABLE(type, template_decl)	\
+    template_decl						\
+    inline istream& operator>> (istream& is, type& v)		\
+    { return (nr_container_read (is, v)); } 			\
+    template_decl						\
+    inline ostream& operator<< (ostream& os, const type& v)	\
+    { return (nr_container_write (os, v)); } 			\
+    template_decl						\
+    inline ostringstream& operator<< (ostringstream& os, const type& v)	\
+    { return (container_text_write (os, v)); }			\
+    template_decl						\
+    inline size_t stream_size_of (const type& v)		\
+    { return (nr_container_stream_size (v)); }
+
+//----------------------------------------------------------------------
+// Fixed size container serialization.
+//----------------------------------------------------------------------
+
+/// Reads fixed size container \p v from stream \p is.
+template <typename Container>
+inline istream& nr_container_read (istream& is, Container& v)
+{
+    foreach (typename Container::iterator, i, v)
+	is >> *i;
+    return (is);
+}
+
+/// Writes fixed size container \p v into stream \p os.
+template <typename Container>
+inline ostream& nr_container_write (ostream& os, const Container& v)
+{
+    foreach (typename Container::const_iterator, i, v)
+	os << *i;
+    return (os);
+}
+
+/// Computes the stream size of a fixed size standard container.
+template <typename Container>
+size_t nr_container_stream_size (const Container& v)
+{
+    typedef typename Container::const_iterator vciter_t;
+    typedef typename iterator_traits<vciter_t>::value_type value_type;
+    size_t s = 0;
+    if (numeric_limits<value_type>::is_integral)
+	s += v.size() * stream_size_of(value_type());
+    else
+	foreach (vciter_t, i, v)
+	    s += stream_size_of(*i);
+    return (s);
+}
+
+//----------------------------------------------------------------------
+// Resizable container serialization.
+//----------------------------------------------------------------------
+
+/// Reads container \p v from stream \p is.
+template <typename Container>
+istream& container_read (istream& is, Container& v)
+{
+    typedef typename Container::value_type value_type;
+    typedef typename Container::iterator iterator;
+    typedef typename Container::written_size_type written_size_type;
+    written_size_type n;
+    is >> n;
+    const size_t expectedSize = n * stream_size_of(value_type());
+#if !PLATFORM_ANDROID
+    is.verify_remaining ("read", typeid(v).name(), expectedSize);
+#endif
+    if (alignof(value_type()) > alignof(n))
+	is >> ios::talign<value_type>();
+    v.resize (n);
+    nr_container_read (is, v);
+    is >> ios::talign<written_size_type>();
+    return (is);
+}
+
+/// Writes the vector to stream \p os.
+template <typename Container>
+ostream& container_write (ostream& os, const Container& v)
+{
+    typedef typename Container::value_type value_type;
+    typedef typename Container::written_size_type written_size_type;
+    const written_size_type sz (v.size());
+    os << sz;
+    if (alignof(value_type()) > alignof(sz))
+	os << ios::talign<value_type>();
+    nr_container_write (os, v);
+    os << ios::talign<written_size_type>();
+    return (os);
+}
+
+/// Computes the stream size of a standard container.
+template <typename Container>
+size_t container_stream_size (const Container& v)
+{
+    typedef typename Container::value_type value_type;
+    typedef typename Container::written_size_type written_size_type;
+    const written_size_type sz (v.size());
+    size_t sizeSize = stream_size_of (sz);
+    if (alignof(value_type()) > alignof(sz))
+	sizeSize = Align (sizeSize, alignof(value_type()));
+    return (Align (sizeSize + nr_container_stream_size (v), alignof(sz)));
+}
+
+/// \brief Writes element \p v into stream \p os as text.
+/// Specialize to custom print elements.
+template <typename T>
+inline ostringstream& container_element_text_write (ostringstream& os, const T& v)
+{ return (os << v); }
+
+/// Writes container \p v into stream \p os as text.
+template <typename Container>
+ostringstream& container_text_write (ostringstream& os, const Container& v)
+{
+    typename Container::const_iterator i = v.begin();
+    os << '(';
+    while (i < v.end()) {
+	container_element_text_write (os, *i);
+	if (++i >= v.end()) break;
+	os << ',';
+    }
+    os << ')';
+    return (os);
+}
+
+//----------------------------------------------------------------------
+
+} // namespace ustl
+
+#endif
+
diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/uexception.cpp b/media/libdrm/mobile2/src/util/ustl-1.0/uexception.cpp
new file mode 100644
index 0000000..d00f219
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/ustl-1.0/uexception.cpp
@@ -0,0 +1,305 @@
+// This file is part of the ustl library, an STL implementation.
+//
+// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
+// This file is free software, distributed under the MIT License.
+//
+// uexception.cc
+//
+
+#include "uassert.h"
+#include "uexception.h"
+#include "ustring.h"
+#include "mistream.h"
+#include "sostream.h"
+#include "strmsize.h"
+#include "uspecial.h"
+#include <errno.h>
+#if __GNUC__ >= 3 && !PLATFORM_ANDROID
+    #include <cxxabi.h>
+#endif
+
+namespace ustl {
+
+//----------------------------------------------------------------------
+
+/// \brief Returns a descriptive error message. fmt="%s"
+/// Overloads of this functions must set NULL as the default fmt
+/// argument and handle that case to provide a default format string
+/// in case the user does not have a localized one. The format
+/// string should be shown in the documentation to not require
+/// translators to look through code. Also, this function must
+/// not throw anything, so you must wrap memory allocation routines
+/// (like string::format, for instance) in a try{}catch(...){} block.
+///
+void exception::info (string& msgbuf, const char*) const throw()
+{
+#if PLATFORM_ANDROID
+    msgbuf.format ("%s", what());
+#else /* !PLATFORM_ANDROID */
+    try { msgbuf.format ("%s", what()); } catch (...) { /* Ignore all exceptions */ }
+#endif
+}
+
+/// Reads the exception from stream \p is.
+void exception::read (istream& is)
+{
+    uint32_t stmSize;
+    xfmt_t fmt;
+    is >> fmt >> stmSize >> m_Backtrace;
+    assert (fmt == m_Format && "The saved exception is of a different type.");
+    assert (stmSize - exception::stream_size() <= is.remaining() && "The saved exception data is corrupt.");
+    m_Format = fmt;
+}
+
+/// Writes the exception into stream \p os as an IFF chunk.
+void exception::write (ostream& os) const
+{
+    os << m_Format << uint32_t(stream_size()) << m_Backtrace;
+}
+
+/// Writes the exception as text into stream \p os.
+void exception::text_write (ostringstream& os) const
+{
+#if !PLATFORM_ANDROID
+    try {
+#endif
+	string buf;
+	info (buf);
+	os << buf;
+#if !PLATFORM_ANDROID
+    } catch (...) {}
+#endif
+}
+
+//----------------------------------------------------------------------
+
+/// Initializes the empty object. \p nBytes is the size of the attempted allocation.
+bad_alloc::bad_alloc (size_t nBytes) throw()
+: ustl::exception(),
+  m_nBytesRequested (nBytes)
+{
+    set_format (xfmt_BadAlloc);
+}
+
+/// Returns a descriptive error message. fmt="failed to allocate %d bytes"
+void bad_alloc::info (string& msgbuf, const char* fmt) const throw()
+{
+    if (!fmt) fmt = "failed to allocate %d bytes";
+#if PLATFORM_ANDROID
+    msgbuf.format (fmt, m_nBytesRequested);
+#else /* !PLATFORM_ANDROID */
+    try { msgbuf.format (fmt, m_nBytesRequested); } catch (...) {}
+#endif
+}
+
+/// Reads the exception from stream \p is.
+void bad_alloc::read (istream& is)
+{
+    ustl::exception::read (is);
+    is >> m_nBytesRequested;
+}
+
+/// Writes the exception into stream \p os.
+void bad_alloc::write (ostream& os) const
+{
+    ustl::exception::write (os);
+    os << m_nBytesRequested;
+}
+
+/// Returns the size of the written exception.
+size_t bad_alloc::stream_size (void) const
+{
+    return (ustl::exception::stream_size() + stream_size_of(m_nBytesRequested));
+}
+
+//----------------------------------------------------------------------
+
+/// Initializes the empty object. \p operation is the function that returned the error code.
+libc_exception::libc_exception (const char* operation) throw()
+: exception(),
+  m_Errno (errno),
+  m_Operation (operation)
+{
+    set_format (xfmt_LibcException);
+}
+
+/// Copies object \p v.
+libc_exception::libc_exception (const libc_exception& v) throw()
+: exception (v),
+  m_Errno (v.m_Errno),
+  m_Operation (v.m_Operation)
+{
+}
+
+/// Copies object \p v.
+const libc_exception& libc_exception::operator= (const libc_exception& v)
+{
+    m_Errno = v.m_Errno;
+    m_Operation = v.m_Operation;
+    return (*this);
+}
+
+/// Returns a descriptive error message. fmt="%s: %m"
+void libc_exception::info (string& msgbuf, const char* fmt) const throw()
+{
+    if (!fmt) fmt = "%s: %m";
+#if PLATFORM_ANDROID
+    msgbuf.format (fmt, m_Operation, m_Errno, m_Errno);
+#else /* !PLATFORM_ANDROID */
+    try { msgbuf.format (fmt, m_Operation, m_Errno, m_Errno); } catch (...) {}
+#endif
+}
+
+/// Reads the exception from stream \p is.
+void libc_exception::read (istream& is)
+{
+    exception::read (is);
+    is >> m_Errno >> m_Operation;
+}
+
+/// Writes the exception into stream \p os.
+void libc_exception::write (ostream& os) const
+{
+    exception::write (os);
+    os << m_Errno << m_Operation;
+}
+
+/// Returns the size of the written exception.
+size_t libc_exception::stream_size (void) const
+{
+    return (exception::stream_size() +
+	    stream_size_of(m_Errno) +
+	    stream_size_of(m_Operation));
+}
+
+//----------------------------------------------------------------------
+
+/// Initializes the empty object. \p operation is the function that returned the error code.
+file_exception::file_exception (const char* operation, const char* filename) throw()
+: libc_exception (operation)
+{
+    memset (m_Filename, 0, VectorSize(m_Filename));
+    set_format (xfmt_FileException);
+    if (filename) {
+	strncpy (m_Filename, filename, VectorSize(m_Filename));
+	m_Filename [VectorSize(m_Filename) - 1] = 0;
+    }
+}
+
+/// Returns a descriptive error message. fmt="%s %s: %m"
+void file_exception::info (string& msgbuf, const char* fmt) const throw()
+{
+    if (!fmt) fmt = "%s %s: %m";
+#if PLATFORM_ANDROID
+    msgbuf.format (fmt, m_Operation, m_Filename, m_Errno, m_Errno);
+#else /* !PLATFORM_ANDROID */
+    try { msgbuf.format (fmt, m_Operation, m_Filename, m_Errno, m_Errno); } catch (...) {}
+#endif
+}
+
+/// Reads the exception from stream \p is.
+void file_exception::read (istream& is)
+{
+    libc_exception::read (is);
+    string filename;
+    is >> filename;
+    is.align (8);
+    filename.copyto (filename, VectorSize(m_Filename));
+}
+
+/// Writes the exception into stream \p os.
+void file_exception::write (ostream& os) const
+{
+    libc_exception::write (os);
+    os << string (m_Filename);
+    os.align (8);
+}
+
+/// Returns the size of the written exception.
+size_t file_exception::stream_size (void) const
+{
+    return (libc_exception::stream_size() +
+	    Align (stream_size_of (string (m_Filename)), 8));
+}
+
+//----------------------------------------------------------------------
+
+/// \brief Uses C++ ABI call, if available to demangle the contents of \p buf.
+///
+/// The result is written to \p buf, with the maximum size of \p bufSize, and
+/// is zero-terminated. The return value is \p buf.
+///
+const char* demangle_type_name (char* buf, size_t bufSize, size_t* pdmSize)
+{
+    size_t bl = strlen (buf);
+#if __GNUC__ >= 3 && !PLATFORM_ANDROID
+    char dmname [256];
+    size_t sz = VectorSize(dmname);
+    int bFailed;
+    abi::__cxa_demangle (buf, dmname, &sz, &bFailed);
+    if (!bFailed) {
+	bl = min (strlen (dmname), bufSize - 1);
+	memcpy (buf, dmname, bl);
+	buf[bl] = 0;
+    }
+#else
+    bl = min (bl, bufSize);
+#endif
+    if (pdmSize)
+	*pdmSize = bl;
+    return (buf);
+}
+
+//----------------------------------------------------------------------
+
+/// Initializes the empty object. \p operation is the function that returned the error code.
+stream_bounds_exception::stream_bounds_exception (const char* operation, const char* type, uoff_t offset, size_t expected, size_t remaining) throw()
+: libc_exception (operation),
+  m_TypeName (type),
+  m_Offset (offset),
+  m_Expected (expected),
+  m_Remaining (remaining)
+{
+    set_format (xfmt_StreamBoundsException);
+}
+
+/// Returns a descriptive error message. fmt="%s stream %s: @%u: expected %u, available %u";
+void stream_bounds_exception::info (string& msgbuf, const char* fmt) const throw()
+{
+    char typeName [256];
+    strncpy (typeName, m_TypeName, VectorSize(typeName));
+    typeName[VectorSize(typeName)-1] = 0;
+    if (!fmt) fmt = "%s stream %s: @0x%X: need %u bytes, have %u";
+#if PLATFORM_ANDROID
+    msgbuf.format (fmt, demangle_type_name (VectorBlock(typeName)), m_Operation, m_Offset, m_Expected, m_Remaining);
+#else /* !PLATFORM_ANDROID */
+    try { msgbuf.format (fmt, demangle_type_name (VectorBlock(typeName)), m_Operation, m_Offset, m_Expected, m_Remaining); } catch (...) {}
+#endif
+}
+
+/// Reads the exception from stream \p is.
+void stream_bounds_exception::read (istream& is)
+{
+    libc_exception::read (is);
+    is >> m_TypeName >> m_Offset >> m_Expected >> m_Remaining;
+}
+
+/// Writes the exception into stream \p os.
+void stream_bounds_exception::write (ostream& os) const
+{
+    libc_exception::write (os);
+    os << m_TypeName << m_Offset << m_Expected << m_Remaining;
+}
+
+/// Returns the size of the written exception.
+size_t stream_bounds_exception::stream_size (void) const
+{
+    return (libc_exception::stream_size() +
+	    stream_size_of(m_TypeName) +
+	    stream_size_of(m_Offset) +
+	    stream_size_of(m_Expected) +
+	    stream_size_of(m_Remaining));
+}
+
+} // namespace ustl
+
diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/uexception.h b/media/libdrm/mobile2/src/util/ustl-1.0/uexception.h
new file mode 100644
index 0000000..3e9a179
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/ustl-1.0/uexception.h
@@ -0,0 +1,194 @@
+// This file is part of the ustl library, an STL implementation.
+//
+// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
+// This file is free software, distributed under the MIT License.
+//
+// uexception.h
+//
+// This file contains stuff from \<exception\>.
+// The standard C++ headers are duplicated because uSTL is intended
+// to completely replace all C++ standard library functions.
+//
+
+#ifndef UEXCEPTION_H_18DE3EF55C4F00673268F0D66546AF5D
+#define UEXCEPTION_H_18DE3EF55C4F00673268F0D66546AF5D
+
+#include "utypes.h"
+#ifndef WITHOUT_LIBSTDCPP
+    #include <exception>
+    #include <new>
+#endif
+#include "bktrace.h"
+
+#ifdef WITHOUT_LIBSTDCPP	// This code is copied from <exception>
+namespace std {
+/// If you write a replacement terminate handler, it must be of this type.
+typedef void (*terminate_handler) (void);
+/// If you write a replacement unexpected handler, it must be of this type.
+typedef void (*unexpected_handler) (void);
+/// Takes a new handler function as an argument, returns the old function.
+terminate_handler set_terminate (terminate_handler pHandler) throw();
+/// The runtime will call this function if exception handling must be
+/// abandoned for any reason.  It can also be called by the user.
+void terminate (void) __attribute__ ((__noreturn__));
+/// Takes a new handler function as an argument, returns the old function.
+unexpected_handler set_unexpected (unexpected_handler pHandler) throw();
+/// The runtime will call this function if an exception is thrown which
+/// violates the function's exception specification.
+void unexpected (void) __attribute__ ((__noreturn__));
+/// Returns true when the caught exception violates the throw specification.
+bool uncaught_exception() throw();
+} // namespace std
+#endif
+
+namespace ustl {
+
+class string;
+
+typedef uint32_t	xfmt_t;
+
+enum {
+    xfmt_Exception,
+    xfmt_BadAlloc,
+    xfmt_LibcException		= 12,
+    xfmt_FileException		= 13,
+    xfmt_StreamBoundsException	= 14
+};
+
+/// \class exception uexception.h ustl.h
+/// \ingroup Exceptions
+///
+/// \brief Base class for exceptions, equivalent to std::exception.
+///
+#ifdef WITHOUT_LIBSTDCPP
+class exception {
+#else
+class exception : public std::exception {
+#endif
+public:
+    typedef const CBacktrace& rcbktrace_t;
+public:
+    inline		exception (void) throw() : m_Format (xfmt_Exception) {}
+    inline virtual     ~exception (void) throw() {}
+    inline virtual const char* what (void) const throw() { return ("error"); }
+    virtual void	info (string& msgbuf, const char* fmt = NULL) const throw();
+    virtual void	read (istream& is);
+    virtual void	write (ostream& os) const;
+    void		text_write (ostringstream& os) const;
+    inline virtual size_t stream_size (void) const { return (sizeof(m_Format) + sizeof(uint32_t) + m_Backtrace.stream_size()); }
+    /// Format of the exception is used to lookup exception::info format string.
+    /// Another common use is the instantiation of serialized exceptions, used
+    /// by the error handler node chain to troubleshoot specific errors.
+    inline xfmt_t	format (void) const	{ return (m_Format); }
+    inline rcbktrace_t	backtrace (void) const	{ return (m_Backtrace); }
+protected:
+    inline void		set_format (xfmt_t fmt) { m_Format = fmt; }
+private:
+    CBacktrace		m_Backtrace;	///< Backtrace of the throw point.
+    xfmt_t		m_Format;	///< Format of the exception's data.
+};
+
+/// \class bad_cast uexception.h ustl.h
+/// \ingroup Exceptions
+///
+/// \brief Thrown to indicate a bad dynamic_cast usage.
+///
+class bad_cast : public exception {
+public:
+    inline explicit		bad_cast (void) throw() : exception() {}
+    inline virtual const char*	what (void) const throw() { return ("bad cast"); }
+};
+
+//----------------------------------------------------------------------
+
+/// \class bad_alloc uexception.h ustl.h
+/// \ingroup Exceptions
+///
+/// \brief Exception thrown on memory allocation failure by memblock::reserve.
+///
+#ifdef WITHOUT_LIBSTDCPP
+class bad_alloc : public exception {
+#else
+class bad_alloc : public std::bad_alloc, public exception {
+#endif
+public:
+    explicit		bad_alloc (size_t nBytes = 0) throw();
+    inline virtual const char*	what (void) const throw() { return ("memory allocation failed"); }
+    virtual void	info (string& msgbuf, const char* fmt = NULL) const throw();
+    virtual void	read (istream& is);
+    virtual void	write (ostream& os) const;
+    virtual size_t	stream_size (void) const;
+protected:
+    size_t		m_nBytesRequested;	///< Number of bytes requested by the failed allocation.
+};
+
+/// \class libc_exception uexception.h ustl.h
+/// \ingroup Exceptions
+///
+/// \brief Thrown when a libc function returns an error.
+///
+/// Contains an errno and description. This is a uSTL extension.
+///
+class libc_exception : public exception {
+public:
+    explicit		libc_exception (const char* operation) throw();
+			libc_exception (const libc_exception& v) throw();
+    const libc_exception& operator= (const libc_exception& v);
+    inline virtual const char*	what (void) const throw() { return ("libc function failed"); }
+    virtual void	info (string& msgbuf, const char* fmt = NULL) const throw();
+    virtual void	read (istream& is);
+    virtual void	write (ostream& os) const;
+    virtual size_t	stream_size (void) const;
+protected:
+    intptr_t		m_Errno;		///< Error code returned by the failed operation.
+    const char*		m_Operation;		///< Name of the failed operation.
+};
+
+/// \class file_exception uexception.h ustl.h
+/// \ingroup Exceptions
+///
+/// \brief File-related exceptions.
+///
+/// Contains the file name. This is a uSTL extension.
+///
+class file_exception : public libc_exception {
+public:
+			file_exception (const char* operation, const char* filename) throw();
+    inline virtual const char* what (void) const throw() { return ("file error"); }
+    virtual void	info (string& msgbuf, const char* fmt = NULL) const throw();
+    virtual void	read (istream& is);
+    virtual void	write (ostream& os) const;
+    virtual size_t	stream_size (void) const;
+protected:
+    char		m_Filename [PATH_MAX];	///< Name of the file causing the error.
+};
+
+/// \class stream_bounds_exception uexception.h ustl.h
+/// \ingroup Exceptions
+///
+/// \brief Stream bounds checking.
+///
+/// Only thrown in debug builds unless you say otherwise in config.h
+/// This is a uSTL extension.
+///
+class stream_bounds_exception : public libc_exception {
+public:
+			stream_bounds_exception (const char* operation, const char* type, uoff_t offset, size_t expected, size_t remaining) throw();
+    inline virtual const char*	what (void) const throw() { return ("stream bounds exception"); }
+    virtual void	info (string& msgbuf, const char* fmt = NULL) const throw();
+    virtual void	read (istream& is);
+    virtual void	write (ostream& os) const;
+    virtual size_t	stream_size (void) const;
+protected:
+    const char*		m_TypeName;
+    uoff_t		m_Offset;
+    size_t		m_Expected;
+    size_t		m_Remaining;
+};
+
+const char* demangle_type_name (char* buf, size_t bufSize, size_t* pdmSize = NULL);
+
+} // namespace ustl
+
+#endif
+
diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/ufunction.h b/media/libdrm/mobile2/src/util/ustl-1.0/ufunction.h
new file mode 100644
index 0000000..53dc5e2
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/ustl-1.0/ufunction.h
@@ -0,0 +1,480 @@
+// This file is part of the ustl library, an STL implementation.
+//
+// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
+// This file is free software, distributed under the MIT License.
+//
+// \file ufunction.h
+//
+// \brief Implements STL standard functors.
+//
+// See STL specification and bvts for usage of these. The only
+// extension is the mem_var functors for member variable access:
+// \code
+//	f = find_if (ctr, mem_var_equal_to(&MyClass::m_Var, matchVar));
+//	f = find_if (ctr, mem_var_less(&MyClass::m_Var, matchVar));
+// \endcode
+// There are a couple of others but the syntax is much harder to grasp.
+// See bvt10.cc for more examples.
+//
+
+#ifndef UFUNCTION_H_221ABA8551801799263C927234C085F3
+#define UFUNCTION_H_221ABA8551801799263C927234C085F3
+
+namespace ustl {
+
+//----------------------------------------------------------------------
+// Standard functors
+//----------------------------------------------------------------------
+
+/// \brief void-returning function abstract interface.
+/// \ingroup FunctorObjects
+template <typename Result>
+struct void_function {
+    typedef Result	result_type;
+};
+
+/// \brief \p Result f (\p Arg) function abstract interface.
+/// \ingroup FunctorObjects
+template <typename Arg, typename Result>
+struct unary_function {
+    typedef Arg		argument_type;
+    typedef Result	result_type;
+};
+
+/// \brief \p Result f (\p Arg1, \p Arg2) function abstract interface.
+/// \ingroup FunctorObjects
+template <typename Arg1, typename Arg2, typename Result>
+struct binary_function {
+    typedef Arg1	first_argument_type;
+    typedef Arg2	second_argument_type;
+    typedef Result	result_type;
+};
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+#define STD_BINARY_FUNCTOR(name, rv, func)	\
+template <class T> struct name : public binary_function<T,T,rv> \
+{ inline rv operator()(const T& a, const T& b) const { return func; } };
+#define STD_UNARY_FUNCTOR(name, rv, func)	\
+template <class T> struct name : public unary_function<T,rv> \
+{ inline rv operator()(const T& a) const { return func; } };
+#define STD_CONVERSION_FUNCTOR(name, func)	\
+template <class S, class D> struct name : public unary_function<S,D> \
+{ inline D operator()(const S& a) const { return func; } };
+
+STD_BINARY_FUNCTOR (plus,		T,	(a + b))
+STD_BINARY_FUNCTOR (minus,		T,	(a - b))
+STD_BINARY_FUNCTOR (divides,		T,	(a / b))
+STD_BINARY_FUNCTOR (modulus,		T,	(a % b))
+STD_BINARY_FUNCTOR (multiplies,		T,	(a * b))
+STD_BINARY_FUNCTOR (logical_and,	T,	(a && b))
+STD_BINARY_FUNCTOR (logical_or,		T,	(a || b))
+STD_UNARY_FUNCTOR  (logical_not,	T,	(!a))
+STD_BINARY_FUNCTOR (bitwise_or,		T,	(a | b))
+STD_BINARY_FUNCTOR (bitwise_and,	T,	(a & b))
+STD_BINARY_FUNCTOR (bitwise_xor,	T,	(a ^ b))
+STD_UNARY_FUNCTOR  (bitwise_not,	T,	(~a))
+STD_UNARY_FUNCTOR  (negate,		T,	(-a))
+STD_BINARY_FUNCTOR (equal_to,		bool,	(a == b))
+STD_BINARY_FUNCTOR (not_equal_to,	bool,	(!(a == b)))
+STD_BINARY_FUNCTOR (greater,		bool,	(b < a))
+STD_BINARY_FUNCTOR (less,		bool,	(a < b))
+STD_BINARY_FUNCTOR (greater_equal,	bool,	(!(a < b)))
+STD_BINARY_FUNCTOR (less_equal,		bool,	(!(b < a)))
+STD_BINARY_FUNCTOR (compare,		int,	(a < b ? -1 : (b < a)))
+STD_UNARY_FUNCTOR  (identity,		T,	(a))
+
+#endif // DOXYGEN_SHOULD_SKIP_THIS
+
+/// \brief Selects and returns the first argument.
+/// \ingroup FunctorObjects
+template <class T1, class T2> struct project1st	: public binary_function<T1,T2,T1>    { inline const T1& operator()(const T1& a, const T2&) const { return (a); } };
+/// \brief Selects and returns the second argument.
+/// \ingroup FunctorObjects
+template <class T1, class T2> struct project2nd	: public binary_function<T1,T2,T2>    { inline const T2& operator()(const T1&, const T2& a) const { return (a); } };
+
+//----------------------------------------------------------------------
+// Generic function to functor converters.
+//----------------------------------------------------------------------
+
+/// \brief Wrapper object for unary function pointers.
+/// Use the \ref ptr_fun accessor to create this object.
+/// \ingroup FunctorObjects
+template <typename Arg, typename Result>
+class pointer_to_unary_function : public unary_function<Arg,Result> {
+public:
+    typedef Arg		argument_type;
+    typedef Result	result_type;
+    typedef Result	(*pfunc_t)(Arg);
+public:
+    explicit inline	pointer_to_unary_function (pfunc_t pfn) : m_pfn (pfn) {}
+    inline result_type	operator() (argument_type v) const { return (m_pfn(v)); }
+private:
+    pfunc_t		m_pfn;	///< Pointer to the wrapped function.
+};
+
+/// \brief Wrapper object for binary function pointers.
+/// Use the \ref ptr_fun accessor to create this object.
+/// \ingroup FunctorObjects
+template <typename Arg1, typename Arg2, typename Result>
+class pointer_to_binary_function : public binary_function<Arg1,Arg2,Result> {
+public:
+    typedef Arg1	first_argument_type;
+    typedef Arg2	second_argument_type;
+    typedef Result	result_type;
+    typedef Result	(*pfunc_t)(Arg1, Arg2);
+public:
+    explicit inline	pointer_to_binary_function (pfunc_t pfn) : m_pfn (pfn) {}
+    inline result_type	operator() (first_argument_type v1, second_argument_type v2) const { return (m_pfn(v1, v2)); }
+private:
+    pfunc_t		m_pfn;	///< Pointer to the wrapped function.
+};
+
+/// ptr_fun(pfn) wraps function pointer pfn into a functor class that calls it.
+/// \ingroup FunctorAccessors
+template <typename Arg, typename Result>
+inline pointer_to_unary_function<Arg,Result> ptr_fun (Result (*pfn)(Arg))
+{
+    return (pointer_to_unary_function<Arg,Result> (pfn));
+}
+
+/// ptr_fun(pfn) wraps function pointer pfn into a functor class that calls it.
+/// \ingroup FunctorAccessors
+template <typename Arg1, typename Arg2, typename Result>
+inline pointer_to_binary_function<Arg1,Arg2,Result> ptr_fun (Result (*pfn)(Arg1,Arg2))
+{
+    return (pointer_to_binary_function<Arg1,Arg2,Result> (pfn));
+}
+
+//----------------------------------------------------------------------
+// Negators.
+//----------------------------------------------------------------------
+
+/// \brief Wraps a unary function to return its logical negative.
+/// Use the \ref unary_negator accessor to create this object.
+/// \ingroup FunctorObjects
+template <class UnaryFunction>
+class unary_negate : public unary_function<typename UnaryFunction::argument_type,
+					   typename UnaryFunction::result_type> {
+public:
+    typedef typename UnaryFunction::argument_type	argument_type;
+    typedef typename UnaryFunction::result_type		result_type;
+public:
+    explicit inline unary_negate (UnaryFunction pfn) : m_pfn (pfn) {}
+    inline result_type operator() (argument_type v) const { return (!m_pfn(v)); }
+private:
+    UnaryFunction	m_pfn;
+};
+
+/// Returns the functor that negates the result of *pfn().
+/// \ingroup FunctorAccessors
+template <class UnaryFunction>
+inline unary_negate<UnaryFunction> unary_negator (UnaryFunction pfn)
+{
+    return (unary_negate<UnaryFunction>(pfn));
+}
+
+//----------------------------------------------------------------------
+// Argument binders
+//----------------------------------------------------------------------
+
+/// \brief Converts a binary function to a unary function
+/// by binding a constant value to the first argument.
+/// Use the \ref bind1st accessor to create this object.
+/// \ingroup FunctorObjects
+template <class BinaryFunction> 
+class binder1st : public unary_function<typename BinaryFunction::second_argument_type,
+					typename BinaryFunction::result_type> {
+public:
+    typedef typename BinaryFunction::first_argument_type	arg1_t;
+    typedef typename BinaryFunction::second_argument_type	arg2_t;
+    typedef typename BinaryFunction::result_type		result_t;
+public:
+    inline binder1st (const BinaryFunction& pfn, const arg1_t& v) : m_pfn (pfn), m_Value(v) {}
+    inline result_t operator()(arg2_t v2) const { return (m_pfn (m_Value, v2)); }
+protected:
+    BinaryFunction	m_pfn;
+    arg1_t		m_Value;
+};
+
+/// \brief Converts a binary function to a unary function
+/// by binding a constant value to the second argument.
+/// Use the \ref bind2nd accessor to create this object.
+/// \ingroup FunctorObjects
+template <class BinaryFunction> 
+class binder2nd : public unary_function<typename BinaryFunction::first_argument_type,
+					typename BinaryFunction::result_type> {
+public:
+    typedef typename BinaryFunction::first_argument_type	arg1_t;
+    typedef typename BinaryFunction::second_argument_type	arg2_t;
+    typedef typename BinaryFunction::result_type		result_t;
+public:
+    inline binder2nd (const BinaryFunction& pfn, const arg2_t& v) : m_pfn (pfn), m_Value(v) {}
+    inline result_t operator()(arg1_t v1) const { return (m_pfn (v1, m_Value)); }
+protected:
+    BinaryFunction	m_pfn;
+    arg2_t		m_Value;
+};
+
+/// Converts \p pfn into a unary function by binding the first argument to \p v.
+/// \ingroup FunctorAccessors
+template <typename BinaryFunction>
+inline binder1st<BinaryFunction>
+bind1st (BinaryFunction pfn, typename BinaryFunction::first_argument_type v) 
+{
+    return (binder1st<BinaryFunction> (pfn, v));
+}
+
+/// Converts \p pfn into a unary function by binding the second argument to \p v.
+/// \ingroup FunctorAccessors
+template <typename BinaryFunction>
+inline binder2nd<BinaryFunction>
+bind2nd (BinaryFunction pfn, typename BinaryFunction::second_argument_type v) 
+{
+    return (binder2nd<BinaryFunction> (pfn, v));
+}
+
+//----------------------------------------------------------------------
+// Composition adapters
+//----------------------------------------------------------------------
+
+/// \brief Chains two unary functions together.
+///
+/// When f(x) and g(x) are composed, the result is function c(x)=f(g(x)).
+/// Use the \ref compose1 accessor to create this object.
+/// This template is an extension, implemented by SGI STL and uSTL.
+/// \ingroup FunctorObjects
+///
+template <typename Operation1, typename Operation2>
+class unary_compose : public unary_function<typename Operation2::argument_type,
+					    typename Operation1::result_type> {
+public:
+    typedef typename Operation2::argument_type	arg_t;
+    typedef const arg_t&			rcarg_t;
+    typedef typename Operation1::result_type	result_t;
+public:
+    inline unary_compose (const Operation1& f, const Operation2& g) : m_f(f), m_g(g) {}
+    inline result_t operator() (rcarg_t x) const { return m_f(m_g(x)); }
+protected:
+    Operation1	m_f;	///< f(x), if c(x) = f(g(x))
+    Operation2	m_g;	///< g(x), if c(x) = f(g(x))
+};
+
+/// Creates a \ref unary_compose object whose function c(x)=f(g(x))
+/// \ingroup FunctorAccessors
+template <typename Operation1, typename Operation2>
+inline unary_compose<Operation1, Operation2>
+compose1 (const Operation1& f, const Operation2& g)
+{ return unary_compose<Operation1,Operation2>(f, g); }
+
+/// \brief Chains two unary functions through a binary function.
+///
+/// When f(x,y), g(x), and h(x) are composed, the result is function
+/// c(x)=f(g(x),h(x)). Use the \ref compose2 accessor to create this
+/// object. This template is an extension, implemented by SGI STL and uSTL.
+/// \ingroup FunctorObjects
+///
+template <typename Operation1, typename Operation2, typename Operation3>
+class binary_compose : public unary_function<typename Operation2::argument_type,
+					    typename Operation1::result_type> {
+public:
+    typedef typename Operation2::argument_type	arg_t;
+    typedef const arg_t&			rcarg_t;
+    typedef typename Operation1::result_type	result_t;
+public:
+    inline binary_compose (const Operation1& f, const Operation2& g, const Operation3& h) : m_f(f), m_g(g), m_h(h) {}
+    inline result_t operator() (rcarg_t x) const { return m_f(m_g(x), m_h(x)); }
+protected:
+    Operation1	m_f;	///< f(x,y), if c(x) = f(g(x),h(x))
+    Operation2	m_g;	///< g(x), if c(x) = f(g(x),h(x))
+    Operation3	m_h;	///< h(x), if c(x) = f(g(x),h(x))
+};
+
+/// Creates a \ref binary_compose object whose function c(x)=f(g(x),h(x))
+/// \ingroup FunctorAccessors
+template <typename Operation1, typename Operation2, typename Operation3>
+inline binary_compose<Operation1, Operation2, Operation3>
+compose2 (const Operation1& f, const Operation2& g, const Operation3& h)
+{ return binary_compose<Operation1, Operation2, Operation3> (f, g, h); }
+
+//----------------------------------------------------------------------
+// Member function adaptors
+//----------------------------------------------------------------------
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+#define MEM_FUN_T(WrapperName, ClassName, ArgType, FuncType, CallType)				\
+    template <typename Ret, class T>								\
+    class ClassName : public unary_function<ArgType,Ret> {					\
+    public:											\
+	typedef Ret (T::*func_t) FuncType;							\
+    public:											\
+	explicit inline	ClassName (func_t pf) : m_pf (pf) {}					\
+	inline Ret	operator() (ArgType p) const { return ((p CallType m_pf)()); }		\
+    private:											\
+	func_t	m_pf;										\
+    };	\
+	\
+    template <class Ret, typename T>		\
+    inline ClassName<Ret,T> WrapperName (Ret (T::*pf) FuncType)	\
+    {						\
+	return (ClassName<Ret,T> (pf));		\
+    }
+
+MEM_FUN_T(mem_fun,	mem_fun_t, 		T*,		(void),		->*)
+MEM_FUN_T(mem_fun,	const_mem_fun_t, 	const T*,	(void) const,	->*)
+MEM_FUN_T(mem_fun_ref,	mem_fun_ref_t,		T&,		(void),		.*)
+MEM_FUN_T(mem_fun_ref,	const_mem_fun_ref_t, 	const T&,	(void) const,	.*)
+
+#define EXT_MEM_FUN_T(ClassName, HostType, FuncType) \
+    template <class T, typename Ret, typename V> \
+    class ClassName : public unary_function<V,void> { \
+    public: \
+	typedef Ret (T::*func_t)(V) FuncType; \
+    public: \
+	inline		ClassName (HostType t, func_t pf) : m_t (t), m_pf (pf) {} \
+	inline Ret	operator() (V v) const { return ((m_t->*m_pf)(v)); } \
+    private: \
+	HostType	m_t; \
+	func_t		m_pf; \
+    };	\
+	\
+    template <class T, typename Ret, typename V>					\
+    inline ClassName<T,Ret,V> mem_fun (HostType p, Ret (T::*pf)(V) FuncType)	\
+    {											\
+	return (ClassName<T,Ret,V> (p, pf));						\
+    }
+
+EXT_MEM_FUN_T(ext_mem_fun_t,		T*,		)
+EXT_MEM_FUN_T(const_ext_mem_fun_t,	const T*,	const)
+
+#endif // DOXYGEN_SHOULD_SKIP_THIS
+
+//----------------------------------------------------------------------
+// Member variable adaptors (uSTL extension)
+//----------------------------------------------------------------------
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+#define MEM_VAR_T(FunctorName, ArgType, VarType, BaseClass, CallImpl)			\
+    template <typename Function, class T, typename VT>					\
+    class FunctorName##_t : public BaseClass {						\
+    public:										\
+	typedef ArgType				argument_type;				\
+	typedef typename Function::result_type	result_type;				\
+	typedef VarType				mem_var_ptr_t;				\
+    public:										\
+	inline FunctorName##_t (mem_var_ptr_t pv, Function pfn) : m_pv(pv), m_pfn(pfn) {}	\
+	inline result_type operator() CallImpl						\
+    private:										\
+	mem_var_ptr_t	m_pv;								\
+	Function	m_pfn;								\
+    };											\
+											\
+    template <typename Function, class T, typename VT>					\
+    inline FunctorName##_t<Function, T, VT>						\
+    FunctorName (VT T::*mvp, Function pfn)						\
+    {											\
+	return (FunctorName##_t<Function,T,VT> (mvp, pfn));				\
+    }
+
+#define FUNCTOR_UNARY_BASE(ArgType)	unary_function<ArgType, typename Function::result_type>
+#define FUNCTOR_BINARY_BASE(ArgType)	binary_function<ArgType, ArgType, typename Function::result_type>
+
+#define MEM_VAR_UNARY_ARGS		(argument_type p) const \
+					{ return (m_pfn(p.*m_pv)); }
+#define MEM_VAR_BINARY_ARGS		(argument_type p1, argument_type p2) const \
+					{ return (m_pfn(p1.*m_pv, p2.*m_pv)); }
+
+MEM_VAR_T(mem_var1,		T&, VT T::*,		FUNCTOR_UNARY_BASE(T&),  MEM_VAR_UNARY_ARGS)
+MEM_VAR_T(const_mem_var1, const T&, const VT T::*,	FUNCTOR_UNARY_BASE(T&),  MEM_VAR_UNARY_ARGS)
+MEM_VAR_T(mem_var2,		T&, VT T::*,		FUNCTOR_BINARY_BASE(T&), MEM_VAR_BINARY_ARGS)
+MEM_VAR_T(const_mem_var2, const T&, const VT T::*,	FUNCTOR_BINARY_BASE(T&), MEM_VAR_BINARY_ARGS)
+
+#undef MEM_VAR_UNARY_ARGS
+#undef MEM_VAR_BINARY_ARGS
+
+#endif // DOXYGEN_SHOULD_SKIP_THIS
+
+/// Returned functor passes member variable \p mvp reference of given object to equal\<VT\>.
+/// \ingroup FunctorAccessors
+template <class T, typename VT>
+inline const_mem_var1_t<binder2nd<equal_to<VT> >, T, VT>
+mem_var_equal_to (const VT T::*mvp, const VT& v)
+{
+    return (const_mem_var1_t<binder2nd<equal_to<VT> >,T,VT> (mvp, bind2nd(equal_to<VT>(), v)));
+}
+
+/// Returned functor passes member variable \p mvp reference of given object to less\<VT\>.
+/// \ingroup FunctorAccessors
+template <class T, typename VT>
+inline const_mem_var1_t<binder2nd<less<VT> >, T, VT>
+mem_var_less (const VT T::*mvp, const VT& v)
+{
+    return (const_mem_var1_t<binder2nd<less<VT> >,T,VT> (mvp, bind2nd(less<VT>(), v)));
+}
+
+/// Returned functor passes member variable \p mvp reference of given object to equal\<VT\>.
+/// \ingroup FunctorAccessors
+template <class T, typename VT>
+inline const_mem_var2_t<equal_to<VT>, T, VT>
+mem_var_equal_to (const VT T::*mvp)
+{
+    return (const_mem_var2_t<equal_to<VT>,T,VT> (mvp, equal_to<VT>()));
+}
+
+/// Returned functor passes member variable \p mvp reference of given object to less\<VT\>.
+/// \ingroup FunctorAccessors
+template <class T, typename VT>
+inline const_mem_var2_t<less<VT>, T, VT>
+mem_var_less (const VT T::*mvp)
+{
+    return (const_mem_var2_t<less<VT>,T,VT> (mvp, less<VT>()));
+}
+
+//----------------------------------------------------------------------
+// Dereference adaptors (uSTL extension)
+//----------------------------------------------------------------------
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+#define DEREFERENCER_T(ClassName, ArgType, BaseClass, CallImpl, FunctorKey)	\
+    template <typename T, typename Function>					\
+    class ClassName : public BaseClass {					\
+    public:									\
+	typedef ArgType*			argument_type;			\
+	typedef typename Function::result_type	result_type;			\
+    public:									\
+	inline			ClassName (Function pfn) : m_pfn (pfn) {}	\
+	inline result_type	operator() CallImpl				\
+    private:									\
+	Function		m_pfn;						\
+    };										\
+										\
+    template <typename T, typename Function>					\
+    inline ClassName<T,Function> _dereference (Function pfn, FunctorKey)	\
+    {										\
+	return (ClassName<T,Function> (pfn));					\
+    }
+
+#define DEREF_UNARY_ARGS		(argument_type p) const \
+					{ return (m_pfn(*p)); }
+#define DEREF_BINARY_ARGS		(argument_type p1, argument_type p2) const \
+					{ return (m_pfn(*p1, *p2)); }
+
+DEREFERENCER_T(deref1_t,	T, 		FUNCTOR_UNARY_BASE(T*),		DEREF_UNARY_ARGS,	FUNCTOR_UNARY_BASE(T))
+DEREFERENCER_T(const_deref1_t,	const T, 	FUNCTOR_UNARY_BASE(const T*),	DEREF_UNARY_ARGS,	FUNCTOR_UNARY_BASE(const T))
+DEREFERENCER_T(deref2_t,	T, 		FUNCTOR_BINARY_BASE(T*),	DEREF_BINARY_ARGS,	FUNCTOR_BINARY_BASE(T))
+DEREFERENCER_T(const_deref2_t,	const T, 	FUNCTOR_BINARY_BASE(const T*),	DEREF_BINARY_ARGS,	FUNCTOR_BINARY_BASE(const T))
+
+#define dereference(f) _dereference(f,f)
+
+#undef DEREF_UNARY_ARGS
+#undef DEREF_BINARY_ARGS
+
+#endif
+
+} // namespace ustl
+
+#endif
+
diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/uheap.h b/media/libdrm/mobile2/src/util/ustl-1.0/uheap.h
new file mode 100644
index 0000000..9dfddaf
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/ustl-1.0/uheap.h
@@ -0,0 +1,153 @@
+// This file is part of the ustl library, an STL implementation.
+//
+// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
+// This file is free software, distributed under the MIT License.
+//
+// uheap.h
+//
+// Implementation of STL heap algorithms.
+//
+// The function prototypes are copied
+// exactly from the SGI version of STL documentation along with comments about
+// their use. The code is NOT the same, though the functionality is.
+//
+
+#ifndef UHEAP_H_574B9EAF271A1C107190B4D575A356C5
+#define UHEAP_H_574B9EAF271A1C107190B4D575A356C5
+
+#include "uvector.h"
+#include "ualgobase.h"
+
+namespace ustl {
+
+/// \brief Returns true if the given range is a heap under \p comp.
+/// A heap is a sequentially encoded binary tree where for every node
+/// comp(node,child1) is false and comp(node,child2) is false.
+/// \ingroup HeapAlgorithms
+/// \ingroup ConditionAlgorithms
+///
+template <typename RandomAccessIterator, typename Compare>
+bool is_heap (RandomAccessIterator first, RandomAccessIterator last, Compare comp)
+{
+    RandomAccessIterator iChild (first);
+    for (; ++iChild < last; ++first)
+	if (comp (*first, *iChild) || (++iChild < last && comp (*first, *iChild)))
+	    return (false);
+    return (true);
+}
+
+/// \brief make_heap turns the range [first, last) into a heap
+/// At completion, is_heap (first, last, comp) is true.
+/// The algorithm is adapted from "Classic Data Structures in C++" by Timothy Budd.
+/// \ingroup HeapAlgorithms
+/// \ingroup SortingAlgorithms
+///
+template <typename RandomAccessIterator, typename Compare>
+void make_heap (RandomAccessIterator first, RandomAccessIterator last, Compare comp)
+{
+    typedef typename iterator_traits<RandomAccessIterator>::value_type value_type;
+    const value_type v (*first);
+    uoff_t iChild, iHole = 0, iEnd (distance (first, last));
+    while ((iChild = 2 * iHole + 1) < iEnd) {
+	if (iChild + 1 < iEnd)	// Pick the greater child
+	    iChild += comp (first[iChild], first[iChild + 1]);
+	if (comp (first[iChild], v))
+	    break;		// Done when parent is greater than both children.
+	first[iHole] = first[iChild];
+	iHole = iChild;
+    }
+    if (iHole < iEnd)
+	first[iHole] = v;
+}
+
+/// \brief Inserts the *--last into the preceeding range assumed to be a heap.
+/// \ingroup HeapAlgorithms
+/// \ingroup MutatingAlgorithms
+template <typename RandomAccessIterator, typename Compare>
+void push_heap (RandomAccessIterator first, RandomAccessIterator last, Compare comp)
+{
+    if (last <= first)
+	return;
+    typedef typename iterator_traits<RandomAccessIterator>::value_type value_type;
+    const value_type v (*--last);
+    while (first < last) {
+	RandomAccessIterator iParent = first + (distance(first, last) - 1) / 2;
+	if (comp (v, *iParent))
+	    break;
+	*last = *iParent;
+	last = iParent;
+    }
+    *last = v;
+}
+
+/// Removes the largest element from the heap (*first) and places it at *(last-1)
+/// [first, last-1) is a heap after this operation.
+/// \ingroup HeapAlgorithms
+/// \ingroup MutatingAlgorithms
+template <typename RandomAccessIterator, typename Compare>
+void pop_heap (RandomAccessIterator first, RandomAccessIterator last, Compare comp)
+{
+    if (--last <= first)
+	return;
+    iter_swap (first, last);
+    make_heap (first, last, comp);
+}
+
+/// Sorts heap [first, last) in descending order according to comp.
+/// \ingroup HeapAlgorithms
+/// \ingroup SortingAlgorithms
+template <typename RandomAccessIterator, typename Compare>
+void sort_heap (RandomAccessIterator first, RandomAccessIterator last, Compare comp)
+{
+    for (; first < last; --last)
+	pop_heap (first, last, comp);
+}
+
+#define HEAP_FN_WITH_LESS(rtype, name)	\
+template <typename RandomAccessIterator>\
+inline rtype name (RandomAccessIterator first, RandomAccessIterator last)		\
+{											\
+    typedef typename iterator_traits<RandomAccessIterator>::value_type value_type;	\
+    return (name (first, last, less<value_type>()));					\
+}
+HEAP_FN_WITH_LESS (bool, is_heap)
+HEAP_FN_WITH_LESS (void, make_heap)
+HEAP_FN_WITH_LESS (void, push_heap)
+HEAP_FN_WITH_LESS (void, pop_heap)
+HEAP_FN_WITH_LESS (void, sort_heap)
+#undef HEAP_FN_WITH_LESS
+
+/// \class priority_queue uheap.h ustl.h
+/// \ingroup Sequences
+///
+/// \brief Sorted queue adapter to uSTL containers.
+///
+/// Acts just like the queue adapter, but keeps the elements sorted by priority
+/// specified by the given comparison operator.
+///
+template <typename T, typename Ctr = vector<T>, typename Comp = less<typename Ctr::value_type> >
+class priority_queue {
+public:
+    typedef Ctr					base_ctr;
+    typedef typename base_ctr::value_type	value_type;
+    typedef typename base_ctr::size_type	size_type;
+    typedef typename base_ctr::const_pointer	const_pointer;
+    typedef typename base_ctr::const_reference	reference;
+public:
+			priority_queue (const Comp& c = Comp()) : m_v(), m_c (c) {}
+			priority_queue (const_pointer f, const_pointer l, const Comp& c = Comp())
+			    : m_v (f, l), m_c (c) { make_heap (m_v.begin(), m_v.end(), m_c); }
+    inline size_type	size (void) const	{ return (m_v.size()); }
+    inline bool		empty (void) const	{ return (m_v.empty()); }
+    inline reference	top (void) const	{ return (m_v.at(0)); }
+    inline void		push (reference v)	{ m_v.push_back (v); make_heap (m_v.begin(), m_v.end(), m_c); }
+    inline void		pop (void)		{ pop_heap (m_v.begin(), m_v.end()); m_v.pop_back(); }
+private:
+    base_ctr		m_v;	///< Element container.
+    Comp		m_c;	///< Comparison functor by value.
+};
+
+} // namespace ustl
+
+#endif
+
diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/uios.h b/media/libdrm/mobile2/src/util/ustl-1.0/uios.h
new file mode 100644
index 0000000..6153be5
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/ustl-1.0/uios.h
@@ -0,0 +1,107 @@
+// This file is part of the ustl library, an STL implementation.
+//
+// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
+// This file is free software, distributed under the MIT License.
+//
+// uios.h
+//
+// Types used by the streams for option setting.
+//
+
+#ifndef UIOS_H_630C16E316F7650E3A02E1C6611B789A
+#define UIOS_H_630C16E316F7650E3A02E1C6611B789A
+
+#include "utypes.h"
+
+namespace ustl {
+
+class file_exception;
+
+const char endl = '\n';		///< End of line character.
+const char ends = '\0';		///< End of string character.
+
+/// Defines types and constants used by all stream classes.
+class ios_base {
+public:
+    /// Used to set parameters for stringstreams
+    enum fmtflags {
+	boolalpha	= (1 << 0),	///< Boolean values printed as text.
+	dec		= (1 << 1),	///< Decimal number output.
+	fixed		= (1 << 2),	///< Fixed-point float output.
+	hex		= (1 << 3),	///< Hexadecimal number output.
+	internal	= (1 << 4),
+	left		= (1 << 5),	///< Left alignment.
+	oct		= (1 << 6),	///< Octal number output.
+	right		= (1 << 7),	///< Right alignment.
+	scientific	= (1 << 8),	///< Scientific float format.
+	showbase	= (1 << 9),	///< Add 0x or 0 prefixes on hex and octal numbers.
+	showpoint	= (1 << 10),	///< Print decimal point.
+	showpos		= (1 << 11),
+	skipws		= (1 << 12),	///< Skip whitespace when reading.
+	unitbuf		= (1 << 13),
+	uppercase	= (1 << 14),
+	adjustfield	= (1 << 15),
+	basefield	= (1 << 16),
+	floatfield	= (1 << 17)
+    };
+    /// For file-based streams, specifies fd mode.
+    enum openmode_bits {
+	in	= (1 << 0),
+	out	= (1 << 1),
+	app	= (1 << 2),
+	ate	= (1 << 3),
+	binary	= (1 << 4),
+	trunc	= (1 << 5),
+	#ifndef DOXYGEN_SHOULD_SKIP_THIS
+	nonblock= (1 << 6),
+	nocreate= (1 << 7),
+	noctty	= (1 << 8),
+	nombits	= 9
+	#endif
+    };
+    /// Seek directions, equivalent to SEEK_SET, SEEK_CUR, and SEEK_END.
+    enum seekdir {
+	beg,
+	cur,
+	end
+    };
+    /// I/O state bitmasks.
+    enum iostate_bits {
+	goodbit	= 0,
+	badbit	= (1 << 0),
+	eofbit	= (1 << 1),
+	failbit	= (1 << 2),
+	#ifndef DOXYGEN_SHOULD_SKIP_THIS
+	nbadbits = 3,
+	allbadbits = 0x7
+	#endif
+    };
+
+    typedef uint32_t		openmode;	///< Holds openmode_bits.
+    typedef uint32_t		iostate;	///< Holds iostate_bits for a file stream.
+    typedef file_exception	failure;	///< Thrown by fstream on errors.
+
+    static const char c_DefaultDelimiters [16];	///< Default word delimiters for stringstreams.
+public:
+    inline		ios_base (void)			: m_State (goodbit), m_Exceptions (goodbit) {}
+    inline iostate	rdstate (void) const		{ return (m_State); }
+    inline bool		bad (void) const		{ return (rdstate() & badbit); }
+    inline bool		good (void) const		{ return (rdstate() == goodbit); }
+    inline bool		fail (void) const		{ return (rdstate() & (badbit | failbit)); }
+    inline bool		eof (void) const		{ return (rdstate() & eofbit); }
+    inline bool		operator! (void) const		{ return (fail()); }
+    inline void		clear (iostate v = goodbit)	{ m_State = v; }
+    inline void		setstate (iostate v)		{ m_State |= v; }
+    inline iostate	exceptions (void) const		{ return (m_Exceptions); }
+    inline iostate	exceptions (iostate v)		{ return (m_Exceptions = v); }
+protected:
+    inline bool		set_and_throw (iostate v)	{ setstate(v); return (exceptions() & v); }
+private:
+    uint16_t		m_State;	///< Open state, using ios::iostate_bits.
+    uint16_t		m_Exceptions;	///< Exception flags, using ios::iostate_bits.
+};
+
+} // namespace ustl
+
+#endif
+
diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/uiosfunc.h b/media/libdrm/mobile2/src/util/ustl-1.0/uiosfunc.h
new file mode 100644
index 0000000..fe26ed1
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/ustl-1.0/uiosfunc.h
@@ -0,0 +1,103 @@
+// This file is part of the ustl library, an STL implementation.
+//
+// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
+// This file is free software, distributed under the MIT License.
+//
+// uiosfunc.h
+//
+
+#ifndef UIOSFUNC_H_730C16E316F7650E3A02E1C6611B789A
+#define UIOSFUNC_H_730C16E316F7650E3A02E1C6611B789A
+
+#include "sostream.h"
+
+namespace ustl {
+
+class ios : public ios_base {
+public:
+    /// \class align uiosfunc.h ustl.h
+    /// \ingroup StreamFunctors
+    /// \brief Stream functor to allow inline align() calls.
+    ///
+    /// Example: os << ios::align(sizeof(uint16_t));
+    ///
+    class align {
+    public:
+	inline explicit		align (size_t grain = c_DefaultAlignment) : m_Grain(grain) {}
+	inline istream&		apply (istream& is) const { is.align (m_Grain); return (is); }
+	inline ostream&		apply (ostream& os) const { os.align (m_Grain); return (os); }
+	inline size_t		stream_size (void) const  { return (m_Grain - 1); }
+    private:
+	const size_t		m_Grain;
+    };
+
+    /// \class talign uiosfunc.h ustl.h
+    /// \ingroup StreamFunctors
+    /// \brief Stream functor to allow type-based alignment.
+    template <typename T>
+    class talign : public align {
+    public:
+	inline explicit		talign (void) : align (alignof (T())) {}
+    };
+
+    /// \class skip uiosfunc.h ustl.h
+    /// \ingroup StreamFunctors
+    /// \brief Stream functor to allow inline skip() calls.
+    ///
+    /// Example: os << ios::skip(sizeof(uint16_t));
+    ///
+    class skip {
+    public:
+	inline explicit 	skip (size_t nBytes) : m_nBytes(nBytes) {}
+	inline istream&		apply (istream& is) const { is.skip (m_nBytes); return (is); }
+	inline ostream&		apply (ostream& os) const { os.skip (m_nBytes); return (os); }
+	inline size_t		stream_size (void) const  { return (m_nBytes); }
+    private:
+	const size_t		m_nBytes;
+    };
+
+    /// \class width uiosfunc.h ustl.h
+    /// \ingroup StreamFunctors
+    /// \brief Stream functor to allow inline set_width() calls.
+    ///
+    /// Example: os << ios::width(15);
+    ///
+    class width {
+    public:
+	inline explicit		width (size_t nBytes) : m_nBytes(nBytes) {}
+	inline ostringstream&	apply (ostringstream& os) const { os.set_width (m_nBytes); return (os); }
+    private:
+	const size_t		m_nBytes;
+    };
+
+    /// \class base uiosfunc.h ustl.h
+    /// \ingroup StreamFunctors
+    /// \brief Stream functor to allow inline set_base() calls.
+    ///
+    /// Example: os << ios::base(15);
+    ///
+    class base {
+    public:
+	inline explicit		base (size_t n) : m_Base(n) {}
+	inline ostringstream&	apply (ostringstream& os) const { os.set_base (m_Base); return (os); }
+    private:
+	const size_t		m_Base;
+    };
+};
+
+inline istream& operator>> (istream& is, const ios::skip& op)	{ return (op.apply (is)); }
+inline ostream& operator<< (ostream& os, const ios::skip& op)	{ return (op.apply (os)); }
+inline size_t stream_size_of (const ios::skip& op)		{ return (op.stream_size()); }
+inline istream& operator>> (istream& is, const ios::align& op)	{ return (op.apply (is)); }
+inline ostream& operator<< (ostream& os, const ios::align& op)	{ return (op.apply (os)); }
+inline size_t stream_size_of (const ios::align& op)		{ return (op.stream_size()); }
+inline ostringstream& operator<< (ostringstream& os, const ios::width& op)	{ return (op.apply (os)); }
+inline ostringstream& operator<< (ostringstream& os, const ios::base& op)	{ return (op.apply (os)); }
+
+} // namespace ustl
+
+CAST_STREAMABLE(ustl::ios::fmtflags, uint32_t)
+CAST_STREAMABLE(ustl::ios::seekdir, uint32_t)
+
+#endif
+
diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/uiterator.h b/media/libdrm/mobile2/src/util/ustl-1.0/uiterator.h
new file mode 100644
index 0000000..48c0d2d
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/ustl-1.0/uiterator.h
@@ -0,0 +1,268 @@
+// This file is part of the ustl library, an STL implementation.
+//
+// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
+// This file is free software, distributed under the MIT License.
+//
+/// \file uiterator.h
+/// \brief Contains various iterator adapters.
+//
+
+#ifndef UITERATOR_H_5BCA176C7214A30F2069E2614D2DC226
+#define UITERATOR_H_5BCA176C7214A30F2069E2614D2DC226
+
+#include "uassert.h"
+#include "utypes.h"
+
+namespace ustl {
+
+//----------------------------------------------------------------------
+
+/// \struct iterator_traits uiterator.h ustl.h
+/// \brief Contains the type traits of \p Iterator
+///
+template <typename Iterator>
+struct iterator_traits {
+    typedef typename Iterator::value_type        value_type;
+    typedef typename Iterator::difference_type   difference_type;
+    typedef typename Iterator::pointer           pointer;
+    typedef typename Iterator::reference         reference;
+};
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+template <typename T>
+struct iterator_traits<T*> {
+    typedef T		value_type;
+    typedef ptrdiff_t	difference_type;
+    typedef const T*	const_pointer;
+    typedef T*		pointer;
+    typedef T&		reference;
+};
+
+template <typename T>
+struct iterator_traits<const T*> {
+    typedef T		value_type;
+    typedef ptrdiff_t	difference_type;
+    typedef const T*	const_pointer;
+    typedef const T*	pointer;
+    typedef const T&	reference;
+};
+
+template <>
+struct iterator_traits<void*> {
+    typedef uint8_t	value_type;
+    typedef ptrdiff_t	difference_type;
+    typedef const void*	const_pointer;
+    typedef void*	pointer;
+    typedef value_type&	reference;
+};
+
+template <>
+struct iterator_traits<const void*> {
+    typedef uint8_t		value_type;
+    typedef ptrdiff_t		difference_type;
+    typedef const void*		const_pointer;
+    typedef const void*		pointer;
+    typedef const value_type&	reference;
+};
+
+#endif
+
+//----------------------------------------------------------------------
+
+/// \class reverse_iterator uiterator.h ustl.h
+/// \ingroup IteratorAdaptors
+/// \brief Wraps \p Iterator to behave in an exactly opposite manner.
+///
+template <class Iterator>
+class reverse_iterator {
+public:
+    typedef typename iterator_traits<Iterator>::value_type	value_type;
+    typedef typename iterator_traits<Iterator>::difference_type	difference_type;
+    typedef typename iterator_traits<Iterator>::pointer		pointer;
+    typedef typename iterator_traits<Iterator>::reference	reference;
+public:
+    				reverse_iterator (void) : m_i() {}
+    explicit			reverse_iterator (Iterator iter) : m_i (iter) {}
+    inline bool			operator== (const reverse_iterator& iter) const { return (m_i == iter.m_i); }
+    inline bool			operator< (const reverse_iterator& iter) const { return (iter.m_i < m_i); }
+    inline Iterator		base (void) const { return (m_i); }
+    inline reference		operator* (void) const { Iterator prev (m_i); --prev; return (*prev); }
+    inline pointer		operator-> (void) const { return (&(operator*())); }
+    inline reverse_iterator&	operator++ (void) { -- m_i; return (*this); }
+    inline reverse_iterator&	operator-- (void) { ++ m_i; return (*this); }
+    inline reverse_iterator	operator++ (int) { reverse_iterator prev (*this); -- m_i; return (prev); }
+    inline reverse_iterator	operator-- (int) { reverse_iterator prev (*this); ++ m_i; return (prev); }
+    inline reverse_iterator&	operator+= (size_t n) { m_i -= n; return (*this); }
+    inline reverse_iterator&	operator-= (size_t n) { m_i += n; return (*this); }
+    inline reverse_iterator	operator+ (size_t n) const { return (reverse_iterator (m_i - n)); }
+    inline reverse_iterator	operator- (size_t n) const { return (reverse_iterator (m_i + n)); }
+    inline reference		operator[] (uoff_t n) const { return (*(*this + n)); }
+    inline difference_type	operator- (const reverse_iterator& i) const { return (distance (m_i, i.m_i)); }
+protected:
+    Iterator		m_i;
+};
+
+//----------------------------------------------------------------------
+
+/// \class insert_iterator uiterator.h ustl.h
+/// \ingroup IteratorAdaptors
+/// \brief Calls insert on bound container for each assignment.
+///
+template <class Container>
+class insert_iterator {
+public:
+    typedef typename Container::value_type	value_type;
+    typedef typename Container::difference_type	difference_type;
+    typedef typename Container::pointer		pointer;
+    typedef typename Container::reference	reference;
+    typedef typename Container::iterator	iterator;
+public:
+    explicit			insert_iterator (Container& ctr, iterator ip) : m_rCtr (ctr), m_ip (ip) {}
+    inline insert_iterator&	operator= (typename Container::const_reference v)
+    				    { m_ip = m_rCtr.insert (m_ip, v); return (*this); }
+    inline insert_iterator&	operator* (void)  { return (*this); }
+    inline insert_iterator&	operator++ (void) { ++ m_ip; return (*this); }
+    inline insert_iterator	operator++ (int)  { insert_iterator prev (*this); ++ m_ip; return (*this); }
+protected:
+    Container&			m_rCtr;
+    iterator			m_ip;
+};
+
+/// Returns the insert_iterator for \p ctr.
+template <class Container>
+inline insert_iterator<Container> inserter (Container& ctr, typename Container::iterator ip)
+{
+    return (insert_iterator<Container> (ctr, ip));
+}
+
+//----------------------------------------------------------------------
+
+/// \class back_insert_iterator uiterator.h ustl.h
+/// \ingroup IteratorAdaptors
+/// \brief Calls push_back on bound container for each assignment.
+///
+template <class Container>
+class back_insert_iterator {
+public:
+    typedef typename Container::value_type	value_type;
+    typedef typename Container::difference_type	difference_type;
+    typedef typename Container::pointer		pointer;
+    typedef typename Container::reference	reference;
+public:
+    explicit				back_insert_iterator (Container& ctr) : m_rCtr (ctr) {}
+    inline back_insert_iterator&	operator= (typename Container::const_reference v)
+    					    { m_rCtr.push_back (v); return (*this); }
+    inline back_insert_iterator&	operator* (void)  { return (*this); }
+    inline back_insert_iterator&	operator++ (void) { return (*this); }
+    inline back_insert_iterator		operator++ (int)  { return (*this); }
+protected:
+    Container&		m_rCtr;
+};
+
+/// Returns the back_insert_iterator for \p ctr.
+template <class Container>
+inline back_insert_iterator<Container> back_inserter (Container& ctr)
+{
+    return (back_insert_iterator<Container> (ctr));
+}
+
+//----------------------------------------------------------------------
+
+/// \class index_iterate uiterator.h ustl.h
+/// \ingroup IteratorAdaptors
+///
+/// \brief Allows iteration through an index container.
+///
+/// Converts an iterator into a container of uoff_t indexes to an
+/// iterator of iterators into another container.
+///
+template <typename RandomAccessIterator, typename IndexIterator>
+class index_iterate {
+public:
+    typedef RandomAccessIterator	value_type;
+    typedef ptrdiff_t			difference_type;
+    typedef RandomAccessIterator*	pointer;
+    typedef RandomAccessIterator	reference;
+public:
+    				index_iterate (void) : m_Base(), m_i() {}
+				index_iterate (RandomAccessIterator ibase, IndexIterator iindex) : m_Base (ibase), m_i (iindex) {}
+    inline bool			operator== (const index_iterate& i) const { return (m_i == i.m_i); }
+    inline bool			operator< (const index_iterate& i) const { return (m_i < i.m_i); }
+    inline bool			operator== (const RandomAccessIterator& i) const { return (m_Base == i); }
+    inline bool			operator< (const RandomAccessIterator& i) const { return (m_Base < i); }
+    inline IndexIterator	base (void) const { return (m_i); }
+    inline reference		operator* (void) const { return (advance(m_Base, *m_i)); }
+    inline pointer		operator-> (void) const { return (&(operator*())); }
+    inline index_iterate&	operator++ (void) { ++ m_i; return (*this); }
+    inline index_iterate&	operator-- (void) { -- m_i; return (*this); }
+    inline index_iterate	operator++ (int) { index_iterate prev (*this); ++ m_i; return (prev); }
+    inline index_iterate	operator-- (int) { index_iterate prev (*this); -- m_i; return (prev); }
+    inline index_iterate&	operator+= (size_t n) { m_i += n; return (*this); }
+    inline index_iterate&	operator-= (size_t n) { m_i -= n; return (*this); }
+    inline index_iterate	operator+ (size_t n) const { return (index_iterate (m_Base, m_i + n)); }
+    inline index_iterate	operator- (size_t n) const { return (index_iterate (m_Base, m_i - n)); }
+    inline reference		operator[] (uoff_t n) const { return (*(*this + n)); }
+    inline difference_type	operator- (const index_iterate& i) const { return (distance (m_i, i.m_i)); }
+private:
+    RandomAccessIterator	m_Base;
+    IndexIterator		m_i;
+};
+
+/// Returns an index_iterate for \p ibase over \p iindex.
+template <typename RandomAccessIterator, typename IndexIterator>
+inline index_iterate<RandomAccessIterator, IndexIterator> index_iterator (RandomAccessIterator ibase, IndexIterator iindex)
+{
+    return (index_iterate<RandomAccessIterator, IndexIterator> (ibase, iindex));
+}
+
+/// Converts the indexes in \p xc to iterators in \p ic of base \p ibase.
+template <typename IndexContainer, typename IteratorContainer>
+inline void indexv_to_iteratorv (typename IteratorContainer::value_type ibase, const IndexContainer& xc, IteratorContainer& ic)
+{
+    ic.resize (xc.size());
+    copy_n (index_iterator (ibase, xc.begin()), xc.size(), ic.begin());
+}
+
+//----------------------------------------------------------------------
+
+/// Converts the given const_iterator into an iterator.
+///
+template <typename Container>
+inline typename Container::iterator unconst (typename Container::const_iterator i, Container& ctr)
+{
+    const Container& cctr = ctr;
+    return (ctr.begin() + (i - cctr.begin()));
+}
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+#define IBYI(Iter1, Iter2, Ctr1, Ctr2)	\
+template <typename Container1, typename Container2>	\
+inline typename Container2::Iter2 ibyi (typename Container1::Iter1 idx, Ctr1& ctr1, Ctr2& ctr2)	\
+{							\
+    assert (ctr1.size() == ctr2.size());		\
+    return (ctr2.begin() + (idx - ctr1.begin()));	\
+}
+
+IBYI(const_iterator, const_iterator, const Container1, const Container2)
+IBYI(iterator, iterator, Container1, Container2)
+IBYI(const_iterator, iterator, const Container1, Container2)
+IBYI(iterator, const_iterator, Container1, const Container2)
+
+#else // DOXYGEN
+
+#error This declaration is for doxygen only; it is not compiled.
+
+/// Converts a const_iterator in one container into a const_iterator in another container.
+template <typename Container1, typename Container2>
+inline typename Container2::iterator ibyi (typename Container1::iterator idx, Container1& ctr1, Container2& ctr2) {}
+
+#endif // DOXYGEN
+
+//----------------------------------------------------------------------
+
+} // namespace ustl
+
+#endif
+
diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/ulaalgo.h b/media/libdrm/mobile2/src/util/ustl-1.0/ulaalgo.h
new file mode 100644
index 0000000..1efc977
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/ustl-1.0/ulaalgo.h
@@ -0,0 +1,223 @@
+// This file is part of the ustl library, an STL implementation.
+//
+// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
+// This file is free software, distributed under the MIT License.
+//
+// ulaalgo.h
+//
+
+#ifndef ULAALGO_H_2E403D182E83FB596AFB800E68B255A1
+#define ULAALGO_H_2E403D182E83FB596AFB800E68B255A1
+
+#include "umatrix.h"
+#include "simd.h"
+
+namespace ustl {
+
+/// \brief Creates an identity matrix in \p m
+/// \ingroup NumericAlgorithms
+template <size_t NX, size_t NY, typename T>
+void load_identity (matrix<NX,NY,T>& m)
+{
+    fill_n (m.begin(), NX * NY, 0);
+    for (typename matrix<NX,NY,T>::iterator i = m.begin(); i < m.end(); i += NX + 1)
+	*i = 1;
+}
+
+/// \brief Multiplies two matrices
+/// \ingroup NumericAlgorithms
+template <size_t NX, size_t NY, typename T>
+matrix<NY,NY,T> operator* (const matrix<NX,NY,T>& m1, const matrix<NY,NX,T>& m2)
+{
+    matrix<NY,NY,T> mr;
+    for (uoff_t ry = 0; ry < NY; ++ ry) {
+	for (uoff_t rx = 0; rx < NY; ++ rx) {
+	    T dpv (0);
+	    for (uoff_t x = 0; x < NX; ++ x)
+		dpv += m1[ry][x] * m2[x][rx];
+	    mr[ry][rx] = dpv;
+	}
+    }
+    return (mr);
+}
+
+/// \brief Transforms vector \p t with matrix \p m
+/// \ingroup NumericAlgorithms
+template <size_t NX, size_t NY, typename T>
+tuple<NX,T> operator* (const tuple<NY,T>& t, const matrix<NX,NY,T>& m)
+{
+    tuple<NX,T> tr;
+    for (uoff_t x = 0; x < NX; ++ x) {
+	T dpv (0);
+	for (uoff_t y = 0; y < NY; ++ y)
+	    dpv += t[y] * m[y][x];
+	tr[x] = dpv;
+    }
+    return (tr);
+}
+
+/// \brief Transposes (exchanges rows and columns) matrix \p m.
+/// \ingroup NumericAlgorithms
+template <size_t N, typename T>
+void transpose (matrix<N,N,T>& m)
+{
+    for (uoff_t x = 0; x < N; ++ x)
+	for (uoff_t y = x; y < N; ++ y)
+	    swap (m[x][y], m[y][x]);
+}
+
+#if WANT_UNROLLED_COPY
+
+#if CPU_HAS_SSE
+
+#if linux // Non-linux gcc versions (BSD, Solaris) can't handle "x" constraint and provide no alternative.
+template <>
+inline void load_identity (matrix<4,4,float>& m)
+{
+    asm (
+	"movaps %4, %%xmm1		\n\t"	// 1 0 0 0
+	"movups %4, %0			\n\t"	// 1 0 0 0
+	"shufps $0xB1,%%xmm1,%%xmm1	\n\t"	// 0 1 0 0
+	"movups %%xmm1, %1		\n\t"	// 0 1 0 0
+	"shufps $0x4F,%4,%%xmm1		\n\t"	// 0 0 1 0
+	"shufps $0x1B,%4,%4		\n\t"	// 0 0 0 1
+	"movups %%xmm1, %2		\n\t"	// 0 0 1 0
+	"movups %4, %3"				// 0 0 0 1
+	: "=m"(m[0][0]), "=m"(m[1][0]), "=m"(m[2][0]), "=m"(m[3][0])
+	: "x"(1.0f)
+	: "xmm1"
+    );
+}
+#endif
+
+inline void _sse_load_matrix (const float* m)
+{
+    asm (
+	"movups %0, %%xmm4	\n\t"	// xmm4 = m[1 2 3 4]
+	"movups %1, %%xmm5	\n\t"	// xmm5 = m[1 2 3 4]
+	"movups %2, %%xmm6	\n\t"	// xmm6 = m[1 2 3 4]
+	"movups %3, %%xmm7"		// xmm7 = m[1 2 3 4]
+	: : "m"(m[0]), "m"(m[4]), "m"(m[8]), "m"(m[12])
+	: "xmm4", "xmm5", "xmm6", "xmm7"
+    );
+}
+
+inline void _sse_transform_to_vector (float* result)
+{
+    asm (
+	"movaps %%xmm0, %%xmm1		\n\t" // xmm1 = t[0 1 2 3]
+	"movaps %%xmm0, %%xmm2		\n\t" // xmm1 = t[0 1 2 3]
+	"movaps %%xmm0, %%xmm3		\n\t" // xmm1 = t[0 1 2 3]
+	"shufps $0x00, %%xmm0, %%xmm0	\n\t" // xmm0 = t[0 0 0 0]
+	"shufps $0x66, %%xmm1, %%xmm1	\n\t" // xmm1 = t[1 1 1 1]
+	"shufps $0xAA, %%xmm2, %%xmm2	\n\t" // xmm2 = t[2 2 2 2]
+	"shufps $0xFF, %%xmm3, %%xmm3	\n\t" // xmm3 = t[3 3 3 3]
+	"mulps  %%xmm4, %%xmm0		\n\t" // xmm0 = t[0 0 0 0] * m[0 1 2 3]
+	"mulps  %%xmm5, %%xmm1		\n\t" // xmm1 = t[1 1 1 1] * m[0 1 2 3]
+	"addps  %%xmm1, %%xmm0		\n\t" // xmm0 = xmm0 + xmm1
+	"mulps  %%xmm6, %%xmm2		\n\t" // xmm2 = t[2 2 2 2] * m[0 1 2 3]
+	"mulps  %%xmm7, %%xmm3		\n\t" // xmm3 = t[3 3 3 3] * m[0 1 2 3]
+	"addps  %%xmm3, %%xmm2		\n\t" // xmm2 = xmm2 + xmm3
+	"addps  %%xmm2, %%xmm0		\n\t" // xmm0 = result
+	"movups %%xmm0, %0"
+	: "=m"(result[0]) :
+	: "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7"
+    );
+}
+
+template <>
+tuple<4,float> operator* (const tuple<4,float>& t, const matrix<4,4,float>& m)
+{
+    tuple<4,float> result;
+    _sse_load_matrix (m.begin());
+    asm ("movups %0, %%xmm0" : : "m"(t[0]) : "xmm0");
+    _sse_transform_to_vector (result.begin());
+    return (result);
+}
+
+template <>
+matrix<4,4,float> operator* (const matrix<4,4,float>& m1, const matrix<4,4,float>& m2)
+{
+    matrix<4,4,float> result;
+    _sse_load_matrix (m2.begin());
+    for (uoff_t r = 0; r < 4; ++ r) { 
+	asm ("movups %0, %%xmm0" : : "m"(m1[r][0]) : "xmm0");
+	_sse_transform_to_vector (result[r]);
+    }
+    return (result);
+}
+
+#elif CPU_HAS_3DNOW
+
+/// Specialization for 4-component vector transform, the slow part of 3D graphics.
+template <>
+tuple<4,float> operator* (const tuple<4,float>& t, const matrix<4,4,float>& m)
+{
+    tuple<4,float> result;
+    // This is taken from "AMD Athlon Code Optimization Guide" from AMD. 18 cycles!
+    // If you are writing a 3D engine, you may want to copy it instead of calling it
+    // because of the femms instruction at the end, which takes 2 cycles.
+    asm (
+	"movq	   %2, %%mm0		\n\t"	//            y | x
+	"movq	   %3, %%mm1		\n\t"	//            w | z
+	"movq	   %%mm0, %%mm2		\n\t"	//            y | x
+	"movq	   %4, %%mm3		\n\t"	//      m[0][1] | m[0][0]
+	"punpckldq  %%mm0, %%mm0	\n\t"	//            x | x
+	"movq	   %6, %%mm4		\n\t"	//      m[1][1] | m[1][0]
+	"pfmul	   %%mm0, %%mm3		\n\t"	//    x*m[0][1] | x*m[0][0]
+	"punpckhdq  %%mm2, %%mm2	\n\t"	//            y | y
+	"pfmul	   %%mm2, %%mm4		\n\t"	//    y*m[1][1] | y*m[1][0]
+	"movq	   %5, %%mm5		\n\t"	//      m[0][3] | m[0][2]
+	"movq	   %7, %%mm7		\n\t"	//      m[1][3] | m[1][2]
+	"movq	   %%mm1, %%mm6		\n\t"	//            w | z
+	"pfmul	   %%mm0, %%mm5		\n\t"	//    x*m[0][3] | v0>x*m[0][2]
+	"movq	   %8, %%mm0		\n\t"	//      m[2][1] | m[2][0]
+	"punpckldq  %%mm1, %%mm1	\n\t"	//            z | z
+	"pfmul	   %%mm2, %%mm7		\n\t"	//    y*m[1][3] | y*m[1][2]
+	"movq	   %9, %%mm2		\n\t"	//      m[2][3] | m[2][2]
+	"pfmul	   %%mm1, %%mm0		\n\t"	//    z*m[2][1] | z*m[2][0]
+	"pfadd	   %%mm4, %%mm3		\n\t"	// x*m[0][1]+y*m[1][1] | x*m[0][0]+y*m[1][0]
+	"movq	   %10, %%mm4		\n\t"	//      m[3][1] | m[3][0]
+	"pfmul	   %%mm1, %%mm2		\n\t"	//    z*m[2][3] | z*m[2][2]
+	"pfadd	   %%mm7, %%mm5		\n\t"	// x*m[0][3]+y*m[1][3] | x*m[0][2]+y*m[1][2]
+	"movq	   %11, %%mm1		\n\t"	//      m[3][3] | m[3][2]
+	"punpckhdq  %%mm6, %%mm6	\n\t"	//            w | w
+	"pfadd	   %%mm0, %%mm3		\n\t"	// x*m[0][1]+y*m[1][1]+z*m[2][1] | x*m[0][0]+y*m[1][0]+z*m[2][0]
+	"pfmul	   %%mm6, %%mm4		\n\t"	//    w*m[3][1] | w*m[3][0]
+	"pfmul	   %%mm6, %%mm1		\n\t"	//    w*m[3][3] | w*m[3][2]
+	"pfadd	   %%mm2, %%mm5		\n\t"	// x*m[0][3]+y*m[1][3]+z*m[2][3] | x*m[0][2]+y*m[1][2]+z*m[2][2]
+	"pfadd	   %%mm4, %%mm3		\n\t"	// x*m[0][1]+y*m[1][1]+z*m[2][1]+w*m[3][1] | x*m[0][0]+y*m[1][0]+z*m[2][0]+w*m[3][0]
+	"movq	   %%mm3, %0		\n\t"	// store result->y | result->x
+	"pfadd	   %%mm1, %%mm5		\n\t"	// x*m[0][3]+y*m[1][3]+z*m[2][3]+w*m[3][3] | x*m[0][2]+y*m[1][2]+z*m[2][2]+w*m[3][2]
+	"movq	   %%mm5, %1"			// store result->w | result->z
+	: "=m"(result[0]), "=m"(result[2])
+	: "m"(t[0]), "m"(t[2]),
+	  "m"(m[0][0]), "m"(m[0][2]),
+	  "m"(m[1][0]), "m"(m[1][2]),
+	  "m"(m[2][0]), "m"(m[2][2]),
+	  "m"(m[3][0]), "m"(m[3][2])
+	: "mm0","mm1","mm2","mm3","mm4","mm5","mm6","mm7"
+    );
+    simd::reset_mmx();
+    return (result);
+}
+
+#else	// If no processor extensions, just unroll the multiplication
+
+/// Specialization for 4-component vector transform, the slow part of 3D graphics.
+template <>
+tuple<4,float> operator* (const tuple<4,float>& t, const matrix<4,4,float>& m)
+{
+    tuple<4,float> tr;
+    for (uoff_t i = 0; i < 4; ++ i)
+	tr[i] = t[0] * m[0][i] + t[1] * m[1][i] + t[2] * m[2][i] + t[3] * m[3][i];
+    return (tr);
+}
+
+#endif	// CPU_HAS_3DNOW
+#endif	// WANT_UNROLLED_COPY
+
+} // namespace ustl
+
+#endif
+
diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/ulimits.h b/media/libdrm/mobile2/src/util/ustl-1.0/ulimits.h
new file mode 100644
index 0000000..85f1db1
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/ustl-1.0/ulimits.h
@@ -0,0 +1,108 @@
+// This file is part of the ustl library, an STL implementation.
+//
+// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
+// This file is free software, distributed under the MIT License.
+//
+// ulimits.h
+//
+
+#ifndef ULIMITS_H_1C2192EA3821E0811BBAF86B0F048364
+#define ULIMITS_H_1C2192EA3821E0811BBAF86B0F048364
+
+#include "utypes.h"
+#include <stdint.h>
+
+namespace ustl {
+
+// Android
+#ifndef UINTPTR_MAX
+#define UINTPTR_MAX	UINT32_MAX
+#endif
+
+#ifndef UINT32_MAX
+#define UINT32_MAX    (0xffffffff)
+#endif
+	
+/// \class numeric_limits ulimits.h ustl.h
+/// \brief Defines numeric limits for a type.
+///
+template <typename T> 
+struct numeric_limits {
+    /// Returns the minimum value for type T.
+    static inline T min (void)		{ return (T(0)); }
+    /// Returns the minimum value for type T.
+    static inline T max (void)		{ return (T(0)); }
+    static const bool is_signed = false;	///< True if the type is signed.
+    static const bool is_integer = false;	///< True if stores an exact value.
+    static const bool is_integral = false;	///< True if fixed size and cast-copyable.
+};
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+template <typename T>
+struct numeric_limits<T*> {
+    static inline T* min (void)	{ return (NULL); }
+    static inline T* max (void)	{ return (UINTPTR_MAX); }
+    static const bool is_signed = false;
+    static const bool is_integer = true;
+    static const bool is_integral = true;
+};
+
+#define _NUMERIC_LIMITS(type, minVal, maxVal, bSigned, bInteger, bIntegral)	\
+template <>							\
+struct numeric_limits<type> {					\
+    static inline type min (void)	{ return (minVal); }	\
+    static inline type max (void)	{ return (maxVal); }	\
+    static const bool is_signed = bSigned;			\
+    static const bool is_integer = bInteger;			\
+    static const bool is_integral = bIntegral;			\
+}
+
+//--------------------------------------------------------------------------------------
+//		type		min		max		signed	integer	integral
+//--------------------------------------------------------------------------------------
+_NUMERIC_LIMITS (bool,		false,		true,		false,	true,	true);
+_NUMERIC_LIMITS (char,		SCHAR_MIN,	SCHAR_MAX,	true,	true,	true);
+_NUMERIC_LIMITS (int,		INT_MIN,	INT_MAX,	true,	true,	true);
+_NUMERIC_LIMITS (short,		SHRT_MIN,	SHRT_MAX,	true,	true,	true);
+_NUMERIC_LIMITS (long,		LONG_MIN,	LONG_MAX,	true,	true,	true);
+#if HAVE_THREE_CHAR_TYPES
+_NUMERIC_LIMITS (signed char,	SCHAR_MIN,	SCHAR_MAX,	true,	true,	true);
+#endif
+_NUMERIC_LIMITS (unsigned char,	0,		UCHAR_MAX,	false,	true,	true);
+_NUMERIC_LIMITS (unsigned int,	0,		UINT_MAX,	false,	true,	true);
+_NUMERIC_LIMITS (unsigned short,0,		USHRT_MAX,	false,	true,	true);
+_NUMERIC_LIMITS (unsigned long,	0,		ULONG_MAX,	false,	true,	true);
+_NUMERIC_LIMITS (wchar_t,	0,		WCHAR_MAX,	false,	true,	true);
+_NUMERIC_LIMITS (float,		FLT_MIN,	FLT_MAX,	true,	false,	true);
+_NUMERIC_LIMITS (double,	DBL_MIN,	DBL_MAX,	true,	false,	true);
+_NUMERIC_LIMITS (long double,	LDBL_MIN,	LDBL_MAX,	true,	false,	true);
+#ifdef HAVE_LONG_LONG
+_NUMERIC_LIMITS (long long,	LLONG_MIN,	LLONG_MAX,	true,	true,	true);
+_NUMERIC_LIMITS (unsigned long long,	0,	ULLONG_MAX,	false,	true,	true);
+#endif
+//--------------------------------------------------------------------------------------
+
+#endif // DOXYGEN_SHOULD_SKIP_THIS
+
+/// Macro for defining numeric_limits specializations
+#define NUMERIC_LIMITS(type, minVal, maxVal, bSigned, bInteger, bIntegral)	\
+namespace ustl { _NUMERIC_LIMITS (type, minVal, maxVal, bSigned, bInteger, bIntegral); }
+
+/// Returns the recommended stream alignment for type \p T. Override with ALIGNOF.
+template <typename T>
+inline size_t alignof (const T&)
+{
+    if (numeric_limits<T>::is_integral)
+	return (__alignof__(T));
+    return (4);
+}
+
+#define ALIGNOF(type,grain)	\
+namespace ustl {		\
+    template <> inline size_t alignof (const type&) { return (grain); } }
+
+} // namespace ustl
+
+#endif
+
diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/ulist.h b/media/libdrm/mobile2/src/util/ustl-1.0/ulist.h
new file mode 100644
index 0000000..842bbde
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/ustl-1.0/ulist.h
@@ -0,0 +1,78 @@
+// This file is part of the ustl library, an STL implementation.
+//
+// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
+// This file is free software, distributed under the MIT License.
+//
+// ulist.h
+//
+
+#ifndef ULIST_H_54E3B510498982C87A0A1E1932E6729D
+#define ULIST_H_54E3B510498982C87A0A1E1932E6729D
+
+#include "uvector.h"
+#include "uctralgo.h"
+
+namespace ustl {
+
+/// \class list ulist.h ustl.h
+/// \ingroup Sequences
+///
+/// \brief Linked list, defined as an alias to \ref vector.
+///
+template <typename T>
+class list : public vector<T> {
+public:
+    typedef typename vector<T>::size_type	size_type;
+    typedef typename vector<T>::iterator	iterator;
+    typedef typename vector<T>::const_iterator	const_iterator;
+    typedef typename vector<T>::reference	reference;
+    typedef typename vector<T>::const_reference	const_reference;
+public:
+    inline			list (void)			: vector<T> () {}
+    inline explicit		list (size_type n)		: vector<T> (n) {}
+    inline			list (size_type n, const T& v)	: vector<T> (n, v) {}
+    inline			list (const list<T>& v)		: vector<T> (v) {}
+    inline			list (const_iterator i1, const_iterator i2)	: vector<T> (i1, i2) {}
+    inline size_type		size (void) const		{ return (vector<T>::size()); }
+    inline iterator		begin (void)			{ return (vector<T>::begin()); }
+    inline const_iterator	begin (void) const		{ return (vector<T>::begin()); }
+    inline iterator		end (void)			{ return (vector<T>::end()); }
+    inline const_iterator	end (void) const		{ return (vector<T>::end()); }
+    inline void			push_front (const T& v)		{ insert (begin(), v); }
+    inline void			pop_front (void)		{ erase (begin()); }
+    inline const_reference	front (void) const		{ return (*begin()); }
+    inline reference		front (void)			{ return (*begin()); }
+    inline void			remove (const T& v)		{ ::ustl::remove (*this, v); }
+    inline void			unique (void)			{ ::ustl::unique (*this); }
+    inline void			sort (void)			{ ::ustl::sort (*this); }
+    void			merge (list<T>& l);
+    void			splice (iterator ip, list<T>& l, iterator first = NULL, iterator last = NULL);
+};
+
+/// Merges the contents with \p l. Assumes both lists are sorted.
+template <typename T>
+void list<T>::merge (list& l)
+{
+    list<T>::resize (size() + l.size());
+    iterator me = merge (begin(), end(), l.begin(), l.end(), begin());
+    list<T>::resize (distance (begin(), me));
+}
+
+/// Moves the range [first, last) from \p l to this list at \p ip.
+template <typename T>
+void list<T>::splice (iterator ip, list<T>& l, iterator first, iterator last)
+{
+    if (!first)
+	first = l.begin();
+    if (!last)
+	last = l.end();
+    insert (ip, first, last);
+    l.erase (first, last);
+}
+
+#define deque list ///< list has all the functionality provided by deque
+
+} // namespace ustl
+
+#endif
+
diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/umap.h b/media/libdrm/mobile2/src/util/ustl-1.0/umap.h
new file mode 100644
index 0000000..938c507
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/ustl-1.0/umap.h
@@ -0,0 +1,165 @@
+// This file is part of the ustl library, an STL implementation.
+//
+// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
+// This file is free software, distributed under the MIT License.
+//
+// umap.h
+//
+
+#ifndef UMAP_H_45643F516E02A87A3DCEA5024052A6F5
+#define UMAP_H_45643F516E02A87A3DCEA5024052A6F5
+
+#include "uassert.h"
+#include "ufunction.h"
+#include "uvector.h"
+
+namespace ustl {
+
+/// \class map umap.h ustl.h
+/// \ingroup AssociativeContainers
+///
+/// \brief A sorted associative container of pair<K,V>
+///
+template <typename K, typename V>
+class map : public vector<pair<K,V> > {
+public:
+    typedef K						key_type;
+    typedef V						data_type;
+    typedef const K&					const_key_ref;
+    typedef const V&					const_data_ref;
+    typedef const map<K,V>&				rcself_t;
+    typedef vector<pair<K,V> >				base_class;
+    typedef typename base_class::value_type		value_type;
+    typedef typename base_class::size_type		size_type;
+    typedef typename base_class::pointer		pointer;
+    typedef typename base_class::const_pointer		const_pointer;
+    typedef typename base_class::reference		reference;
+    typedef typename base_class::const_reference	const_reference;
+    typedef typename base_class::const_iterator		const_iterator;
+    typedef typename base_class::iterator		iterator;
+    typedef typename base_class::reverse_iterator	reverse_iterator;
+    typedef typename base_class::const_reverse_iterator	const_reverse_iterator;
+    typedef pair<const_iterator,const_iterator>		const_range_t;
+    typedef pair<iterator,iterator>			range_t;
+public:
+    inline			map (void)			: vector<pair<K,V> > () {}
+    explicit inline		map (size_type n)		: vector<pair<K,V> > (n) {}
+    inline			map (rcself_t v)		: vector<pair<K,V> > (v) {}
+    inline			map (const_iterator i1, const_iterator i2) : vector<pair<K,V> >() { insert (i1, i2); }
+    inline rcself_t		operator= (rcself_t v)		{ base_class::operator= (v); return (*this); }
+    inline const_data_ref	operator[] (const_key_ref i) const;
+    data_type&			operator[] (const_key_ref i);
+    inline size_type		size (void) const		{ return (base_class::size()); }
+    inline iterator		begin (void)			{ return (base_class::begin()); }
+    inline const_iterator	begin (void) const		{ return (base_class::begin()); }
+    inline iterator		end (void)			{ return (base_class::end()); }
+    inline const_iterator	end (void) const		{ return (base_class::end()); }
+    inline void			assign (const_iterator i1, const_iterator i2)	{ clear(); insert (i1, i2); }
+    inline void			push_back (const_reference v)			{ insert (v); }
+    inline const_iterator	find (const_key_ref k) const;
+    inline iterator		find (const_key_ref k)	{ return (const_cast<iterator> (const_cast<rcself_t>(*this).find (k))); }
+    inline const_iterator	find_data (const_data_ref v, const_iterator first = NULL, const_iterator last = NULL) const;
+    inline iterator		find_data (const_data_ref v, iterator first = NULL, iterator last = NULL);
+    iterator			insert (const_reference v);
+    void			insert (const_iterator i1, const_iterator i2);
+    inline void			erase (const_key_ref k);
+    inline iterator		erase (iterator ep)	{ return (base_class::erase (ep)); }
+    inline iterator		erase (iterator ep1, iterator ep2) { return (base_class::erase (ep1, ep2)); }
+    inline void			clear (void)		{ base_class::clear(); }
+private:
+    const_iterator		lower_bound (const_key_ref k) const;
+    inline iterator		lower_bound (const_key_ref k) { return (const_cast<iterator>(const_cast<rcself_t>(*this).lower_bound (k))); }
+};
+
+template <typename K, typename V>
+typename map<K,V>::const_iterator map<K,V>::lower_bound (const_key_ref k) const
+{
+    const_iterator first (begin()), last (end());
+    while (first != last) {
+	const_iterator mid = advance (first, distance (first,last) / 2);
+	if (mid->first < k)
+	    first = advance (mid, 1);
+	else
+	    last = mid;
+    }
+    return (first);
+}
+
+/// Returns the pair<K,V> where K = \p k.
+template <typename K, typename V>
+inline typename map<K,V>::const_iterator map<K,V>::find (const_key_ref k) const
+{
+    const_iterator i = lower_bound (k);
+    return ((i < end() && k < i->first) ? end() : i);
+}
+
+/// Returns the pair<K,V> where V = \p v, occuring in range [first,last).
+template <typename K, typename V>
+inline typename map<K,V>::const_iterator map<K,V>::find_data (const_data_ref v, const_iterator first, const_iterator last) const
+{
+    if (!first) first = begin();
+    if (!last) last = end();
+    for (; first != last && first->second != v; ++first);
+    return (first);
+}
+
+/// Returns the pair<K,V> where V = \p v, occuring in range [first,last).
+template <typename K, typename V>
+inline typename map<K,V>::iterator map<K,V>::find_data (const_data_ref v, iterator first, iterator last)
+{
+    return (const_cast<iterator> (find_data (v, const_cast<const_iterator>(first), const_cast<const_iterator>(last))));
+}
+
+/// Returns data associated with key \p k.
+template <typename K, typename V>
+inline const typename map<K,V>::data_type& map<K,V>::operator[] (const_key_ref k) const
+{
+    assert (find(k) != end() && "operator[] const can not insert non-existent keys");
+    return (find(k)->second);
+}
+
+/// Returns data associated with key \p k.
+template <typename K, typename V>
+typename map<K,V>::data_type& map<K,V>::operator[] (const_key_ref k)
+{
+    iterator ip = lower_bound (k);
+    if (ip == end() || k < ip->first)
+	ip = base_class::insert (ip, make_pair (k, V()));
+    return (ip->second);
+}
+
+/// Inserts the pair into the container.
+template <typename K, typename V>
+typename map<K,V>::iterator map<K,V>::insert (const_reference v)
+{
+    iterator ip = lower_bound (v.first);
+    if (ip == end() || v.first < ip->first)
+	ip = base_class::insert (ip, v);
+    else
+	*ip = v;
+    return (ip);
+}
+
+/// Inserts elements from range [i1,i2) into the container.
+template <typename K, typename V>
+void map<K,V>::insert (const_iterator i1, const_iterator i2)
+{
+    assert (i1 <= i2);
+    reserve (size() + distance (i1, i2));
+    for (; i1 != i2; ++i1)
+	insert (*i1);
+}
+
+/// Erases the element with key value \p k.
+template <typename K, typename V>
+inline void map<K,V>::erase (const_key_ref k)
+{
+    iterator ip = find (k);
+    if (ip != end())
+	erase (ip);
+}
+
+} // namespace ustl
+
+#endif
+
diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/umatrix.h b/media/libdrm/mobile2/src/util/ustl-1.0/umatrix.h
new file mode 100644
index 0000000..e6810f1
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/ustl-1.0/umatrix.h
@@ -0,0 +1,80 @@
+// This file is part of the ustl library, an STL implementation.
+//
+// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
+// This file is free software, distributed under the MIT License.
+//
+// umatrix.h
+//
+
+#ifndef UMATRIX_H_740EBFEF554E833645E0FD72419A8185
+#define UMATRIX_H_740EBFEF554E833645E0FD72419A8185
+
+#include "utuple.h"
+
+namespace ustl {
+
+/// \class matrix umatrix.h ustl.h
+/// \ingroup Sequences
+///
+/// \brief A two-dimensional array of NX*NY elements of type T.
+///
+template <size_t NX, size_t NY, typename T>
+class matrix : public tuple<NX*NY,T> {
+public:
+    typedef tuple<NX,T>					row_type;
+    typedef tuple<NY,T>					column_type;
+    typedef tuple<NX*NY,T>				tuple_type;
+    typedef typename tuple_type::value_type		value_type;
+    typedef typename tuple_type::size_type		size_type;
+    typedef typename tuple_type::pointer		pointer;
+    typedef typename tuple_type::const_pointer		const_pointer;
+    typedef typename tuple_type::reference		reference;
+    typedef typename tuple_type::const_reference	const_reference;
+    typedef typename tuple_type::iterator		iterator;
+    typedef typename tuple_type::const_iterator		const_iterator;
+    typedef typename tuple_type::range_t		range_t;
+    typedef typename tuple_type::const_range_t		const_range_t;
+    typedef typename tuple_type::reverse_iterator	reverse_iterator;
+    typedef typename tuple_type::const_reverse_iterator	const_reverse_iterator;
+public:
+    inline			matrix (void)			{ fill_n (matrix::begin(), NX*NY, T()); }
+    inline size_type		columns (void) const		{ return (NX); }
+    inline size_type		rows (void) const		{ return (NY); }
+    inline const_iterator	at (size_type i) const		{ return (matrix::begin() + i * NX); }
+    inline iterator		at (size_type i)		{ return (matrix::begin() + i * NX); }
+    inline const_iterator	operator[] (size_type i) const	{ return (at (i)); }
+    inline iterator		operator[] (size_type i)	{ return (at (i)); }
+    inline row_type		row (size_type r) const		{ return (row_type (at (r))); }
+    inline column_type		column (size_type c) const;
+    template <typename T2>
+    inline const matrix&	operator= (const matrix<NX,NY,T2>& src)	{ tuple_type::operator= (src); return (*this); }
+    inline const matrix&	operator= (const matrix<NX,NY,T>& src)	{ tuple_type::operator= (src); return (*this); }
+    inline const matrix&	operator+= (const_reference v)		{ tuple_type::operator+= (v); return (*this); }
+    inline const matrix&	operator-= (const_reference v)		{ tuple_type::operator-= (v); return (*this); }
+    inline const matrix&	operator*= (const_reference v)		{ tuple_type::operator*= (v); return (*this); }
+    inline const matrix&	operator/= (const_reference v)		{ tuple_type::operator/= (v); return (*this); }
+    inline const matrix		operator+ (const_reference v) const
+				    { matrix result (*this); result += v; return (result); }
+    inline const matrix		operator- (const_reference v) const
+				    { matrix result (*this); result -= v; return (result); }
+    inline const matrix		operator* (const_reference v) const
+				    { matrix result (*this); result *= v; return (result); }
+    inline const matrix		operator/ (const_reference v) const
+				    { matrix result (*this); result /= v; return (result); }
+};
+
+template <size_t NX, size_t NY, typename T>
+inline typename matrix<NX,NY,T>::column_type matrix<NX,NY,T>::column (size_type c) const
+{
+    column_type result;
+    const_iterator src (matrix::begin() + c);
+    iterator dest (result.begin());
+    for (uoff_t i = 0; i < NY; ++ i, ++ dest, src += NX)
+	*dest = *src;
+    return (result);
+}
+
+} // namespace ustl
+
+#endif
+
diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/umemory.h b/media/libdrm/mobile2/src/util/ustl-1.0/umemory.h
new file mode 100644
index 0000000..75a9005
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/ustl-1.0/umemory.h
@@ -0,0 +1,199 @@
+// This file is part of the ustl library, an STL implementation.
+//
+// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
+// This file is free software, distributed under the MIT License.
+//
+// umemory.h
+//
+
+#ifndef UMEMORY_H_4AB5B0DB5BF09140541409CC47BCD17A
+#define UMEMORY_H_4AB5B0DB5BF09140541409CC47BCD17A
+
+#include "unew.h"
+#ifdef HAVE_ALLOCA_H
+    #include <alloca.h>
+#else
+    #include <stdlib.h>
+#endif
+#include "upair.h"
+#include "uiterator.h"
+#include "ulimits.h"
+
+namespace ustl {
+
+/// \class auto_ptr umemory.h ustl.h
+/// \ingroup MemoryManagement
+///
+/// \brief A smart pointer.
+///
+/// Calls delete in the destructor; assignment transfers ownership.
+/// This class does not work with void pointers due to the absence
+/// of the required dereference operator.
+///
+template <typename T>
+class auto_ptr {
+public:
+    typedef T		value_type;
+    typedef T*		pointer;
+    typedef T&		reference;
+public:
+    /// Takes ownership of \p p.
+    inline explicit	auto_ptr (pointer p = NULL)	: m_p (p) {}
+    /// Takes ownership of pointer in \p p. \p p relinquishes ownership.
+    inline		auto_ptr (auto_ptr<T>& p)	: m_p (p.release()) {}
+    /// Deletes the owned pointer.
+    inline	       ~auto_ptr (void)			{ delete m_p; }
+    /// Returns the pointer without relinquishing ownership.
+    inline pointer	get (void) const		{ return (m_p); }
+    /// Returns the pointer and gives up ownership.
+    inline pointer	release (void)			{ pointer rv (m_p); m_p = NULL; return (rv); }
+    /// Deletes the pointer and sets it equal to \p p.
+    inline void		reset (pointer p)		{ if (p != m_p) { delete m_p; m_p = p; } }
+    /// Takes ownership of \p p.
+    inline auto_ptr<T>&	operator= (pointer p)		{ reset (p); return (*this); }
+    /// Takes ownership of pointer in \p p. \p p relinquishes ownership.
+    inline auto_ptr<T>&	operator= (auto_ptr<T>& p)	{ reset (p.release()); return (*this); }
+    inline reference	operator* (void) const		{ return (*m_p); }
+    inline pointer	operator-> (void) const		{ return (m_p); }
+    inline bool		operator== (const pointer p) const	{ return (m_p == p); }
+    inline bool		operator== (const auto_ptr<T>& p) const	{ return (m_p == p.m_p); }
+    inline bool		operator< (const auto_ptr<T>& p) const	{ return (p.m_p < m_p); }
+private:
+    pointer		m_p;
+};
+
+/// Calls the placement new on \p p.
+/// \ingroup RawStorageAlgorithms
+///
+template <typename T>
+inline void construct (T* p)
+{
+    new (p) T;
+}
+
+/// Calls the placement new on \p p.
+/// \ingroup RawStorageAlgorithms
+///
+template <typename ForwardIterator>
+inline void construct (ForwardIterator first, ForwardIterator last)
+{
+    typedef typename iterator_traits<ForwardIterator>::value_type value_type;
+    if (!numeric_limits<value_type>::is_integral) {
+	while (first < last) {
+	    construct (&*first);
+	    ++ first;
+	}
+    }
+}
+
+/// Calls the placement new on \p p.
+/// \ingroup RawStorageAlgorithms
+///
+template <typename T>
+inline void construct (T* p, const T& value)
+{
+    new (p) T (value);
+}
+
+/// Calls the destructor of \p p without calling delete.
+/// \ingroup RawStorageAlgorithms
+///
+template <typename T>
+inline void destroy (T* p) throw()
+{
+    p->~T();
+}
+
+/// Calls the destructor on elements in range [first, last) without calling delete.
+/// \ingroup RawStorageAlgorithms
+///
+template <typename ForwardIterator>
+inline void destroy (ForwardIterator first, ForwardIterator last) throw()
+{
+    typedef typename iterator_traits<ForwardIterator>::value_type value_type;
+    if (!numeric_limits<value_type>::is_integral)
+	for (; first < last; ++ first)
+	    destroy (&*first);
+}
+
+/// Casts \p p to the type of the second pointer argument.
+template <typename T> inline T* cast_to_type (void* p, const T*) { return ((T*) p); }
+
+/// \brief Creates a temporary buffer pair from \p p and \p n
+/// This is intended to be used with alloca to create temporary buffers.
+/// The size in the returned pair is set to 0 if the allocation is unsuccessful.
+/// \ingroup RawStorageAlgorithms
+///
+template <typename T>
+inline pair<T*, ptrdiff_t> make_temporary_buffer (void* p, size_t n, const T* ptype)
+{
+    return (make_pair (cast_to_type(p,ptype), ptrdiff_t(p ? n : 0)));
+}
+
+#ifdef HAVE_ALLOCA_H
+    /// \brief Allocates a temporary buffer, if possible.
+    /// \ingroup RawStorageAlgorithms
+    #define get_temporary_buffer(size, ptype)	make_temporary_buffer (alloca(size_of_elements(size, ptype)), size, ptype)
+    #define return_temporary_buffer(p)
+#else
+    #define get_temporary_buffer(size, ptype)	make_temporary_buffer (malloc(size_of_elements(size, ptype)), size, ptype)
+    #define return_temporary_buffer(p)		if (p) free (p), p = NULL
+#endif
+
+/// Copies [first, last) into result by calling copy constructors in result.
+/// \ingroup RawStorageAlgorithms
+///
+template <typename InputIterator, typename ForwardIterator>
+ForwardIterator uninitialized_copy (InputIterator first, InputIterator last, ForwardIterator result)
+{
+    while (first < last) {
+	construct (&*result, *first);
+	++ result;
+	++ first;
+    }
+    return (result);
+}
+
+/// Copies [first, first + n) into result by calling copy constructors in result.
+/// \ingroup RawStorageAlgorithms
+///
+template <typename InputIterator, typename ForwardIterator>
+ForwardIterator uninitialized_copy_n (InputIterator first, size_t n, ForwardIterator result)
+{
+    while (n--) {
+	construct (&*result, *first);
+	++ result;
+	++ first;
+    }
+    return (result);
+}
+
+/// Calls construct on all elements in [first, last) with value \p v.
+/// \ingroup RawStorageAlgorithms
+///
+template <typename ForwardIterator, typename T>
+void uninitialized_fill (ForwardIterator first, ForwardIterator last, const T& v)
+{
+    while (first < last) {
+	construct (&*first, v);
+	++ first;
+    }
+}
+
+/// Calls construct on all elements in [first, first + n) with value \p v.
+/// \ingroup RawStorageAlgorithms
+///
+template <typename ForwardIterator, typename T>
+ForwardIterator uninitialized_fill_n (ForwardIterator first, size_t n, const T& v)
+{
+    while (n--) {
+	construct (&*first, v);
+	++ first;
+    }
+    return (first);
+}
+    
+} // namespace ustl
+
+#endif
+
diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/umultimap.h b/media/libdrm/mobile2/src/util/ustl-1.0/umultimap.h
new file mode 100644
index 0000000..dd6ca48
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/ustl-1.0/umultimap.h
@@ -0,0 +1,121 @@
+// This file is part of the ustl library, an STL implementation.
+//
+// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
+// This file is free software, distributed under the MIT License.
+//
+// umultimap.h
+//
+
+#ifndef UMULTIMAP_H_45743F516E02A87A3FCEA5024052A6F5
+#define UMULTIMAP_H_45743F516E02A87A3FCEA5024052A6F5
+
+#include "uassert.h"
+#include "ufunction.h"
+#include "uvector.h"
+
+namespace ustl {
+
+/// \class multimap umultimap.h ustl.h
+/// \ingroup AssociativeContainers
+///
+/// \brief A sorted associative container that may container multiple entries for each key.
+///
+template <typename K, typename V>
+class multimap : public vector<pair<K,V> > {
+public:
+    typedef K						key_type;
+    typedef V						data_type;
+    typedef const K&					const_key_ref;
+    typedef const V&					const_data_ref;
+    typedef const multimap<K,V>&			rcself_t;
+    typedef vector<pair<K,V> >				base_class;
+    typedef typename base_class::value_type	value_type;
+    typedef typename base_class::size_type	size_type;
+    typedef typename base_class::pointer	pointer;
+    typedef typename base_class::const_pointer	const_pointer;
+    typedef typename base_class::reference	reference;
+    typedef typename base_class::const_reference	const_reference;
+    typedef typename base_class::const_iterator		const_iterator;
+    typedef typename base_class::iterator		iterator;
+    typedef typename base_class::reverse_iterator	reverse_iterator;
+    typedef typename base_class::const_reverse_iterator	const_reverse_iterator;
+    typedef pair<const_iterator,const_iterator>		const_range_t;
+    typedef pair<iterator,iterator>			range_t;
+public:
+    inline			multimap (void)		: vector<pair<K,V> > () {} 
+    explicit inline		multimap (size_type n)	: vector<pair<K,V> > (n) {} 
+    inline			multimap (rcself_t v)	: vector<pair<K,V> > (v) {} 
+    inline			multimap (const_iterator i1, const_iterator i2)	: vector<pair<K,V> > () { insert (i1, i2); } 
+    inline rcself_t		operator= (rcself_t v)	{ base_class::operator= (v); return (*this); }
+    inline size_type		size (void) const	{ return (base_class::size()); }
+    inline iterator		begin (void)		{ return (base_class::begin()); }
+    inline const_iterator	begin (void) const	{ return (base_class::begin()); }
+    inline iterator		end (void)		{ return (base_class::end()); }
+    inline const_iterator	end (void) const	{ return (base_class::end()); }
+    inline void			assign (const_iterator i1, const_iterator i2) { clear(); insert (i1, i2); }
+    inline size_type		count (const_key_ref k) const		{ return (upper_bound(k) - lower_bound(k)); }
+    inline void			push_back (const_reference v)		{ insert (v); }
+    inline const_range_t	equal_range (const_key_ref k) const	{ return (make_pair (lower_bound(k), upper_bound(k))); }
+    inline range_t		equal_range (const_key_ref k)		{ return (make_pair (const_cast<iterator>(lower_bound(k)), const_cast<iterator>(upper_bound(k)))); }
+    const_iterator		lower_bound (const_key_ref k) const;
+    const_iterator		upper_bound (const_key_ref k) const;
+    inline iterator		insert (const_reference v);
+    void			insert (const_iterator i1, const_iterator i2);
+    inline void			erase (const_key_ref k)			{ erase (const_cast<iterator>(lower_bound(k)), const_cast<iterator>(upper_bound(k))); }
+    inline iterator		erase (iterator ep)			{ return (base_class::erase (ep)); } 
+    inline iterator		erase (iterator ep1, iterator ep2)	{ return (base_class::erase (ep1, ep2)); } 
+    inline void			clear (void)				{ base_class::clear(); }
+};
+
+/// Returns an iterator to the first element with key value \p k.
+template <typename K, typename V>
+typename multimap<K,V>::const_iterator multimap<K,V>::lower_bound (const_key_ref k) const
+{
+    const_iterator first (begin()), last (end());
+    while (first != last) {
+	const_iterator mid = advance (first, distance (first,last) / 2);
+	if (mid->first < k)
+	    first = advance (mid, 1);
+	else
+	    last = mid;
+    }
+    return (first);
+}
+
+/// Returns an iterator to the first element with key value \p k.
+template <typename K, typename V>
+typename multimap<K,V>::const_iterator multimap<K,V>::upper_bound (const_key_ref k) const
+{
+    const_iterator first (begin()), last (end());
+    while (first != last) {
+	const_iterator mid = advance (first, distance (first,last) / 2);
+	if (k < mid->first)
+	    last = mid;
+	else
+	    first = advance (mid, 1);
+    }
+    return (last);
+}
+
+/// Inserts the pair into the container.
+template <typename K, typename V>
+inline typename multimap<K,V>::iterator multimap<K,V>::insert (const_reference v)
+{
+    iterator ip = const_cast<iterator> (upper_bound (v.first));
+    return (base_class::insert (ip, v));
+}
+
+/// Inserts elements from range [i1,i2) into the container.
+template <typename K, typename V>
+void multimap<K,V>::insert (const_iterator i1, const_iterator i2)
+{
+    assert (i1 <= i2);
+    reserve (size() + distance (i1, i2));
+    for (; i1 != i2; ++i1)
+	insert (*i1);
+}
+
+} // namespace ustl
+
+#endif
+
diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/umultiset.h b/media/libdrm/mobile2/src/util/ustl-1.0/umultiset.h
new file mode 100644
index 0000000..404b877
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/ustl-1.0/umultiset.h
@@ -0,0 +1,106 @@
+// This file is part of the ustl library, an STL implementation.
+//
+// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
+// This file is free software, distributed under the MIT License.
+//
+// umultiset.h
+//
+
+#ifndef UMULTISET_H_446AEDBB7F61C6994DC228C25D5FA3A1
+#define UMULTISET_H_446AEDBB7F61C6994DC228C25D5FA3A1
+
+#include "uassert.h"
+#include "ualgo.h"
+#include "uvector.h"
+
+namespace ustl {
+
+/// \class multiset umultiset.h ustl.h
+/// \ingroup AssociativeContainers
+///
+/// \brief Multiple sorted container.
+/// Unlike set, it may contain multiple copies of each element.
+///
+template <typename T>
+class multiset : public vector<T> {
+public:
+    typedef const multiset<T>&				rcself_t;
+    typedef vector<T>					base_class;
+    typedef typename base_class::value_type		value_type;
+    typedef typename base_class::size_type		size_type;
+    typedef typename base_class::pointer		pointer;
+    typedef typename base_class::const_pointer		const_pointer;
+    typedef typename base_class::reference		reference;
+    typedef typename base_class::const_reference	const_reference;
+    typedef typename base_class::const_iterator		const_iterator;
+    typedef typename base_class::iterator		iterator;
+    typedef typename base_class::reverse_iterator	reverse_iterator;
+    typedef typename base_class::const_reverse_iterator	const_reverse_iterator;
+public:
+    inline			multiset (void)		: vector<T> () {}
+    explicit inline		multiset (size_type n)	: vector<T> (n) {}
+    inline			multiset (rcself_t v)	: vector<T> (v) {} 
+    inline			multiset (const_iterator i1, const_iterator i2) : vector<T> () { insert (i1, i2); }
+    inline rcself_t		operator= (rcself_t v)	{ base_class::operator= (v); return (*this); }
+    inline size_type		size (void) const	{ return (base_class::size()); }
+    inline iterator		begin (void)		{ return (base_class::begin()); }
+    inline const_iterator	begin (void) const	{ return (base_class::begin()); }
+    inline iterator		end (void)		{ return (base_class::end()); }
+    inline const_iterator	end (void) const	{ return (base_class::end()); }
+    inline void			assign (const_iterator i1, const_iterator i2);
+    size_type			count (const_reference v) const;
+    inline void			push_back (const_reference v)	{ insert (v); }
+    inline iterator		insert (const_reference v);
+    void			insert (const_iterator i1, const_iterator i2);
+    void			erase (const_reference v);
+    inline iterator		erase (iterator ep)	{ return (base_class::erase (ep)); }
+    inline iterator		erase (iterator ep1, iterator ep2) { return (base_class::erase (ep1, ep2)); }
+    inline void			clear (void)		{ base_class::clear(); }
+};
+
+/// Copies contents of range [i1,i2)
+template <typename T>
+inline void multiset<T>::assign (const_iterator i1, const_iterator i2)
+{
+    base_class::clear();
+    insert (i1, i2);
+}
+
+/// Returns the number of elements of value \p v.
+template <typename T>
+typename multiset<T>::size_type multiset<T>::count (const_reference v) const
+{
+    const pair<const_iterator,const_iterator> fr = equal_range (begin(), end(), v);
+    return (distance (fr.first, fr.second));
+}
+
+/// Inserts \p v.
+template <typename T>
+inline typename multiset<T>::iterator multiset<T>::insert (const_reference v)
+{
+    iterator ip = upper_bound (begin(), end(), v);
+    return (base_class::insert (ip, v));
+}
+
+/// Inserts all elements from range [i1,i2).
+template <typename T>
+void multiset<T>::insert (const_iterator i1, const_iterator i2)
+{
+    assert (i1 <= i2);
+    reserve (size() + distance (i1, i2));
+    for (; i1 < i2; ++i1)
+	push_back (*i1);
+}
+
+/// Erases all elements with value \p v.
+template <typename T>
+void multiset<T>::erase (const_reference v)
+{
+    pair<iterator,iterator> epr = equal_range (begin(), end(), v);
+    erase (epr.first, epr.second);
+}
+
+} // namespace ustl
+
+#endif
+
diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/unew.cpp b/media/libdrm/mobile2/src/util/ustl-1.0/unew.cpp
new file mode 100644
index 0000000..084e053
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/ustl-1.0/unew.cpp
@@ -0,0 +1,33 @@
+// This file is part of the ustl library, an STL implementation.
+//
+// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
+// This file is free software, distributed under the MIT License.
+//
+// unew.cc
+//
+
+#include "unew.h"
+#include <stdlib.h>
+
+#if PLATFORM_ANDROID
+#include <stdio.h>
+#endif
+
+void* throwing_malloc (size_t n) throw (ustl::bad_alloc)
+{
+    void* p = malloc (n);
+    if (!p)
+#if PLATFORM_ANDROID
+        printf("bad alloc\n");
+#else
+	throw ustl::bad_alloc (n);
+#endif
+    return (p);
+}
+
+void free_nullok (void* p) throw()
+{
+    if (p)
+	free (p);
+}
+
diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/unew.h b/media/libdrm/mobile2/src/util/ustl-1.0/unew.h
new file mode 100644
index 0000000..c4ffb62
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/ustl-1.0/unew.h
@@ -0,0 +1,52 @@
+// This file is part of the ustl library, an STL implementation.
+//
+// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
+// This file is free software, distributed under the MIT License.
+//
+/// \file unew.h
+///
+/// \brief Same as \<new\>, but throws ustl:: exceptions.
+//
+
+#ifndef UNEW_H_11D237512B324C9C05A55DAF1BF086F1
+#define UNEW_H_11D237512B324C9C05A55DAF1BF086F1
+
+#include "uexception.h"
+
+/// Just like malloc, but throws on failure.
+void* throwing_malloc (size_t n) throw (ustl::bad_alloc);
+/// Just like free, but doesn't crash when given a NULL.
+void free_nullok (void* p) throw();
+
+#ifdef WITHOUT_LIBSTDCPP
+
+//
+// These are replaceable signatures:
+//  - normal single new and delete (no arguments, throw @c bad_alloc on error)
+//  - normal array new and delete (same)
+//  - @c nothrow single new and delete (take a @c nothrow argument, return
+//    @c NULL on error)
+//  - @c nothrow array new and delete (same)
+//
+//  Placement new and delete signatures (take a memory address argument,
+//  does nothing) may not be replaced by a user's program.
+//
+inline void* operator new (size_t n) throw (ustl::bad_alloc)	{ return (throwing_malloc (n)); }
+inline void* operator new[] (size_t n) throw (ustl::bad_alloc)	{ return (throwing_malloc (n)); }
+inline void  operator delete (void* p) throw()			{ free_nullok (p); }
+inline void  operator delete[] (void* p) throw()		{ free_nullok (p); }
+
+// Default placement versions of operator new.
+inline void* operator new (size_t, void* p) throw() { return (p); }
+inline void* operator new[] (size_t, void* p) throw() { return (p); }
+
+// Default placement versions of operator delete.
+inline void  operator delete  (void*, void*) throw() { }
+inline void  operator delete[](void*, void*) throw() { }
+
+#else
+#include <new>
+#endif	// WITHOUT_LIBSTDCPP
+
+#endif
+
diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/unumeric.h b/media/libdrm/mobile2/src/util/ustl-1.0/unumeric.h
new file mode 100644
index 0000000..4883eb4
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/ustl-1.0/unumeric.h
@@ -0,0 +1,160 @@
+// This file is part of the ustl library, an STL implementation.
+//
+// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
+// This file is free software, distributed under the MIT License.
+//
+// unumeric.h
+//
+//	This file contains numeric algorithm templates.
+//
+
+#ifndef UNUMERIC_H_6C99D6F6363832C644A6FFF336E84E18
+#define UNUMERIC_H_6C99D6F6363832C644A6FFF336E84E18
+
+namespace ustl {
+
+/// Returns the sum of all elements in [first, last) added to \p init.
+/// \ingroup NumericAlgorithms
+///
+template <typename InputIterator, typename T>
+inline T accumulate (InputIterator first, InputIterator last, T init)
+{
+    while (first < last)
+	init += *first++;
+    return (init);
+}
+
+/// Returns the sum of all elements in [first, last) via \p op, added to \p init.
+/// \ingroup NumericAlgorithms
+///
+template <typename InputIterator, typename T, typename BinaryFunction>
+inline T accumulate (InputIterator first, InputIterator last, T init, BinaryFunction binary_op)
+{
+    while (first < last)
+	init = binary_op (init, *first++);
+    return (init);
+}
+
+/// Assigns range [value, value + (last - first)) to [first, last)
+/// \ingroup NumericAlgorithms
+///
+template <typename ForwardIterator, typename T>
+inline void iota (ForwardIterator first, ForwardIterator last, T value)
+{
+    while (first < last)
+	*first++ = value++;
+}
+
+/// Returns the sum of products of respective elements in the given ranges.
+/// \ingroup NumericAlgorithms
+///
+template <typename InputIterator1, typename InputIterator2, typename T>
+inline T inner_product (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, T init)
+{
+    while (first1 < last1)
+	init += *first1++ * *first2++;
+    return (init);
+}
+
+/// Returns the sum of products of respective elements in the given ranges.
+/// \ingroup NumericAlgorithms
+///
+template <typename InputIterator1, typename InputIterator2, typename T,
+    	  typename BinaryOperation1, typename BinaryOperation2>
+inline T inner_product
+(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, T init,
+ BinaryOperation1 sumOp, BinaryOperation2 productOp)
+{
+    while (first1 < last1)
+	init = sumOp (init, productOp (*first1++, *first2++));
+    return (init);
+}
+
+/// Writes result such that result[i] = sum (first...first+i)
+/// \ingroup NumericAlgorithms
+///
+template <typename InputIterator, typename OutputIterator>
+inline OutputIterator partial_sum (InputIterator first, InputIterator last, OutputIterator result)
+{
+    if (first < last)
+	*result = *first++;
+    while (first < last)
+	*++result = *first++ + *result;
+    return (result);
+}
+
+/// Writes result such that result[i] = sumOp (first...first+i)
+/// \ingroup NumericAlgorithms
+///
+template <typename InputIterator, typename OutputIterator, typename BinaryOperation>
+inline OutputIterator partial_sum (InputIterator first, InputIterator last, OutputIterator result, BinaryOperation sumOp)
+{
+    if (first < last)
+	*result = *first++;
+    while (first < last)
+	*++result = sumOp (*first++, *result);
+    return (result);
+}
+
+/// Writes result such that result[i] = first[i] - first[i - 1]
+/// \ingroup NumericAlgorithms
+///
+template <typename InputIterator, typename OutputIterator>
+inline OutputIterator adjacent_difference (InputIterator first, InputIterator last, OutputIterator result)
+{
+    if (first < last)
+	*result++ = *first++;
+    while (first < last)
+	*result++ = *first - *(first - 1);
+    return (result);
+}
+
+/// Writes result such that result[i] = differenceOp (first[i], first[i - 1])
+/// \ingroup NumericAlgorithms
+///
+template <typename InputIterator, typename OutputIterator, typename BinaryOperation>
+inline OutputIterator adjacent_difference (InputIterator first, InputIterator last, OutputIterator result, BinaryOperation differenceOp)
+{
+    if (first < last)
+	*result++ = *first++;
+    while (first < last)
+	*result++ = differenceOp (*first, *(first - 1));
+    return (result);
+}
+
+/// \brief Returns x^n.
+/// Donald Knuth's Russian Peasant algorithm.
+/// \ingroup NumericAlgorithms
+///
+template <typename T>
+inline T power (T x, unsigned n)
+{
+    T result (n % 2 ? x : 1);
+    while (n /= 2) {
+	x *= x;
+	if (n % 2)
+	    result *= x;
+    }
+    return (result);
+}
+
+/// \brief Returns x^n, using \p op instead of multiplication.
+/// Donald Knuth's Russian Peasant algorithm.
+/// \ingroup NumericAlgorithms
+///
+template <typename T, typename BinaryOperation>
+inline T power (T x, unsigned n, BinaryOperation op)
+{
+    T result (n % 2 ? x : 1);
+    while (n /= 2) {
+	x = op (x, x);
+	if (n % 2)
+	    result = op (result, x);
+    }
+    return (result);
+}
+
+} // namespace ustl
+
+#endif
+
diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/upair.h b/media/libdrm/mobile2/src/util/ustl-1.0/upair.h
new file mode 100644
index 0000000..b4cc3b7
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/ustl-1.0/upair.h
@@ -0,0 +1,63 @@
+// This file is part of the ustl library, an STL implementation.
+//
+// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
+// This file is free software, distributed under the MIT License.
+//
+/// \file upair.h
+/// \brief Pair-related functionality.
+
+#ifndef UPAIR_H_7DC08F1B7FECF8AE6856D84C3B617A75
+#define UPAIR_H_7DC08F1B7FECF8AE6856D84C3B617A75
+
+#include "utypes.h"
+
+namespace ustl {
+
+/// \class pair upair.h ustl.h
+/// \ingroup AssociativeContainers
+///
+/// \brief Container for two values.
+///
+template <typename T1, typename T2>
+class pair {
+public:
+    typedef T1		first_type;
+    typedef T2		second_type;
+public:
+    /// Default constructor.
+    inline pair (void)				: first (T1()), second (T2()) {}
+    /// Initializes members with \p a, and \p b.
+    inline pair (const T1& a, const T2& b)	: first (a), second (b) {}
+    inline pair&	operator= (const pair<T1, T2>& p2) { first = p2.first; second = p2.second; return (*this); }
+    template <typename T3, typename T4>
+    inline pair&	operator= (const pair<T3, T4>& p2) { first = p2.first; second = p2.second; return (*this); }
+public:
+    first_type		first;
+    second_type		second;
+};
+
+/// Compares both values of \p p1 to those of \p p2.
+template <typename T1, typename T2>
+inline bool operator== (const pair<T1,T2>& p1, const pair<T1,T2>& p2)
+{
+    return (p1.first == p2.first && p1.second == p2.second);
+}
+
+/// Compares both values of \p p1 to those of \p p2.
+template <typename T1, typename T2>
+bool operator< (const pair<T1,T2>& p1, const pair<T1,T2>& p2)
+{
+    return (p1.first < p2.first || (p1.first == p2.first && p1.second < p2.second));
+}
+
+/// Returns a pair object with (a,b)
+template <typename T1, typename T2>
+inline pair<T1,T2> make_pair (const T1& a, const T2& b)
+{
+    return (pair<T1,T2> (a, b));
+}
+
+} // namespace ustl
+
+#endif
+
diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/upredalgo.h b/media/libdrm/mobile2/src/util/ustl-1.0/upredalgo.h
new file mode 100644
index 0000000..562a3d6
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/ustl-1.0/upredalgo.h
@@ -0,0 +1,597 @@
+// This file is part of the ustl library, an STL implementation.
+//
+// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
+// This file is free software, distributed under the MIT License.
+//
+// ualgo.h
+//
+// Implementation of STL algorithms with custom predicates.
+//
+// The function prototypes are copied
+// exactly from the SGI version of STL documentation along with comments about
+// their use. The code is NOT the same, though the functionality usually is.
+//
+
+#ifndef UPREDALGO_H_2CB058AE0807A01A2F6A51BA5D5820A5
+#define UPREDALGO_H_2CB058AE0807A01A2F6A51BA5D5820A5
+
+namespace ustl {
+
+/// Copy_if copies elements from the range [first, last) to the range
+/// [result, result + (last - first)) if pred(*i) returns true.
+/// \ingroup MutatingAlgorithms
+/// \ingroup PredicateAlgorithms
+///
+template <typename InputIterator, typename OutputIterator, typename Predicate>
+inline OutputIterator copy_if (InputIterator first, InputIterator last, OutputIterator result, Predicate pred)
+{
+    for (; first != last; ++first) {
+	if (pred(*first)) {
+	    *result = *first;
+	    ++ result;
+	}
+    }
+    return (result);
+}
+
+/// Returns the first iterator i in the range [first, last) such that
+/// pred(*i) is true. Returns last if no such iterator exists.
+/// \ingroup SearchingAlgorithms
+/// \ingroup PredicateAlgorithms
+///
+template <typename InputIterator, typename Predicate>
+inline InputIterator find_if (InputIterator first, InputIterator last, Predicate pred)
+{
+    while (first != last && !pred (*first))
+	++ first;
+    return (first);
+}
+
+/// Returns the first iterator such that p(*i, *(i + 1)) == true.
+/// \ingroup SearchingAlgorithms
+/// \ingroup PredicateAlgorithms
+///
+template <typename ForwardIterator, typename BinaryPredicate>
+inline ForwardIterator adjacent_find (ForwardIterator first, ForwardIterator last, BinaryPredicate p)
+{
+    if (first != last)
+	for (ForwardIterator prev = first; ++first != last; ++ prev)
+	    if (p (*prev, *first))
+		return (prev);
+    return (last);
+}
+
+/// Returns the pointer to the first pair of unequal elements.
+/// \ingroup SearchingAlgorithms
+/// \ingroup PredicateAlgorithms
+///
+template <typename InputIterator, typename BinaryPredicate>
+inline pair<InputIterator,InputIterator>
+mismatch (InputIterator first1, InputIterator last1, InputIterator first2, BinaryPredicate comp)
+{
+    while (first1 != last1 && comp(*first1, *first2))
+	++ first1, ++ first2;
+    return (make_pair (first1, first2));
+}
+
+/// Returns true if two ranges are equal.
+/// This is an extension, present in uSTL and SGI STL.
+/// \ingroup ConditionAlgorithms
+/// \ingroup PredicateAlgorithms
+///
+template <typename InputIterator, typename BinaryPredicate>
+inline bool equal (InputIterator first1, InputIterator last1, InputIterator first2, BinaryPredicate comp)
+{
+    return (mismatch (first1, last1, first2, comp).first == last1);
+}
+
+/// Count_if finds the number of elements in [first, last) that satisfy the
+/// predicate pred. More precisely, the first version of count_if returns the
+/// number of iterators i in [first, last) such that pred(*i) is true.
+/// \ingroup ConditionAlgorithms
+/// \ingroup PredicateAlgorithms
+///
+template <typename InputIterator, typename Predicate>
+inline size_t count_if (InputIterator first, InputIterator last, Predicate pred)
+{
+    size_t total = 0;
+    for (; first != last; ++first)
+	if (pred (*first))
+	    ++ total;
+    return (total);
+}
+
+/// Replace_if replaces every element in the range [first, last) for which
+/// pred returns true with new_value. That is: for every iterator i, if
+/// pred(*i) is true then it performs the assignment *i = new_value.
+/// \ingroup MutatingAlgorithms
+/// \ingroup PredicateAlgorithms
+///
+template <typename ForwardIterator, typename Predicate, typename T>
+inline void replace_if (ForwardIterator first, ForwardIterator last, Predicate pred, const T& new_value)
+{
+    for (; first != last; ++first)
+	if (pred (*first))
+	    *first = new_value;
+}
+
+/// Replace_copy_if copies elements from the range [first, last) to the range
+/// [result, result + (last-first)), except that any element for which pred is
+/// true is not copied; new_value is copied instead. More precisely, for every
+/// integer n such that 0 <= n < last-first, replace_copy_if performs the
+/// assignment *(result+n) = new_value if pred(*(first+n)),
+/// and *(result+n) = *(first+n) otherwise.
+/// \ingroup MutatingAlgorithms
+/// \ingroup PredicateAlgorithms
+///
+template <typename InputIterator, typename OutputIterator, typename Predicate, typename T>
+inline OutputIterator replace_copy_if (InputIterator first, InputIterator last, OutputIterator result, Predicate pred, const T& new_value) 
+{
+    for (; first != last; ++result, ++first)
+        *result = pred(*first) ? new_value : *first;
+}
+
+/// Remove_copy_if copies elements from the range [first, last) to a range
+/// beginning at result, except that elements for which pred is true are not
+/// copied. The return value is the end of the resulting range. This operation
+/// is stable, meaning that the relative order of the elements that are copied
+/// is the same as in the range [first, last).
+/// \ingroup MutatingAlgorithms
+/// \ingroup PredicateAlgorithms
+///
+template <typename InputIterator, typename OutputIterator, typename Predicate>
+inline OutputIterator remove_copy_if (InputIterator first, InputIterator last, OutputIterator result, Predicate pred)
+{
+    for (; first != last; ++first)
+	if (pred (*first))
+	    *result++ = *first;
+    return (result);
+}
+
+/// Remove_if removes from the range [first, last) every element x such that
+/// pred(x) is true. That is, remove_if returns an iterator new_last such that
+/// the range [first, new_last) contains no elements for which pred is true.
+/// The iterators in the range [new_last, last) are all still dereferenceable,
+/// but the elements that they point to are unspecified. Remove_if is stable,
+/// meaning that the relative order of elements that are not removed is
+/// unchanged.
+/// \ingroup MutatingAlgorithms
+/// \ingroup PredicateAlgorithms
+///
+template <typename ForwardIterator, typename Predicate>
+inline ForwardIterator remove_if (ForwardIterator first, ForwardIterator last, Predicate pred)
+{
+    return (remove_copy_if (first, last, first, pred));
+}
+
+/// The reason there are two different versions of unique_copy is that there
+/// are two different definitions of what it means for a consecutive group of
+/// elements to be duplicates. In the first version, the test is simple
+/// equality: the elements in a range [f, l) are duplicates if, for every
+/// iterator i in the range, either i == f or else *i == *(i-1). In the second,
+/// the test is an arbitrary Binary Predicate binary_pred: the elements in
+/// [f, l) are duplicates if, for every iterator i in the range, either
+/// i == f or else binary_pred(*i, *(i-1)) is true.
+/// \ingroup MutatingAlgorithms
+/// \ingroup PredicateAlgorithms
+///
+template <typename InputIterator, typename OutputIterator, typename BinaryPredicate>
+OutputIterator unique_copy (InputIterator first, InputIterator last, OutputIterator result, BinaryPredicate binary_pred)
+{
+    if (first != last) {
+	*result = *first;
+	while (++first != last)
+	    if (!binary_pred (*first, *result))
+		*++result = *first;
+	++ result;
+    }
+    return (result);
+}
+
+/// Every time a consecutive group of duplicate elements appears in the range
+/// [first, last), the algorithm unique removes all but the first element.
+/// That is, unique returns an iterator new_last such that the range [first,
+/// new_last) contains no two consecutive elements that are duplicates.
+/// The iterators in the range [new_last, last) are all still dereferenceable,
+/// but the elements that they point to are unspecified. Unique is stable,
+/// meaning that the relative order of elements that are not removed is
+/// unchanged.
+/// \ingroup MutatingAlgorithms
+/// \ingroup PredicateAlgorithms
+///
+template <typename ForwardIterator, typename BinaryPredicate>
+inline ForwardIterator unique (ForwardIterator first, ForwardIterator last, BinaryPredicate binary_pred)
+{
+    return (unique_copy (first, last, first, binary_pred));
+}
+
+/// Returns the furthermost iterator i in [first, last) such that,
+/// for every iterator j in [first, i), comp(*j, value) is true.
+/// Assumes the range is sorted.
+/// \ingroup SearchingAlgorithms
+/// \ingroup PredicateAlgorithms
+///
+template <typename ForwardIterator, typename T, typename StrictWeakOrdering>
+ForwardIterator lower_bound (ForwardIterator first, ForwardIterator last, const T& value, StrictWeakOrdering comp)
+{
+    ForwardIterator mid;
+    while (first != last) {
+	mid = advance (first, distance (first,last) / 2);
+	if (comp (*mid, value))
+	    first = mid + 1;
+	else
+	    last = mid;
+    }
+    return (first);
+}
+
+/// Performs a binary search inside the sorted range.
+/// \ingroup SearchingAlgorithms
+/// \ingroup PredicateAlgorithms
+///
+template <typename ForwardIterator, typename T, typename StrictWeakOrdering>
+inline ForwardIterator binary_search (ForwardIterator first, ForwardIterator last, const T& value, StrictWeakOrdering comp)
+{
+    ForwardIterator found = lower_bound (first, last, value, comp);
+    return ((found == last || comp(value, *found)) ? last : found);
+}
+
+/// Returns the furthermost iterator i in [first,last) such that for
+/// every iterator j in [first,i), comp(value,*j) is false.
+/// \ingroup SearchingAlgorithms
+/// \ingroup PredicateAlgorithms
+///
+template <typename ForwardIterator, typename T, typename StrictWeakOrdering>
+ForwardIterator upper_bound (ForwardIterator first, ForwardIterator last, const T& value, StrictWeakOrdering comp)
+{
+    ForwardIterator mid;
+    while (first != last) {
+	mid = advance (first, distance (first,last) / 2);
+	if (comp (value, *mid))
+	    last = mid;
+	else
+	    first = mid + 1;
+    }
+    return (last);
+}
+
+/// Returns pair<lower_bound,upper_bound>
+/// \ingroup SearchingAlgorithms
+/// \ingroup PredicateAlgorithms
+///
+template <typename ForwardIterator, typename T, typename StrictWeakOrdering>
+inline pair<ForwardIterator,ForwardIterator> equal_range (ForwardIterator first, ForwardIterator last, const T& value, StrictWeakOrdering comp)
+{
+    pair<ForwardIterator,ForwardIterator> rv;
+    rv.second = rv.first = lower_bound (first, last, value, comp);
+    while (rv.second != last && !comp(value, *(rv.second)))
+	++ rv.second;
+    return (rv);
+}
+
+/// \brief Puts \p nth element into its sorted position.
+/// In this implementation, the entire array is sorted. The performance difference is
+/// so small and the function use is so rare, there is no need to have code for it.
+/// \ingroup SortingAlgorithms
+/// \ingroup SearchingAlgorithms
+/// \ingroup PredicateAlgorithms
+///
+template <typename RandomAccessIterator, typename Compare>
+inline void nth_element (RandomAccessIterator first, RandomAccessIterator, RandomAccessIterator last, Compare comp)
+{
+    sort (first, last, comp);
+}
+
+/// \brief Searches for the first subsequence [first2,last2) in [first1,last1)
+/// \ingroup SearchingAlgorithms
+/// \ingroup PredicateAlgorithms
+template <typename ForwardIterator1, typename ForwardIterator2, typename BinaryPredicate>
+ForwardIterator1 search (ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate comp)
+{
+    const ForwardIterator1 slast = last1 - distance(first2, last2) + 1;
+    for (; first1 < slast; ++first1) {
+	ForwardIterator2 i = first2;
+	ForwardIterator1 j = first1;
+	for (; i != last2 && comp(*j, *i); ++i, ++j);
+	if (i == last2)
+	    return (first1);
+    }
+    return (last1);
+}
+
+/// \brief Searches for the last subsequence [first2,last2) in [first1,last1)
+/// \ingroup SearchingAlgorithms
+/// \ingroup PredicateAlgorithms
+template <typename ForwardIterator1, typename ForwardIterator2, typename BinaryPredicate>
+ForwardIterator1 find_end (ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate comp)
+{
+    ForwardIterator1 s = last1 - distance(first2, last2);
+    for (; first1 < s; --s) {
+	ForwardIterator2 i = first2, j = s;
+	for (; i != last2 && comp(*j, *i); ++i, ++j);
+	if (i == last2)
+	    return (s);
+    }
+    return (last1);
+}
+
+/// \brief Searches for the first occurence of \p count \p values in [first, last)
+/// \ingroup SearchingAlgorithms
+/// \ingroup PredicateAlgorithms
+template <typename Iterator, typename T, typename BinaryPredicate>
+Iterator search_n (Iterator first, Iterator last, size_t count, const T& value, BinaryPredicate comp)
+{
+    size_t n = 0;
+    for (; first != last; ++first) {
+	if (!comp (*first, value))
+	    n = 0;
+	else if (++n == count)
+	    return (first - --n);
+    }
+    return (last);
+}
+
+/// \brief Searches [first1,last1) for the first occurrence of an element from [first2,last2)
+/// \ingroup SearchingAlgorithms
+/// \ingroup PredicateAlgorithms
+template <typename InputIterator, typename ForwardIterator, typename BinaryPredicate>
+InputIterator find_first_of (InputIterator first1, InputIterator last1, ForwardIterator first2, ForwardIterator last2, BinaryPredicate comp)
+{
+    for (; first1 != last1; ++first1)
+	for (ForwardIterator i = first2; i != last2; ++i)
+	    if (comp (*first1, *i))
+		return (first1);
+    return (first1);
+}
+
+/// \brief Returns true if [first2,last2) is a subset of [first1,last1)
+/// \ingroup ConditionAlgorithms
+/// \ingroup SetAlgorithms
+/// \ingroup PredicateAlgorithms
+template <typename InputIterator1, typename InputIterator2, typename StrictWeakOrdering>
+bool includes (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, StrictWeakOrdering comp)
+{
+    for (; (first1 != last1) & (first2 != last2); ++first1) {
+	if (comp (*first2, *first1))
+	    return (false);
+	first2 += !comp (*first1, *first2);
+    }
+    return (first2 == last2);
+}
+
+/// \brief Merges [first1,last1) with [first2,last2)
+///
+/// Result will contain every element that is in either set. If duplicate
+/// elements are present, max(n,m) is placed in the result.
+///
+/// \ingroup SetAlgorithms
+/// \ingroup PredicateAlgorithms
+template <typename InputIterator1, typename InputIterator2, typename OutputIterator, typename StrictWeakOrdering>
+OutputIterator set_union (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result, StrictWeakOrdering comp)
+{
+    for (; (first1 != last1) & (first2 != last2); ++result) {
+	if (comp (*first2, *first1))
+	    *result = *first2++;
+	else {
+	    first2 += !comp (*first1, *first2);
+	    *result = *first1++;
+	}
+    }
+    return (copy (first2, last2, copy (first1, last1, result)));
+}
+
+/// \brief Creates a set containing elements shared by the given ranges.
+/// \ingroup SetAlgorithms
+/// \ingroup PredicateAlgorithms
+template <typename InputIterator1, typename InputIterator2, typename OutputIterator, typename StrictWeakOrdering>
+OutputIterator set_intersection (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result, StrictWeakOrdering comp)
+{
+    while ((first1 != last1) & (first2 != last2)) {
+	bool b1ge2 = !comp (*first1, *first2), b2ge1 = !comp (*first2, *first1);
+	if (b1ge2 & b2ge1)
+	    *result++ = *first1;
+	first1 += b2ge1;
+	first2 += b1ge2;
+    }
+    return (result);
+}
+
+/// \brief Removes from [first1,last1) elements present in [first2,last2)
+/// \ingroup SetAlgorithms
+/// \ingroup PredicateAlgorithms
+template <typename InputIterator1, typename InputIterator2, typename OutputIterator, typename StrictWeakOrdering>
+OutputIterator set_difference (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result, StrictWeakOrdering comp)
+{
+    while ((first1 != last1) & (first2 != last2)) {
+	bool b1ge2 = !comp (*first1, *first2), b2ge1 = !comp (*first2, *first1);
+	if (!b1ge2)
+	    *result++ = *first1;
+	first1 += b2ge1;
+	first2 += b1ge2;
+    }
+    return (copy (first1, last1, result));
+}
+
+/// \brief Performs union of sets A-B and B-A.
+/// \ingroup SetAlgorithms
+/// \ingroup PredicateAlgorithms
+template <typename InputIterator1, typename InputIterator2, typename OutputIterator, typename StrictWeakOrdering>
+OutputIterator set_symmetric_difference (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result, StrictWeakOrdering comp)
+{
+    while ((first1 != last1) & (first2 != last2)) {
+	bool b1l2 = comp (*first1, *first2), b2l1 = comp (*first2, *first1);
+	if (b1l2)
+	    *result++ = *first1;
+	else if (b2l1)
+	    *result++ = *first2;
+	first1 += !b2l1;
+	first2 += !b1l2;
+    }
+    return (copy (first2, last2, copy (first1, last1, result)));
+}
+
+/// \brief Returns true if the given range is sorted.
+/// \ingroup ConditionAlgorithms
+/// \ingroup PredicateAlgorithms
+template <typename ForwardIterator, typename StrictWeakOrdering>
+bool is_sorted (ForwardIterator first, ForwardIterator last, StrictWeakOrdering comp)
+{
+    for (ForwardIterator i = first; ++i < last; ++first)
+	if (comp (*i, *first))
+	    return (false);
+    return (true);
+}
+
+/// \brief Compares two given containers like strcmp compares strings.
+/// \ingroup ConditionAlgorithms
+/// \ingroup PredicateAlgorithms
+template <typename InputIterator1, typename InputIterator2, typename BinaryPredicate>
+bool lexicographical_compare (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, BinaryPredicate comp)
+{
+    for (; (first1 != last1) & (first2 != last2); ++first1, ++first2) {
+	if (comp (*first1, *first2))
+	    return (true);
+	if (comp (*first2, *first1))
+	    return (false);
+    }
+    return ((first1 == last1) & (first2 != last2));
+}
+
+/// \brief Creates the next lexicographical permutation of [first,last).
+/// Returns false if no further permutations can be created.
+/// \ingroup GeneratorAlgorithms
+/// \ingroup PredicateAlgorithms
+template <typename BidirectionalIterator, typename StrictWeakOrdering>
+bool next_permutation (BidirectionalIterator first, BidirectionalIterator last, StrictWeakOrdering comp)
+{
+    if (distance (first, last) < 2)
+	return (false);
+    BidirectionalIterator i = last;
+    for (--i; i != first; ) {
+	--i;
+	if (comp (i[0], i[1])) {
+	    BidirectionalIterator j = last;
+	    while (!comp (*i, *--j));
+	    iter_swap (i, j);
+	    reverse (i + 1, last);
+	    return (true);
+	}
+    }
+    reverse (first, last);
+    return (false);
+}
+
+/// \brief Creates the previous lexicographical permutation of [first,last).
+/// Returns false if no further permutations can be created.
+/// \ingroup GeneratorAlgorithms
+/// \ingroup PredicateAlgorithms
+template <typename BidirectionalIterator, typename StrictWeakOrdering>
+bool prev_permutation (BidirectionalIterator first, BidirectionalIterator last, StrictWeakOrdering comp)
+{
+    if (distance (first, last) < 2)
+	return (false);
+    BidirectionalIterator i = last;
+    for (--i; i != first; ) {
+	--i;
+	if (comp(i[1], i[0])) {
+	    BidirectionalIterator j = last;
+	    while (!comp (*--j, *i));
+	    iter_swap (i, j);
+	    reverse (i + 1, last);
+	    return (true);
+	}
+    }
+    reverse (first, last);
+    return (false);
+}
+
+/// \brief Returns iterator to the max element in [first,last)
+/// \ingroup SearchingAlgorithms
+/// \ingroup PredicateAlgorithms
+template <typename ForwardIterator, typename BinaryPredicate>
+inline ForwardIterator max_element (ForwardIterator first, ForwardIterator last, BinaryPredicate comp)
+{
+    ForwardIterator result = first;
+    for (; first != last; ++first)
+	if (comp (*result, *first))
+	    result = first;
+    return (result);
+}
+
+/// \brief Returns iterator to the min element in [first,last)
+/// \ingroup SearchingAlgorithms
+/// \ingroup PredicateAlgorithms
+template <typename ForwardIterator, typename BinaryPredicate>
+inline ForwardIterator min_element (ForwardIterator first, ForwardIterator last, BinaryPredicate comp)
+{
+    ForwardIterator result = first;
+    for (; first != last; ++first)
+	if (comp (*first, *result))
+	    result = first;
+    return (result);
+}
+
+/// \brief Makes [first,middle) a part of the sorted array.
+/// Contents of [middle,last) is undefined. This implementation just calls stable_sort.
+/// \ingroup SortingAlgorithms
+/// \ingroup PredicateAlgorithms
+template <typename RandomAccessIterator, typename StrictWeakOrdering>
+inline void partial_sort (RandomAccessIterator first, RandomAccessIterator, RandomAccessIterator last, StrictWeakOrdering comp)
+{
+    stable_sort (first, last, comp);
+}
+
+/// \brief Like partial_sort, but outputs to [result_first,result_last)
+/// \ingroup SortingAlgorithms
+/// \ingroup PredicateAlgorithms
+template <typename InputIterator, typename RandomAccessIterator, typename StrictWeakOrdering>
+RandomAccessIterator partial_sort_copy (InputIterator first, InputIterator last, RandomAccessIterator result_first, RandomAccessIterator result_last, StrictWeakOrdering comp)
+{
+    RandomAccessIterator rend = result_first;
+    for (; first != last; ++first) {
+	RandomAccessIterator i = result_first;
+	for (; i != rend && comp (*i, *first); ++i);
+	if (i == result_last)
+	    continue;
+	rend += (rend < result_last);
+	copy_backward (i, rend - 1, rend);
+	*i = *first;
+    }
+    return (rend);
+}
+
+/// \brief Like \ref partition, but preserves equal element order.
+/// \ingroup SortingAlgorithms
+/// \ingroup PredicateAlgorithms
+template <typename ForwardIterator, typename Predicate>
+ForwardIterator stable_partition (ForwardIterator first, ForwardIterator last, Predicate pred)
+{
+    if (first == last)
+	return (first);
+    ForwardIterator l, r, m = advance (first, distance (first, last) / 2);
+    if (first == m)
+	return (pred(*first) ? last : first);
+    l = stable_partition (first, m, pred);
+    r = stable_partition (m, last, pred);
+    rotate (l, m, r);
+    return (advance (l, distance (m, r)));
+}
+
+/// \brief Splits [first,last) in two by \p pred.
+///
+/// Creates two ranges [first,middle) and [middle,last), where every element
+/// in the former is less than every element in the latter.
+/// The return value is middle.
+///
+/// \ingroup SortingAlgorithms
+/// \ingroup PredicateAlgorithms
+template <typename ForwardIterator, typename Predicate>
+inline ForwardIterator partition (ForwardIterator first, ForwardIterator last, Predicate pred)
+{
+    return (stable_partition (first, last, pred));
+}
+
+} // namespace ustl
+
+#endif
+
diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/uqueue.h b/media/libdrm/mobile2/src/util/ustl-1.0/uqueue.h
new file mode 100644
index 0000000..99eef80
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/ustl-1.0/uqueue.h
@@ -0,0 +1,71 @@
+// This file is part of the ustl library, an STL implementation.
+//
+// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
+// This file is free software, distributed under the MIT License.
+//
+// uqueue.h
+//
+
+#ifndef UQUEUE_H_27F01FDB0D59B75277E0E5C41ABC6B5B
+#define UQUEUE_H_27F01FDB0D59B75277E0E5C41ABC6B5B
+
+namespace ustl {
+
+/// \class queue uqueue.h ustl.h
+/// \ingroup Sequences
+///
+/// \brief Queue adapter to uSTL containers.
+///
+/// The most efficient way to use this implementation is to fill the queue
+/// and the completely empty it before filling again.
+///
+template <typename Sequence>
+class queue {
+public:
+    typedef typename Sequence::value_type	value_type;
+    typedef typename Sequence::size_type	size_type;
+    typedef typename Sequence::difference_type	difference_type;
+    typedef typename Sequence::reference	reference;
+    typedef typename Sequence::const_reference	const_reference;
+    typedef typename Sequence::pointer		pointer;
+public:
+    inline			queue (void)			: m_Storage (), m_Front (0) { }
+    explicit inline		queue (const Sequence& s)	: m_Storage (s), m_Front (0) { }
+    inline size_type		size (void) const		{ return (m_Storage.size() - m_Front); }
+    inline bool			empty (void) const		{ return (!size()); }
+    inline reference		front (void)			{ return (m_Storage [m_Front]); }
+    inline const_reference	front (void) const		{ return (m_Storage [m_Front]); }
+    inline reference		back (void)			{ return (m_Storage.back()); }
+    inline const_reference	back (void) const		{ return (m_Storage.back()); }
+    inline void			push (const value_type& v);
+    inline void			pop (void);
+    inline bool			operator== (const queue& s)	{ return (m_Storage == s.m_Storage && m_Front == s.m_Front); }
+    inline bool			operator< (const queue& s)	{ return (size() < s.size()); }
+private:
+    Sequence			m_Storage;	///< Where the data actually is.
+    size_type			m_Front;	///< Index of the element returned by next pop.
+};
+
+/// Pushes \p v on the queue.
+template <class Sequence>
+inline void queue<Sequence>::push (const value_type& v)
+{
+    if (m_Front) {
+	m_Storage.erase (m_Storage.begin(), m_Front);
+	m_Front = 0;
+    }
+    m_Storage.push_back (v);
+}
+
+/// Pops the topmost element from the queue.
+template <class Sequence>
+inline void queue<Sequence>::pop (void)
+{
+    if (++m_Front >= m_Storage.size())
+	m_Storage.resize (m_Front = 0);
+}
+
+} // namespace ustl
+
+#endif
+
diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/uset.h b/media/libdrm/mobile2/src/util/ustl-1.0/uset.h
new file mode 100644
index 0000000..958d4b0
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/ustl-1.0/uset.h
@@ -0,0 +1,97 @@
+// This file is part of the ustl library, an STL implementation.
+//
+// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
+// This file is free software, distributed under the MIT License.
+//
+// uset.h
+//
+
+#ifndef USET_H_45543F516E02A87A3FCEA5024052A6F5
+#define USET_H_45543F516E02A87A3FCEA5024052A6F5
+
+#include "uassert.h"
+#include "uvector.h"
+
+namespace ustl {
+
+/// \class set uset.h ustl.h
+/// \ingroup Sequences
+///
+/// \brief Unique sorted container. Sorted vector with all values unique.
+///
+template <typename T>
+class set : public vector<T> {
+public:
+    typedef const set<T>&			rcself_t;
+    typedef vector<T>				base_class;
+    typedef typename base_class::value_type		key_type;
+    typedef typename base_class::value_type		data_type;
+    typedef typename base_class::value_type		value_type;
+    typedef typename base_class::size_type		size_type;
+    typedef typename base_class::pointer			pointer;
+    typedef typename base_class::const_pointer		const_pointer;
+    typedef typename base_class::reference		reference;
+    typedef typename base_class::const_reference		const_reference;
+    typedef typename base_class::const_iterator		const_iterator;
+    typedef typename base_class::iterator		iterator;
+    typedef typename base_class::reverse_iterator	reverse_iterator;
+    typedef typename base_class::const_reverse_iterator	const_reverse_iterator;
+public:
+    inline			set (void)		: vector<T> () { }
+    explicit inline		set (size_type n)	: vector<T> (n) { }
+    inline			set (rcself_t v)	: vector<T> (v) { } 
+    inline			set (const_iterator i1, const_iterator i2) : vector<T> () { insert (i1, i2); }
+    inline rcself_t		operator= (rcself_t v)	{ base_class::operator= (v); return (*this); }
+    inline size_type		size (void) const	{ return (base_class::size()); }
+    inline iterator		begin (void)		{ return (base_class::begin()); }
+    inline const_iterator	begin (void) const	{ return (base_class::begin()); }
+    inline iterator		end (void)		{ return (base_class::end()); }
+    inline const_iterator	end (void) const	{ return (base_class::end()); }
+    inline void			assign (const_iterator i1, const_iterator i2)	{ clear(); insert (i1, i2); }
+    inline void			push_back (const_reference v)	{ insert (v); }
+    inline const_iterator	find (const_reference v) const	{ return (binary_search (begin(), end(), v)); }
+    inline iterator		find (const_reference v)	{ return (const_cast<iterator>(const_cast<rcself_t>(*this).find (v))); }
+    iterator			insert (const_reference v);
+    inline void			insert (const_iterator i1, const_iterator i2);
+    inline void			erase (const_reference v);
+    inline iterator		erase (iterator ep)	{ return (base_class::erase (ep)); }
+    inline iterator		erase (iterator ep1, iterator ep2) { return (base_class::erase (ep1, ep2)); }
+    inline void			clear (void)		{ base_class::clear(); }
+};
+
+/// Inserts \p v into the container, maintaining the sort order.
+template <typename T>
+typename set<T>::iterator set<T>::insert (const_reference v)
+{
+    iterator ip = lower_bound (begin(), end(), v);
+    if (ip == end() || v < *ip)
+	ip = base_class::insert (ip, v);
+    else
+	*ip = v;
+    return (ip);
+}
+
+/// Inserts the contents of range [i1,i2)
+template <typename T>
+void set<T>::insert (const_iterator i1, const_iterator i2)
+{
+    assert (i1 <= i2);
+    reserve (size() + distance (i1, i2));
+    for (; i1 < i2; ++i1)
+	push_back (*i1);
+}
+
+/// Erases the element with value \p v.
+template <typename T>
+inline void set<T>::erase (const_reference v)
+{
+    iterator ip = find (v);
+    if (ip != end())
+	erase (ip);
+}
+
+
+} // namespace ustl
+
+#endif
+
diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/uspecial.h b/media/libdrm/mobile2/src/util/ustl-1.0/uspecial.h
new file mode 100644
index 0000000..0b87a54
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/ustl-1.0/uspecial.h
@@ -0,0 +1,267 @@
+// This file is part of the ustl library, an STL implementation.
+//
+// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
+// This file is free software, distributed under the MIT License.
+//
+// uspecial.h
+//
+// Template specializations for uSTL classes.
+//
+
+#ifndef USPECIAL_H_947ADYOU0ARE3YOU2REALLY8ARE44CE0
+#define USPECIAL_H_947ADYOU0ARE3YOU2REALLY8ARE44CE0
+
+#include "uassert.h"
+#include "uvector.h"
+#include "ustring.h"
+#include "uset.h"
+#include "umultiset.h"
+#include "ubitset.h"
+#include "ulaalgo.h"
+#include "uctralgo.h"
+#include "ufunction.h"
+#include "uctrstrm.h"
+#include "sistream.h"
+#include <ctype.h>
+
+namespace ustl {
+
+//----------------------------------------------------------------------
+// Alogrithm specializations not in use by the library code.
+//----------------------------------------------------------------------
+
+template <> inline void swap (cmemlink& a, cmemlink& b)			{ a.swap (b); }
+template <> inline void swap (memlink& a, memlink& b)			{ a.swap (b); }
+template <> inline void swap (memblock& a, memblock& b)			{ a.swap (b); }
+template <> inline void swap (string& a, string& b)			{ a.swap (b); }
+#define TEMPLATE_SWAP_PSPEC(type, template_decl)	\
+template_decl inline void swap (type& a, type& b) { a.swap (b); }
+TEMPLATE_SWAP_PSPEC (TEMPLATE_TYPE1 (vector,T),		TEMPLATE_DECL1 (T))
+TEMPLATE_SWAP_PSPEC (TEMPLATE_TYPE1 (set,T),		TEMPLATE_DECL1 (T))
+TEMPLATE_SWAP_PSPEC (TEMPLATE_TYPE1 (multiset,T),	TEMPLATE_DECL1 (T))
+TEMPLATE_SWAP_PSPEC (TEMPLATE_TYPE2 (tuple,N,T),	TEMPLATE_FULL_DECL2 (size_t,N,typename,T))
+
+//----------------------------------------------------------------------
+// Streamable definitions. Not used in the library and require streams.
+//----------------------------------------------------------------------
+
+//----{ pair }----------------------------------------------------------
+
+/// \brief Reads pair \p p from stream \p is.
+template <typename T1, typename T2>
+istream& operator>> (istream& is, pair<T1,T2>& p)
+{
+    is >> p.first;
+    is.align (alignof(T2()));
+    is >> p.second;
+    is.align (alignof(T1()));
+    return (is);
+}
+
+/// Writes pair \p p to stream \p os.
+template <typename T1, typename T2>
+ostream& operator<< (ostream& os, const pair<T1,T2>& p)
+{
+    os << p.first;
+    os.align (alignof(T2()));
+    os << p.second;
+    os.align (alignof(T1()));
+    return (os);
+}
+
+/// Writes pair \p p to stream \p os.
+template <typename T1, typename T2>
+ostringstream& operator<< (ostringstream& os, const pair<T1,T2>& p)
+{
+    os << '(' << p.first << ',' << p.second << ')';
+    return (os);
+}
+
+/// Returns the written size of the object.
+template <typename T1, typename T2>
+inline size_t stream_size_of (const pair<T1,T2>& v)
+{
+    return (Align (stream_size_of(v.first), alignof(T2())) +
+	    Align (stream_size_of(v.second), alignof(T1())));
+}
+
+/// \brief Takes a pair and returns pair.first
+/// This is an extension, available in uSTL and the SGI STL.
+template <typename Pair> struct select1st : public unary_function<Pair,typename Pair::first_type> {
+    typedef typename Pair::first_type result_type;
+    inline const result_type&	operator()(const Pair& a) const { return (a.first); }
+    inline result_type&		operator()(Pair& a) const { return (a.first); }
+};
+
+/// \brief Takes a pair and returns pair.second
+/// This is an extension, available in uSTL and the SGI STL.
+template <typename Pair> struct select2nd : public unary_function<Pair,typename Pair::second_type> {
+    typedef typename Pair::second_type result_type;
+    inline const result_type&	operator()(const Pair& a) const { return (a.second); }
+    inline result_type&		operator()(Pair& a) const { return (a.second); }
+};
+
+/// \brief Converts a const_iterator pair into an iterator pair
+/// Useful for converting pair ranges returned by equal_range, for instance.
+/// This is an extension, available in uSTL.
+template <typename Container>
+inline pair<typename Container::iterator, typename Container::iterator>
+unconst (const pair<typename Container::const_iterator, typename Container::const_iterator>& i, Container& ctr)
+{
+    assert (i.first >= ctr.begin() && i.first <= ctr.end() && "unconst algorithm must be given iterators from the argument container");
+    pair<typename Container::iterator, typename Container::iterator> result;
+    result.first = ctr.begin() + (i.first - ctr.begin());
+    result.second = ctr.begin() + (i.second - ctr.begin());
+    return (result);
+}
+
+//----{ vector }--------------------------------------------------------
+
+STD_TEMPLATE_CTR_STREAMABLE (TEMPLATE_TYPE1 (vector,T), TEMPLATE_DECL1 (T))
+
+template <typename T>
+inline size_t alignof (const vector<T>&)
+{
+    typedef typename vector<T>::written_size_type written_size_type;
+    return (alignof (written_size_type()));
+}
+
+//----{ bitset }--------------------------------------------------------
+
+/// Reads bitset \p v from stream \p is.
+template <size_t Size>
+inline istream& operator>> (istream& is, bitset<Size>& v)
+{
+    return (nr_container_read (is, v));
+}
+
+/// Writes bitset \p v into stream \p os.
+template <size_t Size>
+inline ostream& operator<< (ostream& os, const bitset<Size>& v)
+{
+    return (nr_container_write (os, v));
+}
+
+/// Writes bitset \p v into stream \p os.
+template <size_t Size>
+inline ostringstream& operator<< (ostringstream& os, const bitset<Size>& v)
+{
+    return (os << v.to_string());
+}
+
+/// Writes bitset \p v into stream \p os.
+template <size_t Size>
+istringstream& operator>> (istringstream& is, bitset<Size>& v)
+{
+    char c;
+    for (int i = Size; --i >= 0 && (is >> c).good();)
+	v.set (i, c == '1');
+    return (is);
+}
+
+/// Returns the number of bytes necessary to write this object to a stream
+template <size_t Size>
+inline size_t stream_size_of (const bitset<Size>& v)
+{
+    return (v.capacity() / CHAR_BIT);
+}
+
+//----{ tuple }---------------------------------------------------------
+
+STD_TEMPLATE_NR_CTR_STREAMABLE (
+    TEMPLATE_TYPE2 (tuple,N,T),
+    TEMPLATE_FULL_DECL2 (size_t,N,typename,T)
+)
+
+template <size_t N, typename T>
+struct numeric_limits<tuple<N,T> > {
+    typedef numeric_limits<T> value_limits;
+    static inline tuple<N,T> min (void)	{ tuple<N,T> v; fill (v, value_limits::min()); return (v); }
+    static inline tuple<N,T> max (void)	{ tuple<N,T> v; fill (v, value_limits::max()); return (v); }
+    static const bool is_signed = value_limits::is_signed;
+    static const bool is_integer = value_limits::is_integer;
+    static const bool is_integral = value_limits::is_integral;
+};
+
+template <size_t N, typename T>
+inline size_t alignof (const tuple<N,T>&) { return (alignof (T())); }
+
+template <typename T, typename IntT>
+inline ostringstream& chartype_text_write (ostringstream& os, const T& v)
+{
+    if (isprint(v))
+	os << '\'' << v << '\'';
+    else
+	os << (IntT)(v);
+    return (os);
+}
+
+template <>
+inline ostringstream& container_element_text_write (ostringstream& os, const uint8_t& v)
+{ return (chartype_text_write<uint8_t, unsigned int> (os, v)); }
+template <>
+inline ostringstream& container_element_text_write (ostringstream& os, const int8_t& v)
+{ return (chartype_text_write<int8_t, int> (os, v)); }
+
+//----{ matrix }--------------------------------------------------------
+
+/// Writes tuple \p v into stream \p os.
+template <size_t NX, size_t NY, typename T>
+ostringstream& operator<< (ostringstream& os, const matrix<NX,NY,T>& v)
+{
+    os << '(';
+    for (uoff_t row = 0; row < NY; ++ row) {
+	os << '(';
+        for (uoff_t column = 0; column < NX; ++ column) {
+	    os << v[row][column];
+	    if (column < NX - 1)
+		os << ',';
+	}
+	os << ')';
+    }
+    os << ')';
+    return (os);
+}
+
+//----------------------------------------------------------------------
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+#ifndef WITHOUT_LIBSTDCPP
+
+/// \todo Need a better solution to getting the hash value.
+inline hashvalue_t hash_value (const string::const_pointer& v)
+{
+    string::const_pointer first (v), last (v + strlen(v));
+    hashvalue_t h = 0;
+    // This has the bits flowing into each other from both sides of the number
+    for (; first < last; ++ first)
+	h = *first + ((h << 7) | (h >> BitsInType(hashvalue_t) - 7));
+    return (h);
+}
+
+#endif
+#endif
+
+//----------------------------------------------------------------------
+
+} // namespace ustl
+
+// This is here because there really is no other place to put it.
+#if SIZE_OF_BOOL != SIZE_OF_CHAR
+// bool is a big type on some machines (like DEC Alpha), so it's written as a byte.
+ALIGNOF(bool, sizeof(uint8_t))
+#endif
+STD_STREAMABLE(cmemlink)
+STD_STREAMABLE(istream)
+STD_STREAMABLE(ostream)
+STD_STREAMABLE(string)
+STD_STREAMABLE(exception)
+STD_STREAMABLE(CBacktrace)
+TEXT_STREAMABLE(cmemlink)
+TEXT_STREAMABLE(istream)
+TEXT_STREAMABLE(ostream)
+TEXT_STREAMABLE(exception)
+TEXT_STREAMABLE(CBacktrace)
+
+#endif
+
diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/ustack.h b/media/libdrm/mobile2/src/util/ustl-1.0/ustack.h
new file mode 100644
index 0000000..c48e3b3
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/ustl-1.0/ustack.h
@@ -0,0 +1,46 @@
+// This file is part of the ustl library, an STL implementation.
+//
+// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
+// This file is free software, distributed under the MIT License.
+//
+// ustack.h
+//
+
+#ifndef USTACK_H_5242F5635322B2EC44A9AEE73022C6E9
+#define USTACK_H_5242F5635322B2EC44A9AEE73022C6E9
+
+namespace ustl {
+
+/// \class stack ustack.h ustl.h
+/// \ingroup Sequences
+///
+/// \brief Stack adapter to uSTL containers.
+///
+template <typename Sequence>
+class stack {
+public:
+    typedef typename Sequence::value_type	value_type;
+    typedef typename Sequence::size_type	size_type;
+    typedef typename Sequence::difference_type	difference_type;
+    typedef typename Sequence::reference	reference;
+    typedef typename Sequence::const_reference	const_reference;
+    typedef typename Sequence::pointer		pointer;
+public:
+    inline			stack (void)			: m_Storage () { }
+    explicit inline		stack (const Sequence& s)	: m_Storage (s) { }
+    inline bool			empty (void) const		{ return (m_Storage.empty()); }
+    inline size_type		size (void) const		{ return (m_Storage.size()); }
+    inline reference		top (void)			{ return (m_Storage.back()); }
+    inline const_reference	top (void) const		{ return (m_Storage.back()); }
+    inline void			push (const value_type& v)	{ m_Storage.push_back (v); }
+    inline void			pop (void)			{ m_Storage.pop_back(); }
+    inline bool			operator== (const stack& s)	{ return (m_Storage == s.m_Storage); }
+    inline bool			operator< (const stack& s)	{ return (m_Storage.size() < s.m_Storage.size()); }
+private:
+    Sequence			m_Storage;	///< Where the data actually is.
+};
+
+} // namespace ustl
+
+#endif
+
diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/ustdxept.cpp b/media/libdrm/mobile2/src/util/ustl-1.0/ustdxept.cpp
new file mode 100644
index 0000000..ce731f7
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/ustl-1.0/ustdxept.cpp
@@ -0,0 +1,72 @@
+// This file is part of the ustl library, an STL implementation.
+//
+// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
+// This file is free software, distributed under the MIT License.
+//
+// ustdxept.cc
+//
+
+#include "ustdxept.h"
+#include "mistream.h"
+#include "mostream.h"
+#include "strmsize.h"
+#include "uiosfunc.h"
+#include "uspecial.h"
+
+namespace ustl {
+
+//----------------------------------------------------------------------
+
+/// \p arg contains a description of the error.
+error_message::error_message (const char* arg) throw()
+: m_Arg ()
+{
+#if PLATFORM_ANDROID
+    m_Arg = arg;
+#else /* !PLATFORM_ANDROID */
+    try { m_Arg = arg; } catch (...) {}
+#endif
+    set_format (xfmt_ErrorMessage);
+}
+
+/// Virtual destructor
+error_message::~error_message (void) throw()
+{
+}
+
+/// Returns a descriptive error message. fmt="%s: %s"
+void error_message::info (string& msgbuf, const char* fmt) const throw()
+{
+    if (!fmt) fmt = "%s: %s";
+#if PLATFORM_ANDROID
+    msgbuf.format (fmt, what(), m_Arg.cdata());
+#else /* !PLATFORM_ANDROID */
+    try { msgbuf.format (fmt, what(), m_Arg.cdata()); } catch (...) {}
+#endif
+}
+
+/// Reads the object from stream \p is.
+void error_message::read (istream& is)
+{
+    exception::read (is);
+    is >> m_Arg >> ios::align();
+}
+
+/// Writes the object to stream \p os.
+void error_message::write (ostream& os) const
+{
+    exception::write (os);
+    os << m_Arg << ios::align();
+}
+
+/// Returns the size of the written object.
+size_t error_message::stream_size (void) const
+{
+    return (exception::stream_size() + Align (stream_size_of (m_Arg)));
+}
+
+//----------------------------------------------------------------------
+
+} // namespace ustl
+
+
diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/ustdxept.h b/media/libdrm/mobile2/src/util/ustl-1.0/ustdxept.h
new file mode 100644
index 0000000..4f50953
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/ustl-1.0/ustdxept.h
@@ -0,0 +1,143 @@
+// This file is part of the ustl library, an STL implementation.
+//
+// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
+// This file is free software, distributed under the MIT License.
+//
+// ustdxept.h
+//
+
+#ifndef USTDXEPT_H_46F7AE967738B588038F95E41158D7FF
+#define USTDXEPT_H_46F7AE967738B588038F95E41158D7FF
+
+#include "uexception.h"
+#include "ustring.h"
+
+namespace ustl {
+
+enum { 
+    xfmt_ErrorMessage = 2,
+    xfmt_LogicError = xfmt_ErrorMessage,
+    xfmt_RuntimeError = xfmt_ErrorMessage
+};
+
+/// \class logic_error ustdxept.h ustl.h
+/// \ingroup Exceptions
+///
+/// \brief Logic errors represent problems in the internal logic of the program.
+///
+class error_message : public exception {
+public:
+    explicit		error_message (const char* arg) throw();
+    virtual	       ~error_message (void) throw();
+    inline virtual const char*	what (void) const throw() { return ("error"); }
+    virtual void	info (string& msgbuf, const char* fmt = NULL) const throw();
+    virtual void	read (istream& is);
+    virtual void	write (ostream& os) const;
+    virtual size_t	stream_size (void) const;
+protected:
+    string		m_Arg;
+};
+
+/// \class logic_error ustdxept.h ustl.h
+/// \ingroup Exceptions
+///
+/// \brief Logic errors represent problems in the internal logic of the program.
+///
+class logic_error : public error_message {
+public:
+    inline explicit		logic_error (const char* arg) throw() : error_message (arg) {}
+    inline virtual const char*	what (void) const throw() { return ("logic error"); }
+};
+
+/// \class domain_error ustdxept.h ustl.h
+/// \ingroup Exceptions
+///
+/// \brief Reports domain errors ("domain" is in the mathematical sense)
+///
+class domain_error : public logic_error {
+public:
+    inline explicit		domain_error (const char* arg) throw() : logic_error (arg) {}
+    inline virtual const char*	what (void) const throw() { return ("domain error"); }
+};
+
+/// \class invalid_argument ustdxept.h ustl.h
+/// \ingroup Exceptions
+///
+/// \brief Reports an invalid argument to a function.
+///
+class invalid_argument : public logic_error {
+public:
+    inline explicit		invalid_argument (const char* arg) throw() : logic_error (arg) {}
+    inline virtual const char*	what (void) const throw() { return ("invalid argument"); }
+};
+
+/// \class length_error ustdxept.h ustl.h
+/// \ingroup Exceptions
+///
+/// \brief Reports when an object exceeds its allowed size.
+///
+class length_error : public logic_error {
+public:
+    inline explicit		length_error (const char* arg) throw() : logic_error (arg) {} 
+    inline virtual const char*	what (void) const throw() { return ("length error"); }
+};
+
+/// \class out_of_range ustdxept.h ustl.h
+/// \ingroup Exceptions
+///
+/// \brief Reports arguments with values out of allowed range.
+///
+class out_of_range : public logic_error {
+public:
+    inline explicit		out_of_range (const char* arg) throw() : logic_error (arg) {}
+    inline virtual const char*	what (void) const throw() { return ("out of range"); }
+};
+
+/// \class runtime_error ustdxept.h ustl.h
+/// \ingroup Exceptions
+///
+/// \brief Reports errors that are dependent on the data being processed.
+///
+class runtime_error : public error_message {
+public:
+    inline explicit		runtime_error (const char* arg) throw() : error_message (arg) {}
+    inline virtual const char*	what (void) const throw() { return ("runtime error"); }
+};
+
+/// \class range_error ustdxept.h ustl.h
+/// \ingroup Exceptions
+///
+/// \brief Reports data that does not fall within the permitted range.
+///
+class range_error : public runtime_error {
+public:
+    inline explicit		range_error (const char* arg) throw() : runtime_error (arg) {}
+    inline virtual const char*	what (void) const throw() { return ("range error"); }
+};
+
+/// \class overflow_error ustdxept.h ustl.h
+/// \ingroup Exceptions
+///
+/// \brief Reports arithmetic overflow.
+///
+class overflow_error : public runtime_error {
+public:
+    inline explicit		overflow_error (const char* arg) throw() : runtime_error (arg) {}
+    inline virtual const char*	what (void) const throw() { return ("overflow error"); }
+};
+
+/// \class underflow_error ustdxept.h ustl.h
+/// \ingroup Exceptions
+///
+/// \brief Reports arithmetic underflow.
+///
+class underflow_error : public runtime_error {
+public:
+    inline explicit		underflow_error (const char* arg) throw() : runtime_error (arg) {}
+    inline virtual const char*	what (void) const throw() { return ("underflow error"); }
+};
+
+} // namespace ustl
+
+#endif
+
diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/ustl.tbff b/media/libdrm/mobile2/src/util/ustl-1.0/ustl.tbff
new file mode 100644
index 0000000..b8ad374
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/ustl-1.0/ustl.tbff
@@ -0,0 +1,84 @@
+<!-- ANSI Standard fixed size types -->
+<type name=int8_t format=signedIntegral size=int8_t/>
+<type name=int16_t format=signedIntegral size=int16_t/>
+<type name=int32_t format=signedIntegral size=int32_t/>
+<type name=int64_t format=signedIntegral size=int64_t/>
+<type name=uint8_t format=integral size=int8_t/>
+<type name=uint16_t format=integral size=int16_t/>
+<type name=uint32_t format=integral size=int32_t/>
+<type name=uint64_t format=integral size=int64_t/>
+<type name=float format=float size=float/>
+<type name=double format=float size=double/>
+
+<!-- Standard types of variable size, these are machine specific -->
+<type name=int_least8_t format=signedIntegral size=int8_t/>
+<type name=int_least16_t format=signedIntegral size=int16_t/>
+<type name=int_least32_t format=signedIntegral size=int32_t/>
+<type name=int_least64_t format=signedIntegral size=int64_t/>
+<type name=uint_least8_t format=integral size=int8_t/>
+<type name=uint_least16_t format=integral size=int16_t/>
+<type name=uint_least32_t format=integral size=int32_t/>
+<type name=uint_least64_t format=integral size=int64_t/>
+<type name=int_fast8_t format=signedIntegral size=int8_t/>
+<type name=int_fast16_t format=signedIntegral size=int16_t/>
+<type name=int_fast32_t format=signedIntegral size=int32_t/>
+<type name=int_fast64_t format=signedIntegral size=int64_t/>
+<type name=uint_fast8_t format=integral size=int8_t/>
+<type name=uint_fast16_t format=integral size=int16_t/>
+<type name=uint_fast32_t format=integral size=int32_t/>
+<type name=uint_fast64_t format=integral size=int64_t/>
+<type name=intptr_t format=integral size=intptr_t/>
+<type name=uintptr_t format=integral size=intptr_t/>
+<type name=intmax_t format=integral size=intmax_t/>
+<type name=uintmax_t format=integral size=intmax_t/>
+
+<!-- Standard C++ variable size types, also machine specific -->
+<type name=wchar_t format=signedIntegral size=wchar_t/>
+<type name=size_t format=integral size=size_t/>
+<type name=char format=signedIntegral size=char/>
+<type name=short format=signedIntegral size=short/>
+<type name=int format=signedIntegral size=int/>
+<type name=long format=signedIntegral size=long/>
+<type name=longlong format=signedIntegral size=longlong/>
+<type name=u_char format=signedIntegral size=char/>
+<type name=u_short format=signedIntegral size=short/>
+<type name=u_int format=signedIntegral size=int/>
+<type name=u_long format=signedIntegral size=long/>
+<type name=u_longlong format=signedIntegral size=longlong/>
+
+<!-- libc types -->
+<type name=time_t format=signedIntegral size=time_t/>
+<type name=off_t format=signedIntegral size=off_t/>
+<type name=ptrdiff_t format=signedIntegral size=ptrdiff_t/>
+<type name=dev_t format=integral size=dev_t/>
+<type name=uid_t format=integral size=uid_t/>
+<type name=gid_t format=integral size=gid_t/>
+<type name=mode_t format=integral size=mode_t/>
+<type name=nlink_t format=integral size=nlink_t/>
+<type name=pid_t format=integral size=pid_t/>
+<type name=fsid_t format=integral size=fsid_t/>
+<type name=clock_t format=integral size=clock_t/>
+<type name=id_t format=integral size=id_t/>
+<type name=key_t format=integral size=key_t/>
+<type name=blksize_t format=integral size=blksize_t/>
+
+<!-- Types within the ustl library -->
+<type name=utf8 format=integral minSize="1" maxSize="8"/>
+<type name=auto format=unstructured id="AUTO"/>
+<namespace name=ustl>
+    <type name=uoff_t extends=size_t/>
+    <type name=cmemlink_ptr_t format=pointer/>
+    <type name=memlink_ptr_t extends=cmemlink_ptr_t/>
+    <type name=memblock_ptr_t extends=memlink_ptr_t/>
+    <type name=cmemlink format=struct>
+	<var name=data_size type=size_t />
+	<var name=data format=unstructured size=data_size />
+    </type>
+    <type name=memlink extends=cmemlink />
+    <type name=memblock extends=cmemlink />
+    <type name=string extends=memblock>
+	<var name=data_size type=utf8 />
+	<var name=data format=array type=utf8 size=data_size />
+    </type>
+</namespace>
+
diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/ustring.cpp b/media/libdrm/mobile2/src/util/ustl-1.0/ustring.cpp
new file mode 100644
index 0000000..db87d34
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/ustl-1.0/ustring.cpp
@@ -0,0 +1,425 @@
+// This file is part of the ustl library, an STL implementation.
+//
+// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
+// This file is free software, distributed under the MIT License.
+//
+// ustring.cpp
+//
+//	STL basic_string equivalent functionality.
+//
+
+#include "uassert.h"
+#include "ustring.h"
+#include "mistream.h"
+#include "mostream.h"
+#include "ualgo.h"
+#include <stdio.h>	// for vsnprintf (in string::format)
+
+#include "uassert.h"
+
+namespace ustl {
+
+//----------------------------------------------------------------------
+
+const uoff_t string::npos;
+const string::size_type string::size_Terminator;
+const string::value_type string::c_Terminator;
+const char string::empty_string[string::size_Terminator] = "";
+
+typedef utf8in_iterator<string::const_iterator> utf8icstring_iterator;
+typedef utf8in_iterator<string::iterator> utf8istring_iterator;
+typedef utf8out_iterator<string::iterator> utf8ostring_iterator;
+
+//----------------------------------------------------------------------
+
+/// Creates an empty string.
+string::string (void)
+: memblock ()
+{
+    link (empty_string, 0U);
+}
+
+/// Assigns itself the value of string \p s
+string::string (const string& s)
+: memblock()
+{
+    if (s.is_linked())
+	link (s.c_str(), s.size());
+    else
+	assign (s);
+}
+
+/// Links to \p s
+string::string (const_pointer s)
+: memblock ()
+{
+    if (!s)
+	s = empty_string;
+    link (s, strlen(s));
+}
+
+/// Creates a string of length \p n filled with character \p c.
+string::string (size_type n, value_type c)
+: memblock ()
+{
+    resize (n);
+    fill_n (begin(), n, c);
+}
+
+/// Resize the string to \p n characters. New space contents is undefined.
+void string::resize (size_type n)
+{
+    memblock::resize (n);
+    at(n) = c_Terminator;
+}
+
+/// Assigns itself the value of string \p s
+void string::assign (const_pointer s)
+{
+    if (!s)
+	s = empty_string;
+    assign (s, strlen (s));
+}
+
+/// Assigns itself the value of string \p s of length \p len.
+void string::assign (const_pointer s, size_type len)
+{
+    while (len && s[len - 1] == c_Terminator)
+	-- len;
+    resize (len);
+    copy (s, len);
+}
+
+/// Appends to itself the value of string \p s of length \p len.
+void string::append (const_pointer s)
+{
+    if (!s)
+	s = empty_string;
+    append (s, strlen (s));
+}
+
+/// Appends to itself the value of string \p s of length \p len.
+void string::append (const_pointer s, size_type len)
+{
+    while (len && s[len - 1] == c_Terminator)
+	-- len;
+    resize (size() + len);
+    copy_n (s, len, end() - len);
+}
+
+/// Appends to itself \p n characters of value \p c.
+void string::append (size_type n, value_type c)
+{
+    resize (size() + n);
+    fill_n (end() - n, n, c);
+}
+
+/// Copies into itself at offset \p start, the value of string \p p of length \p n.
+string::size_type string::copyto (pointer p, size_type n, const_iterator start) const
+{
+    assert (p && n);
+    if (!start)
+	start = begin();
+    const size_type btc = min(n - size_Terminator, size());
+    copy_n (start, btc, p);
+    p[btc] = c_Terminator;
+    return (btc + size_Terminator);
+}
+
+/// Returns comparison value regarding string \p s.
+/// The return value is:
+/// \li 1 if this string is greater (by value, not length) than string \p s
+/// \li 0 if this string is equal to string \p s
+/// \li -1 if this string is less than string \p s
+///
+/*static*/ int string::compare (const_iterator first1, const_iterator last1, const_iterator first2, const_iterator last2)
+{
+    assert (first1 <= last1 && (first2 <= last2 || !last2) && "Negative ranges result in memory allocation errors.");
+    const size_type len1 = distance (first1, last1), len2 = distance (first2, last2);
+    const int rvbylen = sign (int(len1 - len2));
+    int rv = memcmp (first1, first2, min (len1, len2));
+    return (rv ? rv : rvbylen);
+}
+
+/// Returns true if this string is equal to string \p s.
+bool string::operator== (const_pointer s) const
+{
+    if (!s)
+	s = empty_string;
+    return (size() == strlen(s) && 0 == memcmp (c_str(), s, size()));
+}
+
+/// Returns the beginning of character \p i.
+string::iterator string::utf8_iat (uoff_t i)
+{
+    utf8istring_iterator cfinder (begin());
+    cfinder += i;
+    return (cfinder.base());
+}
+
+/// Inserts wide character \p c at \p ip \p n times as a UTF-8 string.
+///
+/// \p ip is a character position, not a byte position, and must fall in
+/// the 0 through length() range.
+/// The first argument is not an iterator because it is rather difficult
+/// to get one. You'd have to use ((utf8begin() + n).base()) as the first
+/// argument, which is rather ugly. Besides, then this insert would be
+/// ambiguous with the regular character insert.
+///
+void string::insert (const uoff_t ip, wchar_t c, size_type n)
+{
+    iterator ipp (utf8_iat (ip));
+    ipp = iterator (memblock::insert (memblock::iterator(ipp), n * Utf8Bytes(c)));
+    fill_n (utf8out (ipp), n, c);
+    *end() = c_Terminator;
+}
+
+/// Inserts sequence of wide characters at \p ip.
+void string::insert (const uoff_t ip, const wchar_t* first, const wchar_t* last, const size_type n)
+{
+    iterator ipp (utf8_iat (ip));
+    size_type nti = distance (first, last), bti = 0;
+    for (uoff_t i = 0; i < nti; ++ i)
+	bti += Utf8Bytes(first[i]);
+    ipp = iterator (memblock::insert (memblock::iterator(ipp), n * bti));
+    utf8ostring_iterator uout (utf8out (ipp));
+    for (uoff_t j = 0; j < n; ++ j)
+	for (uoff_t k = 0; k < nti; ++ k, ++ uout)
+	    *uout = first[k];
+    *end() = c_Terminator;
+}
+
+/// Inserts character \p c into this string at \p start.
+string::iterator string::insert (iterator start, const_reference c, size_type n)
+{
+    start = iterator (memblock::insert (memblock::iterator(start), n));
+    fill_n (start, n, c);
+    *end() = c_Terminator;
+    return (start);
+}
+
+/// Inserts \p count instances of string \p s at offset \p start.
+string::iterator string::insert (iterator start, const_pointer s, size_type n)
+{
+    if (!s)
+	s = empty_string;
+    return (insert (start, s, s + strlen(s), n));
+}
+
+/// Inserts [first,last] \p n times.
+string::iterator string::insert (iterator start, const_pointer first, const_pointer last, size_type n)
+{
+    assert (first <= last);
+    assert (begin() <= start && end() >= start);
+    assert ((first < begin() || first >= end() || size() + abs_distance(first,last) < capacity()) && "Insertion of self with autoresize is not supported");
+    start = iterator (memblock::insert (memblock::iterator(start), distance(first, last) * n));
+    fill (memblock::iterator(start), first, distance(first, last), n);
+    *end() = c_Terminator;
+    return (start);
+}
+
+/// Erases \p size bytes at \p start.
+string::iterator string::erase (iterator ep, size_type n)
+{
+    string::iterator rv = memblock::erase (memblock::iterator(ep), n);
+    *end() = c_Terminator;
+    return (rv);
+}
+
+/// Erases \p size characters at \p start.
+/// \p start is a character position, not a byte position, and must be
+/// in the 0..length() range.
+///
+void string::erase (uoff_t ep, size_type n)
+{
+    iterator first (utf8_iat(ep));
+    size_t nbytes (utf8_iat(ep + n) - first);
+    memblock::erase (first, nbytes);
+    *end() = c_Terminator;
+}
+
+/// Replaces range [\p start, \p start + \p len] with string \p s.
+void string::replace (iterator first, iterator last, const_pointer s)
+{
+    if (!s)
+	s = empty_string;
+    replace (first, last, s, s + strlen(s));
+}
+
+/// Replaces range [\p start, \p start + \p len] with \p count instances of string \p s.
+void string::replace (iterator first, iterator last, const_pointer i1, const_pointer i2, size_type n)
+{
+    assert (first <= last);
+    assert (n || distance(first, last));
+    assert (first >= begin() && first <= end() && last >= first && last <= end());
+    assert ((i1 < begin() || i1 >= end() || abs_distance(i1,i2) * n + size() < capacity()) && "Replacement by self can not autoresize");
+    const size_type bte = distance(first, last), bti = distance(i1, i2) * n;
+    if (bti < bte)
+	first = iterator (memblock::erase (memblock::iterator(first), bte - bti));
+    else if (bte < bti)
+	first = iterator (memblock::insert (memblock::iterator(first), bti - bte));
+    fill (memblock::iterator(first), i1, distance(i1, i2), n);
+    *end() = c_Terminator;
+}
+
+/// Returns the offset of the first occurence of \p c after \p pos.
+uoff_t string::find (const_reference c, uoff_t pos) const
+{
+    const_iterator found = ::ustl::find (iat(pos), end(), c);
+    return (found < end() ? distance(begin(),found) : npos);
+}
+
+/// Returns the offset of the first occurence of substring \p s of length \p n after \p pos.
+uoff_t string::find (const string& s, uoff_t pos) const
+{
+    if (s.empty() || s.size() > size() - pos)
+	return (npos);
+    const uoff_t endi = s.size() - 1;
+    const_reference endchar = s[endi];
+    uoff_t lastPos = endi;
+    while (lastPos-- && s[lastPos] != endchar);
+    const size_type skip = endi - lastPos;
+    const_iterator i = iat(pos) + endi;
+    for (; i < end() && (i = ::ustl::find (i, end(), endchar)) < end(); i += skip)
+	if (memcmp (i - endi, s.c_str(), s.size()) == 0)
+	    return (distance (begin(), i) - endi);
+    return (npos);
+}
+
+/// Returns the offset of the last occurence of character \p c before \p pos.
+uoff_t string::rfind (const_reference c, uoff_t pos) const
+{
+    for (int i = min(pos,size()-1); i >= 0; --i)
+	if (at(i) == c)
+	    return (i);
+    return (npos);
+}
+
+/// Returns the offset of the last occurence of substring \p s of size \p n before \p pos.
+uoff_t string::rfind (const string& s, uoff_t pos) const
+{
+    const_iterator d = iat(pos) - 1;
+    const_iterator sp = begin() + s.size() - 1;
+    const_iterator m = s.end() - 1;
+    for (uoff_t i = 0; d > sp && i < s.size(); -- d)
+	for (i = 0; i < s.size(); ++ i)
+	    if (m[-i] != d[-i])
+		break;
+    return (d > sp ? distance (begin(), d + 2 - s.size()) : npos);
+}
+
+/// Returns the offset of the first occurence of one of characters in \p s of size \p n after \p pos.
+uoff_t string::find_first_of (const string& s, uoff_t pos) const
+{
+    for (uoff_t i = min(pos,size()); i < size(); ++ i)
+	if (s.find (at(i)) != npos)
+	    return (i);
+    return (npos);
+}
+
+/// Returns the offset of the first occurence of one of characters not in \p s of size \p n after \p pos.
+uoff_t string::find_first_not_of (const string& s, uoff_t pos) const
+{
+    for (uoff_t i = min(pos,size()); i < size(); ++ i)
+	if (s.find (at(i)) == npos)
+	    return (i);
+    return (npos);
+}
+
+/// Returns the offset of the last occurence of one of characters in \p s of size \p n before \p pos.
+uoff_t string::find_last_of (const string& s, uoff_t pos) const
+{
+    for (int i = min(pos,size()-1); i >= 0; -- i)
+	if (s.find (at(i)) != npos)
+	    return (i);
+    return (npos);
+}
+
+/// Returns the offset of the last occurence of one of characters not in \p s of size \p n before \p pos.
+uoff_t string::find_last_not_of (const string& s, uoff_t pos) const
+{
+    for (int i = min(pos,size()-1); i >= 0; -- i)
+	if (s.find (at(i)) == npos)
+	    return (i);
+    return (npos);
+}
+
+/// Equivalent to a vsprintf on the string.
+int string::vformat (const char* fmt, va_list args)
+{
+#if HAVE_VA_COPY
+    va_list args2;
+#else
+    #define args2 args
+    #undef __va_copy
+    #define __va_copy(x,y)
+#endif
+    size_t rv = size();
+    do {
+	reserve (rv);
+	__va_copy (args2, args);
+	rv = vsnprintf (data(), memblock::capacity(), fmt, args2);
+	rv = min (rv, memblock::capacity());
+    } while (rv > capacity());
+    resize (min (rv, capacity()));
+    return (rv);
+}
+
+/// Equivalent to a sprintf on the string.
+int string::format (const char* fmt, ...)
+{
+    va_list args;
+    va_start (args, fmt);
+    const int rv = vformat (fmt, args);
+    va_end (args);
+    return (rv);
+}
+
+/// Returns the number of bytes required to write this object to a stream.
+size_t string::stream_size (void) const
+{
+    return (Utf8Bytes(size()) + size());
+}
+
+/// Reads the object from stream \p os
+void string::read (istream& is)
+{
+    char szbuf [8];
+    is >> szbuf[0];
+    size_t szsz (Utf8SequenceBytes (szbuf[0]) - 1), n = 0;
+    is.verify_remaining ("read", "ustl::string", szsz);
+    is.read (szbuf + 1, szsz);
+    n = *utf8in(szbuf);
+    is.verify_remaining ("read", "ustl::string", n);
+    resize (n);
+    is.read (data(), size());
+}
+
+/// Writes the object to stream \p os
+void string::write (ostream& os) const
+{
+    const written_size_type sz (size());
+    assert (sz == size() && "No support for writing strings larger than 4G");
+
+    char szbuf [8];
+    utf8out_iterator<char*> szout (szbuf);
+    *szout = sz;
+    size_t szsz = distance (szbuf, szout.base());
+
+    os.verify_remaining ("write", "ustl::string", szsz + sz);
+    os.write (szbuf, szsz);
+    os.write (cdata(), sz);
+}
+
+/// Returns a hash value for [first, last)
+/*static*/ hashvalue_t string::hash (const char* first, const char* last)
+{
+    hashvalue_t h = 0;
+    // This has the bits flowing into each other from both sides of the number
+    for (; first < last; ++ first)
+	h = *first + ((h << 7) | (h >> BitsInType(hashvalue_t) - 7));
+    return (h);
+}
+
+} // namespace ustl
+
diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/ustring.h b/media/libdrm/mobile2/src/util/ustl-1.0/ustring.h
new file mode 100644
index 0000000..9ecf6e7
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/ustl-1.0/ustring.h
@@ -0,0 +1,263 @@
+// This file is part of the ustl library, an STL implementation.
+//
+// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
+// This file is free software, distributed under the MIT License.
+//
+// ustring.h
+//
+
+#ifndef USTRING_H_1249CB7A098A9010763AAC6D37B133CF
+#define USTRING_H_1249CB7A098A9010763AAC6D37B133CF
+
+#include "memblock.h"
+#include "utf8.h"
+#include <stdarg.h>	// for va_list, va_start, and va_end (in string::format)
+
+namespace ustl {
+
+/// \class string ustring.h ustl.h
+/// \ingroup Sequences
+///
+/// \brief STL basic_string&lt;char&gt; equivalent.
+///
+/// An STL container for text string manipulation.
+/// Differences from C++ standard:
+///	- string is a class, not a template. Wide characters are assumed to be
+///		encoded with utf8 at all times except when rendering or editing,
+///		where you would use a utf8 iterator.
+/// 	- format member function - you can, of course use an \ref ostringstream,
+///		which also have format functions, but most of the time this way
+///		is more convenient. Because uSTL does not implement locales,
+///		format is the only way to create localized strings.
+/// 	- const char* cast operator. It is much clearer to use this than having
+/// 		to type .c_str() every time.
+/// 	- length returns the number of _characters_, not bytes.
+///		This function is O(N), so use wisely.
+///
+class string : public memblock {
+public:
+    typedef char		value_type;
+    typedef value_type*		pointer;
+    typedef const value_type*	const_pointer;
+    typedef wchar_t		wvalue_type;
+    typedef wvalue_type*	wpointer;
+    typedef const wvalue_type*	const_wpointer;
+    typedef pointer		iterator;
+    typedef const_pointer	const_iterator;
+    typedef value_type&		reference;
+    typedef value_type		const_reference;
+    typedef ::ustl::reverse_iterator<iterator>		reverse_iterator;
+    typedef ::ustl::reverse_iterator<const_iterator>	const_reverse_iterator;
+    typedef utf8in_iterator<const_iterator>		utf8_iterator;
+public:
+    static const uoff_t npos = static_cast<uoff_t>(-1);			///< Value that means the end of string.
+    static const value_type c_Terminator = 0;				///< String terminator
+    static const size_type size_Terminator = sizeof(c_Terminator);	///< Most systems terminate strings with '\\0'
+    static const char empty_string [size_Terminator];			///< An empty string.
+public:
+				string (void);
+				string (const string& s);
+    inline			string (const string& s, uoff_t o, size_type n);
+    inline explicit		string (const cmemlink& l);
+				string (const_pointer s);
+    inline			string (const_pointer s, size_type len);
+    inline			string (const_pointer s1, const_pointer s2);
+    explicit			string (size_type n, value_type c = c_Terminator);
+    inline pointer		data (void)		{ return (string::pointer (memblock::data())); }
+    inline const_pointer	c_str (void) const	{ return (string::const_pointer (memblock::cdata())); }
+    inline size_type		max_size (void) const	{ size_type s (memblock::max_size()); return (s - !!s); }
+    inline size_type		capacity (void) const	{ size_type c (memblock::capacity()); return (c - !!c); }
+    void			resize (size_type n);
+    inline void			clear (void)		{ resize (0); }
+    inline const_iterator	begin (void) const	{ return (const_iterator (memblock::begin())); }
+    inline iterator		begin (void)		{ return (iterator (memblock::begin())); }
+    inline const_iterator	end (void) const	{ return (const_iterator (memblock::end())); }
+    inline iterator		end (void)		{ return (iterator (memblock::end())); }
+  inline const_reverse_iterator	rbegin (void) const	{ return (const_reverse_iterator (end())); }
+    inline reverse_iterator	rbegin (void)		{ return (reverse_iterator (end())); }
+  inline const_reverse_iterator	rend (void) const	{ return (const_reverse_iterator (begin())); }
+    inline reverse_iterator	rend (void)		{ return (reverse_iterator (begin())); }
+    inline utf8_iterator	utf8_begin (void) const	{ return (utf8_iterator (begin())); }
+    inline utf8_iterator	utf8_end (void) const	{ return (utf8_iterator (end())); }
+    inline const_reference	at (uoff_t pos) const	{ assert (pos <= size() && begin()); return (begin()[pos]); }
+    inline reference		at (uoff_t pos)		{ assert (pos <= size() && begin()); return (begin()[pos]); }
+    inline const_iterator	iat (uoff_t pos) const	{ return (begin() + min (pos, size())); }
+    inline iterator		iat (uoff_t pos)	{ return (begin() + min (pos, size())); }
+    inline size_type		length (void) const	{ return (distance (utf8_begin(), utf8_end())); }
+    inline void			append (const_iterator i1, const_iterator i2)	{ append (i1, distance (i1, i2)); }
+    void	   		append (const_pointer s, size_type len);
+    void	   		append (const_pointer s);
+    void			append (size_type n, const_reference c);
+    inline void			append (size_type n, wvalue_type c)		{ insert (size(), c, n); }
+    inline void			append (const_wpointer s1, const_wpointer s2)	{ insert (size(), s1, s2); }
+    inline void			append (const_wpointer s)			{ const_wpointer se (s); for (;se&&*se;++se); append (s, se); }
+    inline void			append (const string& s)			{ append (s.begin(), s.end()); }
+    inline void			append (const string& s, uoff_t o, size_type n)	{ append (s.iat(o), s.iat(o+n)); }
+    inline void			assign (const_iterator i1, const_iterator i2)	{ assign (i1, distance (i1, i2)); }
+    void	    		assign (const_pointer s, size_type len);
+    void	    		assign (const_pointer s);
+    inline void			assign (const_wpointer s1, const_wpointer s2)	{ clear(); append (s1, s2); }
+    inline void			assign (const_wpointer s1)			{ clear(); append (s1); }
+    inline void			assign (const string& s)			{ assign (s.begin(), s.end()); }
+    inline void			assign (const string& s, uoff_t o, size_type n)	{ assign (s.iat(o), s.iat(o+n)); }
+    size_type			copyto (pointer p, size_type n, const_iterator start = NULL) const;
+    inline int			compare (const string& s) const	{ return (compare (begin(), end(), s.begin(), s.end())); }
+    inline int			compare (const_pointer s) const	{ return (compare (begin(), end(), s, s + strlen(s))); }
+    static int			compare (const_iterator first1, const_iterator last1, const_iterator first2, const_iterator last2);
+    inline			operator const value_type* (void) const;
+    inline			operator value_type* (void);
+    inline const string&	operator= (const string& s)	{ assign (s.begin(), s.end()); return (*this); }
+    inline const string&	operator= (const_reference c)	{ assign (&c, 1); return (*this); }
+    inline const string&	operator= (const_pointer s)	{ assign (s); return (*this); }
+    inline const string&	operator= (const_wpointer s)	{ assign (s); return (*this); }
+    inline const string&	operator+= (const string& s)	{ append (s.begin(), s.size()); return (*this); }
+    inline const string&	operator+= (const_reference c)	{ append (1, c); return (*this); }
+    inline const string&	operator+= (const_pointer s)	{ append (s); return (*this); }
+    inline const string&	operator+= (wvalue_type c)	{ append (1, c); return (*this); }
+    inline const string&	operator+= (const_wpointer s)	{ append (s); return (*this); }
+    inline string		operator+ (const string& s) const;
+    inline bool			operator== (const string& s) const	{ return (memblock::operator== (s)); }
+    bool			operator== (const_pointer s) const;
+    inline bool			operator== (const_reference c) const	{ return (size() == 1 && c == at(0)); }
+    inline bool			operator!= (const string& s) const	{ return (!operator== (s)); }
+    inline bool			operator!= (const_pointer s) const	{ return (!operator== (s)); }
+    inline bool			operator!= (const_reference c) const	{ return (!operator== (c)); }
+    inline bool			operator< (const string& s) const	{ return (0 > compare (s)); }
+    inline bool			operator< (const_pointer s) const	{ return (0 > compare (s)); }
+    inline bool			operator< (const_reference c) const	{ return (0 > compare (begin(), end(), &c, &c + 1)); }
+    inline bool			operator> (const_pointer s) const	{ return (0 < compare (s)); }
+    void			insert (const uoff_t ip, wvalue_type c, size_type n = 1);
+    void			insert (const uoff_t ip, const_wpointer first, const_wpointer last, const size_type n = 1);
+    iterator			insert (iterator start, const_reference c, size_type n = 1);
+    iterator			insert (iterator start, const_pointer s, size_type n = 1);
+    iterator			insert (iterator start, const_pointer first, const_iterator last, size_type n = 1);
+    inline void			insert (uoff_t ip, const_pointer s, size_type nlen)		{ insert (iat(ip), s, s + nlen); }
+    inline void			insert (uoff_t ip, size_type n, value_type c)			{ insert (iat(ip), c, n); }
+    inline void			insert (uoff_t ip, const string& s, uoff_t sp, size_type slen)	{ insert (iat(ip), s.iat(sp), s.iat(sp + slen)); }
+    iterator			erase (iterator start, size_type size = 1);
+    void			erase (uoff_t start, size_type size = 1);
+    inline iterator		erase (iterator first, const_iterator last)	{ return (erase (first, size_type(distance(first,last)))); }
+				OVERLOAD_POINTER_AND_SIZE_T_V2(erase, iterator)
+    inline void			push_back (const_reference c)	{ append (1, c); }
+    inline void			push_back (wvalue_type c)	{ append (1, c); }
+    inline void			pop_back (void)			{ resize (size() - 1); }
+    void			replace (iterator first, iterator last, const_pointer s);
+    void			replace (iterator first, iterator last, const_pointer i1, const_pointer i2, size_type n = 1);
+    inline void			replace (iterator first, iterator last, const string& s)			{ replace (first, last, s.begin(), s.end()); }
+    inline void			replace (iterator first, iterator last, const_pointer s, size_type slen)	{ replace (first, last, s, s + slen); }
+    inline void			replace (iterator first, iterator last, size_type n, value_type c)		{ replace (first, last, &c, &c + 1, n); }
+    inline void			replace (uoff_t rp, size_type n, const string& s)				{ replace (iat(rp), iat(rp + n), s); }
+    inline void			replace (uoff_t rp, size_type n, const string& s, uoff_t sp, size_type slen)	{ replace (iat(rp), iat(rp + n), s.iat(sp), s.iat(sp + slen)); }
+    inline void			replace (uoff_t rp, size_type n, const_pointer s, size_type slen)		{ replace (iat(rp), iat(rp + n), s, s + slen); }
+    inline void			replace (uoff_t rp, size_type n, const_pointer s)				{ replace (iat(rp), iat(rp + n), string(s)); }
+    inline void			replace (uoff_t rp, size_type n, size_type count, value_type c)			{ replace (iat(rp), iat(rp + n), count, c); }
+    inline string		substr (uoff_t o, size_type n) const	{ return (string (*this, o, n)); }
+    uoff_t			find (const_reference c, uoff_t pos = 0) const;
+    uoff_t			find (const string& s, uoff_t pos = 0) const;
+    uoff_t			rfind (const_reference c, uoff_t pos = npos) const;
+    uoff_t			rfind (const string& s, uoff_t pos = npos) const;
+    uoff_t			find_first_of (const string& s, uoff_t pos = 0) const;
+    uoff_t			find_first_not_of (const string& s, uoff_t pos = 0) const;
+    uoff_t			find_last_of (const string& s, uoff_t pos = npos) const;
+    uoff_t			find_last_not_of (const string& s, uoff_t pos = npos) const;
+    int				vformat (const char* fmt, va_list args);
+    int				format (const char* fmt, ...) __attribute__((__format__(__printf__, 2, 3)));
+    void			read (istream&);
+    void			write (ostream& os) const;
+    size_t			stream_size (void) const;
+    static hashvalue_t		hash (const char* f1, const char* l1);
+private:
+    DLL_LOCAL iterator		utf8_iat (uoff_t i);
+protected:
+    inline virtual size_type	minimumFreeCapacity (void) const { return (size_Terminator); }
+};
+
+//----------------------------------------------------------------------
+
+/// Assigns itself the value of string \p s
+inline string::string (const cmemlink& s)
+: memblock ()
+{
+    assign (const_iterator (s.begin()), s.size());
+}
+
+/// Assigns itself a [o,o+n) substring of \p s.
+inline string::string (const string& s, uoff_t o, size_type n)
+: memblock()
+{
+    assign (s, o, n);
+}
+
+/// Copies the value of \p s of length \p len into itself.
+inline string::string (const_pointer s, size_type len)
+: memblock ()
+{
+    assign (s, len);
+}
+
+/// Copies into itself the string data between \p s1 and \p s2
+inline string::string (const_pointer s1, const_pointer s2)
+: memblock ()
+{
+    assert (s1 <= s2 && "Negative ranges result in memory allocation errors.");
+    assign (s1, s2);
+}
+
+/// Returns the pointer to the first character.
+inline string::operator const string::value_type* (void) const
+{
+    assert ((!end() || *end() == c_Terminator) && "This string is linked to data that is not 0-terminated. This may cause serious security problems. Please assign the data instead of linking.");
+    return (begin());
+}
+
+/// Returns the pointer to the first character.
+inline string::operator string::value_type* (void)
+{
+    assert ((end() && *end() == c_Terminator) && "This string is linked to data that is not 0-terminated. This may cause serious security problems. Please assign the data instead of linking.");
+    return (begin());
+}
+
+/// Concatenates itself with \p s
+inline string string::operator+ (const string& s) const
+{
+    string result (*this);
+    result += s;
+    return (result);
+}
+
+//----------------------------------------------------------------------
+// Operators needed to avoid comparing pointer to pointer
+
+#define PTR_STRING_CMP(op, impl)	\
+inline bool op (const char* s1, const string& s2) { return impl; }
+PTR_STRING_CMP (operator==, (s2 == s1))
+PTR_STRING_CMP (operator!=, (s2 != s1))
+PTR_STRING_CMP (operator<,  (s2 >  s1))
+PTR_STRING_CMP (operator<=, (s2 >= s1))
+PTR_STRING_CMP (operator>,  (s2 <  s1))
+PTR_STRING_CMP (operator>=, (s2 <= s1))
+#undef PTR_STRING_CMP
+
+//----------------------------------------------------------------------
+
+template <typename T>
+inline hashvalue_t hash_value (const T& v)
+{ return (string::hash (v.begin(), v.end())); }
+
+template <>
+inline hashvalue_t hash_value (const string::const_pointer& v)
+{ return (string::hash (v, v + strlen(v))); }
+
+template <>
+inline hashvalue_t hash_value (const string::pointer& v)
+{ return (string::hash (v, v + strlen(v))); }
+
+//----------------------------------------------------------------------
+
+} // namespace ustl
+
+// Specialization for stream alignment
+ALIGNOF (ustl::string, alignof (string::value_type()))
+
+#endif
+
diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/utf8.h b/media/libdrm/mobile2/src/util/ustl-1.0/utf8.h
new file mode 100644
index 0000000..f829e7d
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/ustl-1.0/utf8.h
@@ -0,0 +1,200 @@
+// This file is part of the ustl library, an STL implementation.
+//
+// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
+// This file is free software, distributed under the MIT License.
+//
+// utf8.h
+//
+// This file contains stream iterators that read and write UTF-8 encoded
+// characters. The encoding is defined as follows:
+//
+// U-00000000 - U-0000007F: 0xxxxxxx
+// U-00000080 - U-000007FF: 110xxxxx 10xxxxxx
+// U-00000800 - U-0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx
+// U-00010000 - U-001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+// U-00200000 - U-03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
+// U-04000000 - U-7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
+// U-80000000 - U-FFFFFFFF: 11111110 100000xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
+//
+// The last range in not in the UTF-8 standard because Unicode forbids
+// characters of those values. However, since ustl::string uses this code
+// to write its length, the support is here. The reason it was put here
+// in the first place, is that extra code would have been necessary to
+// flag that range as invalid.
+//
+#ifndef UTF8_H_3D7AEEEB3A88928D4D280B785F78B6F4
+#define UTF8_H_3D7AEEEB3A88928D4D280B785F78B6F4
+
+#include "uiterator.h"
+
+namespace ustl {
+
+//----------------------------------------------------------------------
+
+typedef uint8_t utf8subchar_t;	///< Type for the encoding subcharacters.
+
+//----------------------------------------------------------------------
+
+/// Returns the number of bytes required to UTF-8 encode \p v.
+inline size_t Utf8Bytes (wchar_t v)
+{
+    static const uint32_t c_Bounds[] = { 0x0000007F, 0x000007FF, 0x0000FFFF, 0x001FFFFF, 0x03FFFFFF, 0x7FFFFFFF, 0xFFFFFFFF, };
+    size_t bi = 0;
+    while (c_Bounds[bi++] < uint32_t(v));
+    return (bi);
+}
+
+/// Returns the number of bytes in a UTF-8 sequence that starts with \p c.
+inline size_t Utf8SequenceBytes (wchar_t c)	// a wchar_t to keep c in a full register
+{
+    // Count the leading bits. Header bits are 1 * nBytes followed by a 0.
+    //	0 - single byte character. Take 7 bits (0xFF >> 1)
+    //	1 - error, in the middle of the character. Take 6 bits (0xFF >> 2)
+    //	    so you will keep reading invalid entries until you hit the next character.
+    //	>2 - multibyte character. Take remaining bits, and get the next bytes.
+    // All errors are ignored, since the user can not correct them.
+    //
+    wchar_t mask = 0x80;
+    size_t nBytes = 0;
+    for (; c & mask; ++nBytes)
+	mask >>= 1;
+    return (nBytes ? nBytes : 1); // A sequence is always at least 1 byte.
+}
+
+//----------------------------------------------------------------------
+
+/// \class utf8in_iterator utf8.h ustl.h
+/// \ingroup IteratorAdaptors
+///
+/// \brief An iterator adaptor to character containers for reading UTF-8 encoded text.
+///
+/// For example, you can copy from ustl::string to ustl::vector<wchar_t> with
+/// copy (utf8in (str.begin()), utf8in (str.end()), back_inserter(wvect));
+/// There is no error handling; if the reading frame slips you'll get extra
+/// characters, one for every misaligned byte. Although it is possible to skip
+/// to the start of the next character, that would result in omitting the
+/// misformatted character and the one after it, making it very difficult to
+/// detect by the user. It is better to write some strange characters and let
+/// the user know his file is corrupted. Another problem is overflow on bad
+/// encodings (like a 0xFF on the end of a string). This is checked through
+/// the end-of-string nul character, which will always be there as long as
+/// you are using the string class.
+///
+template <typename Iterator, typename WChar = wchar_t>
+class utf8in_iterator {
+public:
+    typedef typename iterator_traits<Iterator>::value_type	value_type;
+    typedef typename iterator_traits<Iterator>::difference_type	difference_type;
+    typedef typename iterator_traits<Iterator>::pointer		pointer;
+    typedef typename iterator_traits<Iterator>::reference	reference;
+public:
+    explicit			utf8in_iterator (const Iterator& is)		: m_i (is), m_v (0) { Read(); }
+				utf8in_iterator (const utf8in_iterator& i)	: m_i (i.m_i), m_v (i.m_v) {} 
+    inline const utf8in_iterator& operator= (const utf8in_iterator& i)		{ m_i = i.m_i; m_v = i.m_v; return (*this); }
+    inline Iterator		base (void) const	{ return (m_i - (Utf8Bytes(m_v) - 1)); }
+    /// Reads and returns the next value.
+    inline WChar		operator* (void) const	{ return (m_v); }
+    inline utf8in_iterator&	operator++ (void)	{ ++m_i; Read(); return (*this); }
+    inline utf8in_iterator	operator++ (int)	{ utf8in_iterator old (*this); operator++(); return (old); }
+    inline utf8in_iterator&	operator+= (uoff_t n)	{ while (n--) operator++(); return (*this); }
+    inline utf8in_iterator	operator+ (uoff_t n)	{ utf8in_iterator v (*this); return (v += n); }
+    inline bool			operator== (const utf8in_iterator& i) const	{ return (m_i == i.m_i); }
+    inline bool			operator< (const utf8in_iterator& i) const	{ return (m_i < i.m_i); }
+    difference_type		operator- (const utf8in_iterator& i) const;
+private:
+    void			Read (void);
+private:
+    Iterator			m_i;
+    WChar			m_v;
+};
+
+/// Steps to the next character and updates current returnable value.
+template <typename Iterator, typename WChar>
+void utf8in_iterator<Iterator,WChar>::Read (void)
+{
+    const utf8subchar_t c = *m_i;
+    size_t nBytes = Utf8SequenceBytes (c);
+    m_v = c & (0xFF >> nBytes);	// First byte contains bits after the header.
+    while (--nBytes && *++m_i)	// Each subsequent byte has 6 bits.
+	m_v = (m_v << 6) | (*m_i & 0x3F);
+}
+
+/// Returns the distance in characters (as opposed to the distance in bytes).
+template <typename Iterator, typename WChar>
+typename utf8in_iterator<Iterator,WChar>::difference_type
+utf8in_iterator<Iterator,WChar>::operator- (const utf8in_iterator<Iterator,WChar>& last) const
+{
+    difference_type dist = 0;
+    for (Iterator first (last.m_i); first < m_i; ++dist)
+	first = advance (first, Utf8SequenceBytes (*first));
+    return (dist);
+}
+
+//----------------------------------------------------------------------
+
+/// \class utf8out_iterator utf8.h ustl.h
+/// \ingroup IteratorAdaptors
+///
+/// \brief An iterator adaptor to character containers for writing UTF-8 encoded text.
+///
+template <typename Iterator, typename WChar = wchar_t>
+class utf8out_iterator {
+public:
+    typedef typename iterator_traits<Iterator>::value_type	value_type;
+    typedef typename iterator_traits<Iterator>::difference_type	difference_type;
+    typedef typename iterator_traits<Iterator>::pointer		pointer;
+    typedef typename iterator_traits<Iterator>::reference	reference;
+public:
+    explicit			utf8out_iterator (const Iterator& os) : m_i (os) {}
+				utf8out_iterator (const utf8out_iterator& i) : m_i (i.m_i) {} 
+    inline const Iterator&	base (void) const { return (m_i); }
+    /// Writes \p v into the stream.
+    utf8out_iterator&		operator= (WChar v);
+    inline utf8out_iterator&	operator* (void) { return (*this); }
+    inline utf8out_iterator&	operator++ (void) { return (*this); }
+    inline utf8out_iterator	operator++ (int) { return (*this); }
+    inline bool			operator== (const utf8out_iterator& i) const { return (m_i == i.m_i); }
+    inline bool			operator< (const utf8out_iterator& i) const { return (m_i < i.m_i); }
+private:
+    Iterator			m_i;
+};
+
+/// Writes \p v into the stream.
+template <typename Iterator, typename WChar>
+utf8out_iterator<Iterator,WChar>& utf8out_iterator<Iterator,WChar>::operator= (WChar v)
+{
+    const size_t nBytes = Utf8Bytes (v);
+    if (nBytes > 1) {
+	// Write the bits 6 bits at a time, except for the first one,
+	// which may be less than 6 bits.
+	register wchar_t shift = nBytes * 6;
+	*m_i++ = ((v >> (shift -= 6)) & 0x3F) | (0xFF << (8 - nBytes));
+	while (shift)
+	    *m_i++ = ((v >> (shift -= 6)) & 0x3F) | 0x80;
+    } else	// If only one byte, there is no header.
+    	*m_i++ = v;
+    return (*this);
+}
+
+//----------------------------------------------------------------------
+
+/// Returns a UTF-8 adaptor writing to \p i. Useful in conjuction with back_insert_iterator.
+template <typename Iterator>
+inline utf8out_iterator<Iterator> utf8out (Iterator i)
+{
+    return (utf8out_iterator<Iterator> (i));
+}
+
+/// Returns a UTF-8 adaptor reading from \p i.
+template <typename Iterator>
+inline utf8in_iterator<Iterator> utf8in (Iterator i)
+{
+    return (utf8in_iterator<Iterator> (i));
+}
+
+//----------------------------------------------------------------------
+
+} // namespace ustl
+
+#endif
+
diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/utuple.h b/media/libdrm/mobile2/src/util/ustl-1.0/utuple.h
new file mode 100644
index 0000000..8a003ab
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/ustl-1.0/utuple.h
@@ -0,0 +1,247 @@
+// This file is part of the ustl library, an STL implementation.
+//
+// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
+// This file is free software, distributed under the MIT License.
+//
+// utuple.h
+//
+
+#ifndef UTUPLE_H_7324ADEC49B397CA74A56F6050FD5A6B
+#define UTUPLE_H_7324ADEC49B397CA74A56F6050FD5A6B
+
+#include "ualgo.h"
+
+#if PLATFORM_ANDROID
+#undef CPU_HAS_MMX
+#endif
+
+namespace ustl {
+
+/// \class tuple utuple.h ustl.h
+/// \ingroup Sequences
+///
+/// \brief A fixed-size array of \p N \p Ts.
+///
+template <size_t N, typename T>
+class tuple {
+public:
+    typedef T						value_type;
+    typedef size_t					size_type;
+    typedef value_type*					pointer;
+    typedef const value_type*				const_pointer;
+    typedef value_type&					reference;
+    typedef const value_type&				const_reference;
+    typedef pointer					iterator;
+    typedef const_pointer				const_iterator;
+    typedef ::ustl::reverse_iterator<iterator>		reverse_iterator;
+    typedef ::ustl::reverse_iterator<const_iterator>	const_reverse_iterator;
+    typedef pair<iterator,iterator>			range_t;
+    typedef pair<const_iterator,const_iterator>		const_range_t;
+public:
+    template <typename T2>
+    inline			tuple (const tuple<N,T2>& t);
+    inline			tuple (const tuple<N,T>& t);
+    inline			tuple (const_pointer v);
+    inline			tuple (void)			{ for (uoff_t i = 0; i < N; ++ i) m_v[i] = T(); }
+    explicit inline		tuple (const_reference v0, const_reference v1 = T(), const_reference v2 = T(), const_reference v3 = T());
+    inline iterator		begin (void)			{ return (m_v); }
+    inline const_iterator	begin (void) const		{ return (m_v); }
+    inline iterator		end (void)			{ return (begin() + N); }
+    inline const_iterator	end (void) const		{ return (begin() + N); }
+    inline size_type		size (void) const		{ return (N); }
+    inline size_type		max_size (void) const		{ return (N); }
+    inline bool			empty (void) const		{ return (N == 0); }
+    inline const_reference	at (size_type i) const		{ return (m_v[i]); }
+    inline reference		at (size_type i)		{ return (m_v[i]); }
+    inline const_reference	operator[] (size_type i) const	{ return (m_v[i]); }
+    inline reference		operator[] (size_type i)	{ return (m_v[i]); }
+    template <typename T2>
+    inline const tuple&		operator= (const tuple<N,T2>& src);
+    inline const tuple&		operator= (const tuple<N,T>& src);
+    inline const tuple&		operator+= (const_reference v)
+				    { for (uoff_t i = 0; i < N; ++ i) m_v[i] += v; return (*this); }
+    inline const tuple&		operator-= (const_reference v)
+				    { for (uoff_t i = 0; i < N; ++ i) m_v[i] -= v; return (*this); }
+    inline const tuple&		operator*= (const_reference v)
+				    { for (uoff_t i = 0; i < N; ++ i) m_v[i] *= v; return (*this); }
+    inline const tuple&		operator/= (const_reference v)
+				    { for (uoff_t i = 0; i < N; ++ i) m_v[i] /= v; return (*this); }
+    inline const tuple		operator+ (const_reference v) const
+				    { tuple result; for (uoff_t i = 0; i < N; ++ i) result[i] = m_v[i] + v; return (result); }
+    inline const tuple		operator- (const_reference v) const
+				    { tuple result; for (uoff_t i = 0; i < N; ++ i) result[i] = m_v[i] - v; return (result); }
+    inline const tuple		operator* (const_reference v) const
+				    { tuple result; for (uoff_t i = 0; i < N; ++ i) result[i] = m_v[i] * v; return (result); }
+    inline const tuple		operator/ (const_reference v) const
+				    { tuple result; for (uoff_t i = 0; i < N; ++ i) result[i] = m_v[i] / v; return (result); }
+    inline void			swap (tuple<N,T>& v)
+				    { for (uoff_t i = 0; i < N; ++ i) ::ustl::swap (m_v[i], v.m_v[i]); }
+private:
+    T				m_v [N];
+};
+
+} // namespace ustl
+
+#include "simd.h"
+
+namespace ustl {
+
+template <size_t N, typename T>
+template <typename T2>
+inline tuple<N,T>::tuple (const tuple<N,T2>& t)
+{ simd::pconvert (t, *this, simd::fcast<T2,T>()); }
+
+template <size_t N, typename T>
+inline tuple<N,T>::tuple (const tuple<N,T>& t)
+{ simd::passign (t, *this); }
+
+template <size_t N, typename T>
+inline tuple<N,T>::tuple (const_pointer v)
+{ simd::ipassign (v, *this); }
+
+template <size_t N, typename T>
+inline tuple<N,T>::tuple (const_reference v0, const_reference v1, const_reference v2, const_reference v3)
+{
+    m_v[0] = v0;
+    if (N > 1) m_v[1] = v1;
+    if (N > 2) m_v[2] = v2;
+    if (N > 3) m_v[3] = v3;
+    if (N > 4) fill_n (m_v + 4, N - 4, T());
+}
+
+template <size_t N, typename T>
+template <typename T2>
+inline const tuple<N,T>& tuple<N,T>::operator= (const tuple<N,T2>& src)
+{ simd::pconvert (src, *this, simd::fcast<T2,T>()); return (*this); }
+
+template <size_t N, typename T>
+inline const tuple<N,T>& tuple<N,T>::operator= (const tuple<N,T>& src)
+{ simd::passign (src, *this); return (*this); }
+
+template <size_t N, typename T1, typename T2>
+inline bool operator== (const tuple<N,T1>& t1, const tuple<N,T2>& t2)
+{
+    for (uoff_t i = 0; i < N; ++ i)
+	if (t1[i] != t2[i])
+	    return (false);
+    return (true);
+}
+
+template <size_t N, typename T1, typename T2>
+inline bool operator< (const tuple<N,T1>& t1, const tuple<N,T2>& t2)
+{
+    for (uoff_t i = 0; i < N && t1[i] <= t2[i]; ++ i)
+	if (t1[i] < t2[i])
+	    return (true);
+    return (false);
+}
+
+template <size_t N, typename T1, typename T2>
+inline const tuple<N,T1>& operator+= (tuple<N,T1>& t1, const tuple<N,T2>& t2)
+    { for (uoff_t i = 0; i < N; ++ i) t1[i] = T1(t1[i] + t2[i]); return (t1); }
+
+template <size_t N, typename T1, typename T2>
+inline const tuple<N,T1>& operator-= (tuple<N,T1>& t1, const tuple<N,T2>& t2)
+    { for (uoff_t i = 0; i < N; ++ i) t1[i] = T1(t1[i] - t2[i]); return (t1); }
+
+template <size_t N, typename T1, typename T2>
+inline const tuple<N,T1>& operator*= (tuple<N,T1>& t1, const tuple<N,T2>& t2)
+    { for (uoff_t i = 0; i < N; ++ i) t1[i] = T1(t1[i] * t2[i]); return (t1); }
+
+template <size_t N, typename T1, typename T2>
+inline const tuple<N,T1>& operator/= (tuple<N,T1>& t1, const tuple<N,T2>& t2)
+    { for (uoff_t i = 0; i < N; ++ i) t1[i] = T1(t1[i] / t2[i]); return (t1); }
+
+template <size_t N, typename T1, typename T2>
+inline const tuple<N,T1> operator+ (const tuple<N,T1>& t1, const tuple<N,T2>& t2)
+{
+    tuple<N,T1> result;
+    for (uoff_t i = 0; i < N; ++ i) result[i] = T1(t1[i] + t2[i]);
+    return (result);
+}
+
+template <size_t N, typename T1, typename T2>
+inline const tuple<N,T1> operator- (const tuple<N,T1>& t1, const tuple<N,T2>& t2)
+{
+    tuple<N,T1> result;
+    for (uoff_t i = 0; i < N; ++ i) result[i] = T1(t1[i] - t2[i]);
+    return (result);
+}
+
+template <size_t N, typename T1, typename T2>
+inline const tuple<N,T1> operator* (const tuple<N,T1>& t1, const tuple<N,T2>& t2)
+{
+    tuple<N,T1> result;
+    for (uoff_t i = 0; i < N; ++ i) result[i] = T1(t1[i] * t2[i]);
+    return (result);
+}
+
+template <size_t N, typename T1, typename T2>
+inline const tuple<N,T1> operator/ (const tuple<N,T1>& t1, const tuple<N,T2>& t2)
+{
+    tuple<N,T1> result;
+    for (uoff_t i = 0; i < N; ++ i) result[i] = T1(t1[i] / t2[i]);
+    return (result);
+}
+
+#if CPU_HAS_SSE
+#define SSE_TUPLE_SPECS(n,type)		\
+template <> inline tuple<n,type>::tuple (void)	\
+{ asm ("xorps %%xmm0, %%xmm0\n\tmovups %%xmm0, %0"::"m"(m_v[0]):"xmm0","memory"); }	\
+template<> inline void tuple<n,type>::swap (tuple<n,type>& v)	\
+{ asm ("movups %0,%%xmm0\n\tmovups %1,%%xmm1\n\tmovups %%xmm0,%1\n\tmovups %%xmm1,%0"::"m"(m_v[0]),"m"(v.m_v[0]):"xmm0","xmm1","memory"); }
+SSE_TUPLE_SPECS(4,float)
+SSE_TUPLE_SPECS(4,int32_t)
+SSE_TUPLE_SPECS(4,uint32_t)
+#undef SSE_TUPLE_SPECS
+#endif
+#if CPU_HAS_MMX
+#define MMX_TUPLE_SPECS(n,type)		\
+template <> inline tuple<n,type>::tuple (void)	\
+{ asm ("pxor %%mm0, %%mm0\n\tmovq %%mm0, %0"::"m"(m_v[0]):"mm0","memory"); simd::reset_mmx(); }	\
+template<> inline void tuple<n,type>::swap (tuple<n,type>& v)	\
+{ asm ("movq %0,%%mm0\n\tmovq %1,%%mm1\n\tmovq %%mm0,%1\n\tmovq %%mm1,%0"::"m"(m_v[0]),"m"(v.m_v[0]):"mm0","mm1","memory"); simd::reset_mmx(); }
+MMX_TUPLE_SPECS(2,float)
+MMX_TUPLE_SPECS(4,int16_t)
+MMX_TUPLE_SPECS(4,uint16_t)
+MMX_TUPLE_SPECS(2,int32_t)
+MMX_TUPLE_SPECS(2,uint32_t)
+MMX_TUPLE_SPECS(8,int8_t)
+MMX_TUPLE_SPECS(8,uint8_t)
+#undef MMX_TUPLE_SPECS
+#endif
+
+#define SIMD_TUPLE_PACKOP(N,T)	\
+template <> inline const tuple<N,T>& operator+= (tuple<N,T>& t1, const tuple<N,T>& t2)	\
+    { simd::padd (t2, t1); return (t1); }						\
+template <> inline const tuple<N,T>& operator-= (tuple<N,T>& t1, const tuple<N,T>& t2)	\
+    { simd::psub (t2, t1); return (t1); }						\
+template <> inline const tuple<N,T>& operator*= (tuple<N,T>& t1, const tuple<N,T>& t2)	\
+    { simd::pmul (t2, t1); return (t1); }						\
+template <> inline const tuple<N,T>& operator/= (tuple<N,T>& t1, const tuple<N,T>& t2)	\
+    { simd::pdiv (t2, t1); return (t1); }						\
+template <> inline const tuple<N,T> operator+ (const tuple<N,T>& t1, const tuple<N,T>& t2) \
+    { tuple<N,T> result (t1); simd::padd (t2, result); return (result); }		\
+template <> inline const tuple<N,T> operator- (const tuple<N,T>& t1, const tuple<N,T>& t2) \
+    { tuple<N,T> result (t1); simd::psub (t2, result); return (result); }		\
+template <> inline const tuple<N,T> operator* (const tuple<N,T>& t1, const tuple<N,T>& t2) \
+    { tuple<N,T> result (t1); simd::pmul (t2, result); return (result); }		\
+template <> inline const tuple<N,T> operator/ (const tuple<N,T>& t1, const tuple<N,T>& t2) \
+    { tuple<N,T> result (t1); simd::pdiv (t2, result); return (result); }
+SIMD_TUPLE_PACKOP(4,float)
+SIMD_TUPLE_PACKOP(2,float)
+SIMD_TUPLE_PACKOP(2,double)
+SIMD_TUPLE_PACKOP(4,int32_t)
+SIMD_TUPLE_PACKOP(4,uint32_t)
+SIMD_TUPLE_PACKOP(4,int16_t)
+SIMD_TUPLE_PACKOP(4,uint16_t)
+SIMD_TUPLE_PACKOP(2,int32_t)
+SIMD_TUPLE_PACKOP(2,uint32_t)
+SIMD_TUPLE_PACKOP(8,int8_t)
+SIMD_TUPLE_PACKOP(8,uint8_t)
+#undef SIMD_TUPLE_PACKOP
+
+} // namespace ustl
+
+#endif
+
diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/utypes.h b/media/libdrm/mobile2/src/util/ustl-1.0/utypes.h
new file mode 100644
index 0000000..f0b0265
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/ustl-1.0/utypes.h
@@ -0,0 +1,69 @@
+// This file is part of the ustl library, an STL implementation.
+//
+// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
+// This file is free software, distributed under the MIT License.
+//
+// utypes.h
+//
+// Types used by this library.
+//
+
+#ifndef UTYPES_H_118BBB3B50B7DBF22F5460C52E515C83
+#define UTYPES_H_118BBB3B50B7DBF22F5460C52E515C83
+
+#include "config.h"
+#ifndef STDC_HEADERS
+    #error This library requires standard C and C++ headers to compile.
+#endif
+#ifndef STDUNIX_HEADERS
+    #error This library compiles only on UNIX systems.
+#endif
+#define __STDC_LIMIT_MACROS	// For WCHAR_MIN and WCHAR_MAX in stdint.
+#define __STDC_CONSTANT_MACROS	// For UINT??_C macros to avoid using L and UL suffixes on constants.
+#ifdef HAVE_STDINT_H
+    #include <stdint.h>
+#elif HAVE_INTTYPES_H
+    #include <inttypes.h>
+#else
+    #error Need standard integer types definitions, usually in stdint.h
+#endif
+#include <stddef.h>		// For ptrdiff_t, size_t
+#include <limits.h>
+#include <float.h>
+#ifdef HAVE_SYS_TYPES_H
+    #include <sys/types.h>
+#endif
+#ifndef SIZE_MAX
+    #define SIZE_MAX		UINT_MAX
+#endif
+#if sun || __sun		// Solaris defines UINTPTR_MAX as empty.
+    #undef UINTPTR_MAX
+    #define UINTPTR_MAX		ULONG_MAX
+#endif
+#ifndef WCHAR_MAX
+    #ifdef __WCHAR_MAX__
+	#define WCHAR_MAX	__WCHAR_MAX__
+    #else
+	#define WCHAR_MAX	CHAR_MAX
+    #endif
+#endif
+#ifdef HAVE_LONG_LONG
+    #ifndef LLONG_MAX
+	#define ULLONG_MAX	UINT64_C(0xFFFFFFFFFFFFFFFF)
+	#define LLONG_MAX	INT64_C(0x7FFFFFFFFFFFFFFF)
+	#define LLONG_MIN	ULLONG_MAX
+    #endif
+#endif
+#if !PLATFORM_ANDROID
+#ifndef BYTE_ORDER
+    #define LITTLE_ENDIAN	USTL_LITTLE_ENDIAN
+    #define BIG_ENDIAN		USTL_BIG_ENDIAN
+    #define BYTE_ORDER		USTL_BYTE_ORDER
+#endif
+#endif
+
+typedef size_t		uoff_t;		///< A type for storing offsets into blocks measured by size_t.
+typedef uint32_t	hashvalue_t;	///< Value type returned by the hash functions.
+
+#endif
+
diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/uutility.h b/media/libdrm/mobile2/src/util/ustl-1.0/uutility.h
new file mode 100644
index 0000000..7b5ae64
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/ustl-1.0/uutility.h
@@ -0,0 +1,387 @@
+// This file is part of the ustl library, an STL implementation.
+//
+// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
+// This file is free software, distributed under the MIT License.
+//
+/// \file uutility.h
+///
+/// \brief Utility templates.
+///
+/// Everything in here except min(), max(), distance(), and advance()
+/// are uSTL extensions and are absent from other STL implementations.
+///
+
+#ifndef UUTILITY_H_6A58BD296269A82A4AAAA4FD19FDB3AC
+#define UUTILITY_H_6A58BD296269A82A4AAAA4FD19FDB3AC
+
+#include "uassert.h"
+#include "utypes.h"
+
+#if PLATFORM_ANDROID
+#include <stdio.h>
+#undef CPU_HAS_MMX
+#endif
+
+namespace ustl {
+
+#ifdef __GNUC__
+    /// Returns the number of elements in a static vector
+    #define VectorSize(v)	(sizeof(v) / sizeof(*v))
+#else
+    // Old compilers will not be able to evaluate *v on an empty vector.
+    // The tradeoff here is that VectorSize will not be able to measure arrays of local structs.
+    #define VectorSize(v)	(sizeof(v) / ustl::size_of_elements(1, v))
+#endif
+
+/// Expands into a ptr,size expression for the given static vector; useful as link arguments.
+#define VectorBlock(v)	(v)+0, VectorSize(v)	// +0 makes it work under gcc 2.95
+/// Expands into a begin,end expression for the given static vector; useful for algorithm arguments.
+#define VectorRange(v)	VectorBlock(v)+(v)
+
+/// Returns the number of bits in the given type
+#define BitsInType(t)	(sizeof(t) * CHAR_BIT)
+
+/// Returns the mask of type \p t with the lowest \p n bits set.
+#define BitMask(t,n)	(t(~t(0)) >> ((sizeof(t) * CHAR_BIT) - (n)))
+
+/// Argument that is used only in debug builds (as in an assert)
+#ifndef NDEBUG
+    #define DebugArg(x)	x
+#else
+    #define DebugArg(x)
+#endif
+
+/// Shorthand for container iteration.
+#define foreach(type,i,ctr)	for (type i = (ctr).begin(); i != (ctr).end(); ++ i)
+/// Shorthand for container reverse iteration.
+#define eachfor(type,i,ctr)	for (type i = (ctr).rbegin(); i != (ctr).rend(); ++ i)
+
+/// Macro for passing template types as macro arguments.
+/// \@{
+#define TEMPLATE_FULL_DECL1(d1,t1)		template <d1 t1>
+#define TEMPLATE_FULL_DECL2(d1,t1,d2,t2)	template <d1 t1, d2 t2>
+#define TEMPLATE_FULL_DECL3(d1,t1,d2,t2,d3,t3)	template <d1 t1, d2 t2, d3 t3>
+#define TEMPLATE_DECL1(t1)		TEMPLATE_FULL_DECL1(typename,t1)
+#define TEMPLATE_DECL2(t1,t2)		TEMPLATE_FULL_DECL2(typename,t1,typename,t2)
+#define TEMPLATE_DECL3(t1,t2,t3)	TEMPLATE_FULL_DECL3(typename,t1,typename,t2,typename,t3)
+#define TEMPLATE_TYPE1(type,a1)		type<a1>
+#define TEMPLATE_TYPE2(type,a1,a2)	type<a1,a2>
+#define TEMPLATE_TYPE3(type,a1,a2,a3)	type<a1,a2,a3>
+/// \@}
+
+/// Returns the minimum of \p a and \p b
+template <typename T1, typename T2>
+inline const T1 min (const T1& a, const T2& b)
+{
+    return (a < b ? a : b);
+}
+
+/// Returns the maximum of \p a and \p b
+template <typename T1, typename T2>
+inline const T1 max (const T1& a, const T2& b)
+{
+    return (b < a ? a : b);
+}
+
+/// \brief Divides \p n1 by \p n2 and rounds the result up.
+/// This is in contrast to regular division, which rounds down.
+/// Negative numbers are rounded down because they are an unusual case, supporting
+/// which would require a branch. Since this is frequently used in graphics, the
+/// speed is important.
+///
+template <typename T1, typename T2>
+inline T1 DivRU (T1 n1, T2 n2)
+{
+    return (n1 / n2 + (n1 % n2 > 0));
+}
+
+/// The alignment performed by default.
+const size_t c_DefaultAlignment = __alignof__(void*);
+
+/// \brief Rounds \p n up to be divisible by \p grain
+template <typename T>
+inline T Align (T n, size_t grain = c_DefaultAlignment)
+{
+    T a, r = n % grain;
+    if (grain == 2) return (n + r);
+    switch (grain) {
+	case 4: case 8: case 16: a = (n & ~(grain - 1)) + grain; break;
+	default:		 a = n + (grain - r);
+    };
+    return (r ? a : n);
+}
+
+/// Offsets an iterator
+template <typename T>
+inline T advance (T i, ssize_t offset)
+{
+    return (i + offset);
+}
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+/// Offsets a void pointer
+template <>
+inline const void* advance (const void* p, ssize_t offset)
+{
+    assert (p || !offset);
+    return (reinterpret_cast<const uint8_t*>(p) + offset);
+}
+
+/// Offsets a void pointer
+template <>
+inline void* advance (void* p, ssize_t offset)
+{
+    assert (p || !offset);
+    return (reinterpret_cast<uint8_t*>(p) + offset);
+}
+#endif
+
+/// Returns the difference \p p1 - \p p2
+template <typename T1, typename T2>
+inline ptrdiff_t distance (T1 i1, T2 i2)
+{
+    return (i2 - i1);
+}
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+#define UNVOID_DISTANCE(T1const,T2const)				   \
+template <> inline ptrdiff_t distance (T1const void* p1, T2const void* p2) \
+{ return ((T2const uint8_t*)(p2) - (T1const uint8_t*)(p1)); }
+UNVOID_DISTANCE(,)
+UNVOID_DISTANCE(const,const)
+UNVOID_DISTANCE(,const)
+UNVOID_DISTANCE(const,)
+#undef UNVOID_DISTANCE
+#endif
+
+/// \brief Returns the absolute value of \p v
+/// Unlike the stdlib functions, this is inline and works with all types.
+template <typename T>
+inline T absv (T v)
+{
+    return (v < 0 ? -v : v);
+}
+
+/// \brief Returns -1 for negative values, 1 for positive, and 0 for 0
+template <typename T>
+inline T sign (T v)
+{
+    return ((0 < v) - (v < 0));
+}
+
+/// Returns the absolute value of the distance i1 and i2
+template <typename T1, typename T2>
+inline size_t abs_distance (T1 i1, T2 i2)
+{
+    return (absv (distance(i1, i2)));
+}
+
+/// Returns the size of \p n elements of size \p T
+template <typename T>
+inline size_t size_of_elements (size_t n, const T*)
+{
+    return (n * sizeof(T));
+}
+
+// Defined in byteswap.h, which is usually unusable.
+#undef bswap_16
+#undef bswap_32
+#undef bswap_64
+
+#if CPU_HAS_CMPXCHG8	// If it has that, it has bswap.
+inline uint16_t bswap_16 (uint16_t v)	{ asm ("rorw $8, %w0" : "=r"(v) : "0"(v) : "cc"); return (v); }
+inline uint32_t bswap_32 (uint32_t v)	{ asm ("bswap %0" : "=r"(v) : "0"(v)); return (v); }
+#else
+inline uint16_t bswap_16 (uint16_t v)	{ return (v << 8 | v >> 8); }
+inline uint32_t bswap_32 (uint32_t v)	{ return (v << 24 | (v & 0xFF00) << 8 | (v >> 8) & 0xFF00 | v >> 24); }
+#endif
+#if HAVE_INT64_T
+inline uint64_t bswap_64 (uint64_t v)	{ return ((uint64_t(bswap_32(v)) << 32) | bswap_32(v >> 32)); }
+#endif
+
+/// \brief Swaps the byteorder of \p v.
+template <typename T>
+inline T bswap (const T& v)
+{
+    switch (BitsInType(T)) {
+	default:	return (v);
+	case 16:	return (T (bswap_16 (uint16_t (v))));
+	case 32:	return (T (bswap_32 (uint32_t (v))));
+#if HAVE_INT64_T
+	case 64:	return (T (bswap_64 (uint64_t (v))));
+#endif
+    };
+}
+
+#if USTL_BYTE_ORDER == USTL_BIG_ENDIAN
+template <typename T> inline T le_to_native (const T& v) { return (bswap (v)); }
+template <typename T> inline T be_to_native (const T& v) { return (v); }
+template <typename T> inline T native_to_le (const T& v) { return (bswap (v)); }
+template <typename T> inline T native_to_be (const T& v) { return (v); }
+#elif USTL_BYTE_ORDER == USTL_LITTLE_ENDIAN
+template <typename T> inline T le_to_native (const T& v) { return (v); }
+template <typename T> inline T be_to_native (const T& v) { return (bswap (v)); }
+template <typename T> inline T native_to_le (const T& v) { return (v); }
+template <typename T> inline T native_to_be (const T& v) { return (bswap (v)); }
+#endif // USTL_BYTE_ORDER
+
+/// Deletes \p p and sets it to NULL
+template <typename T>
+inline void Delete (T*& p)
+{
+    delete p;
+    p = NULL;
+}
+
+/// Deletes \p p as an array and sets it to NULL
+template <typename T>
+inline void DeleteVector (T*& p)
+{
+    delete [] p;
+    p = NULL;
+}
+
+/// Template of making != from ! and ==
+template <typename T>
+inline bool operator!= (const T& x, const T& y)
+{
+    return (!(x == y));
+}
+
+/// Template of making > from <
+template <typename T>
+inline bool operator> (const T& x, const T& y)
+{
+    return (y < x);
+}
+
+/// Template of making <= from < and ==
+template <typename T>
+inline bool operator<= (const T& x, const T& y)
+{
+    return (!(y < x));
+}
+
+/// Template of making >= from < and ==
+template <typename T>
+inline bool operator>= (const T& x, const T& y)
+{
+    return (!(x < y));
+}
+
+/// Packs \p s multiple times into \p b. Useful for loop unrolling.
+template <typename TSmall, typename TBig>
+inline void pack_type (TSmall s, TBig& b)
+{
+    const size_t n = sizeof(TBig) / sizeof(TSmall);
+    b = s;
+    // Calls to min are here to avoid warnings for shifts bigger than the type. min will be gone when optimized.
+    if (n < 2) return;
+    b = (b << min (BitsInType(TSmall), BitsInType(TBig))) | b;
+    if (n < 4) return;
+    b = (b << min (BitsInType(TSmall) * 2, BitsInType(TBig))) | b;
+    if (n < 8) return;
+    b = (b << min (BitsInType(TSmall) * 4, BitsInType(TBig))) | b;
+}
+
+#if __GNUC__ >= 3
+inline bool TestAndSet (int* pm) __attribute__((always_inline));
+#endif
+/// Sets the contents of \p pm to 1 and returns true if the previous value was 0.
+inline bool TestAndSet (int* pm)
+{
+#if CPU_HAS_CMPXCHG8
+    bool rv;
+    int oldVal (1);
+    asm volatile ( // cmpxchg compares to %eax and swaps if equal
+	"cmpxchgl %3, %1\n\t"
+	"sete %0"
+	: "=a" (rv), "=m" (*pm), "=r" (oldVal)
+	: "2" (oldVal), "a" (0)
+	: "memory");
+    return (rv);
+#elif __i386__ || __x86_64__
+    int oldVal (1);
+    asm volatile ("xchgl %0, %1" : "=r"(oldVal), "=m"(*pm) : "0"(oldVal), "m"(*pm) : "memory");
+    return (!oldVal);
+#elif __sparc32__	// This has not been tested
+    int rv;
+    asm volatile ("ldstub %1, %0" : "=r"(rv), "=m"(*pm) : "m"(pm));
+    return (!rv);
+#else
+    const int oldVal (*pm);
+    *pm = 1;
+    return (!oldVal);
+#endif
+}
+
+/// \brief This template is to be used for dereferencing a type-punned pointer without a warning.
+///
+/// When casting a local variable to an unrelated type through a pointer (for
+/// example, casting a float to a uint32_t without conversion), the resulting
+/// memory location can be accessed through either pointer, which violates the
+/// strict aliasing rule. While -fno-strict-aliasing option can be given to
+/// the compiler, eliminating this warning, inefficient code may result in
+/// some instances, because aliasing inhibits some optimizations. By using
+/// this template, and by ensuring the memory is accessed in one way only,
+/// efficient code can be produced without the warning. For gcc 4.1.0+.
+///
+template <typename DEST, typename SRC>
+inline DEST noalias (DEST, SRC* s)
+{
+    union UPun { SRC s; DEST d; };
+    return (((UPun*)(s))->d);
+}
+
+namespace simd {
+    /// Call after you are done using SIMD algorithms for 64 bit tuples.
+#if CPU_HAS_MMX
+    inline void reset_mmx (void) __attribute__((always_inline));
+    #define ALL_MMX_REGS_CHANGELIST "mm0","mm1","mm2","mm3","mm4","mm5","mm6","mm7","st","st(1)","st(2)","st(3)","st(4)","st(5)","st(6)","st(7)"
+    #if CPU_HAS_3DNOW
+	inline void reset_mmx (void) { asm ("femms":::ALL_MMX_REGS_CHANGELIST); }
+    #else
+	inline void reset_mmx (void) { asm ("emms":::ALL_MMX_REGS_CHANGELIST); }
+    #endif
+#else
+    inline void reset_mmx (void) {}
+#endif
+} // namespace simd
+
+/// \brief Type that is not size_t
+///
+/// Because size_t may be declared as unsigned long or unsigned int on
+/// different machines, this macro is convenient when defining overloads
+/// of size_t to use other types.
+///
+#if defined(SIZE_T_IS_LONG) && !defined(__ARM_EABI__)
+     #define NOT_SIZE_T_I_OR_L	unsigned int
+#else
+    #define NOT_SIZE_T_I_OR_L	unsigned long
+#endif
+
+/// \brief Required when you want to overload size_t and a pointer.
+///
+/// The compiler will happily cast a number to a pointer and declare
+/// that the overload is ambiguous unless you define overloads for all
+/// possible integral types that a number may represent. This behaviour,
+/// although braindead, is in the ANSI standard, and thus not a bug. If
+/// you want to change the standard, the best solution is to disallow any
+/// implicit casts to pointer from an integral type. Ironically, such an
+/// implicit cast is already detected by gcc.
+///
+#if defined(USTL_ANDROID_X86)
+#define OVERLOAD_POINTER_AND_SIZE_T_V2(name, arg1type)
+#else
+#define OVERLOAD_POINTER_AND_SIZE_T_V2(name, arg1type)						\
+    inline void	name (arg1type a1, short a2)			{ name (a1, size_t(a2)); }	\
+    inline void	name (arg1type a1, unsigned short a2)		{ name (a1, size_t(a2)); }	\
+    inline void	name (arg1type a1, int a2)			{ name (a1, size_t(a2)); }	\
+    inline void	name (arg1type a1, long a2)			{ name (a1, size_t(a2)); }	\
+    inline void	name (arg1type a1, NOT_SIZE_T_I_OR_L a2)	{ name (a1, size_t(a2)); }
+#endif
+} // namespace ustl
+
+
+#endif
+
diff --git a/media/libdrm/mobile2/src/util/ustl-1.0/uvector.h b/media/libdrm/mobile2/src/util/ustl-1.0/uvector.h
new file mode 100644
index 0000000..ccbc45b
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/ustl-1.0/uvector.h
@@ -0,0 +1,277 @@
+// This file is part of the ustl library, an STL implementation.
+//
+// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
+// This file is free software, distributed under the MIT License.
+//
+// uvector.h
+//
+
+#ifndef UVECTOR_H_00BB13AF082BEB7829C031B265518169
+#define UVECTOR_H_00BB13AF082BEB7829C031B265518169
+
+#include "uassert.h"
+#include "memblock.h"
+#include "umemory.h"
+
+namespace ustl {
+
+/// \class vector uvector.h ustl.h
+/// \ingroup Sequences
+///
+/// \brief STL vector equivalent.
+///
+/// Provides a typed array-like interface to a managed memory block, including
+/// element access, iteration, modification, resizing, and serialization. In
+/// this design elements frequently undergo bitwise move, so don't put it in
+/// here if it doesn't support it. This mostly means having no self-pointers.
+///
+template <typename T>
+class vector {
+public:
+    typedef T				value_type;
+    typedef value_type*			pointer;
+    typedef const value_type*		const_pointer;
+    typedef value_type&			reference;
+    typedef const value_type&		const_reference;
+    typedef pointer			iterator;
+    typedef const_pointer		const_iterator;
+    typedef memblock::size_type		size_type;
+    typedef memblock::written_size_type	written_size_type;
+    typedef memblock::difference_type	difference_type;
+    typedef ::ustl::reverse_iterator<iterator>	reverse_iterator;
+    typedef ::ustl::reverse_iterator<const_iterator>	const_reverse_iterator;
+public:
+    inline			vector (void);
+    inline explicit		vector (size_type n);
+				vector (size_type n, const T& v);
+				vector (const vector<T>& v);
+				vector (const_iterator i1, const_iterator i2);
+			       ~vector (void) throw();
+    inline const vector<T>&	operator= (const vector<T>& v);
+    inline bool			operator== (const vector<T>& v)	{ return (m_Data == v.m_Data); }
+    inline			operator cmemlink (void) const	{ return (cmemlink (m_Data)); }
+    inline			operator cmemlink (void)	{ return (cmemlink (m_Data)); }
+    inline			operator memlink (void)		{ return (memlink (m_Data)); }
+    inline void			reserve (size_type n, bool bExact = true);
+    inline void			resize (size_type n, bool bExact = true);
+    inline size_type		capacity (void) const		{ return (m_Data.capacity() / sizeof(T));	}
+    inline size_type		size (void) const		{ return (m_Data.size() / sizeof(T));		}
+    inline size_type		max_size (void) const		{ return (m_Data.max_size() / sizeof(T));	}
+    inline bool			empty (void) const		{ return (m_Data.empty());			}
+    inline iterator		begin (void)			{ return (iterator (m_Data.begin()));		}
+    inline const_iterator	begin (void) const		{ return (const_iterator (m_Data.begin()));	}
+    inline iterator		end (void)			{ return (iterator (m_Data.end()));		}
+    inline const_iterator	end (void) const		{ return (const_iterator (m_Data.end()));	}
+    inline reverse_iterator		rbegin (void)		{ return (reverse_iterator (end()));		}
+    inline const_reverse_iterator	rbegin (void) const	{ return (const_reverse_iterator (end()));	}
+    inline reverse_iterator		rend (void)		{ return (reverse_iterator (begin()));		}
+    inline const_reverse_iterator	rend (void) const	{ return (const_reverse_iterator (begin()));	}
+    inline iterator		iat (size_type i)		{ assert (i <= size()); return (begin() + i); }
+    inline const_iterator	iat (size_type i) const		{ assert (i <= size()); return (begin() + i); }
+    inline reference		at (size_type i)		{ assert (i < size()); return (begin()[i]); }
+    inline const_reference	at (size_type i) const		{ assert (i < size()); return (begin()[i]); }
+    inline reference		operator[] (size_type i)	{ return (at (i)); }
+    inline const_reference	operator[] (size_type i) const	{ return (at (i)); }
+    inline reference		front (void)			{ return (at(0)); }
+    inline const_reference	front (void) const		{ return (at(0)); }
+    inline reference		back (void)			{ assert (!empty()); return (end()[-1]); }
+    inline const_reference	back (void) const		{ assert (!empty()); return (end()[-1]); }
+    inline void			push_back (const T& v = T());
+    inline void			pop_back (void)			{ m_Data.memlink::resize (m_Data.size() - sizeof(T)); }
+    inline void			clear (void)			{ m_Data.clear(); }
+    void			deallocate (void) throw();
+    inline void			assign (const_iterator i1, const_iterator i2);
+    inline void			assign (size_type n, const T& v);
+    inline void			swap (vector<T>& v)		{ m_Data.swap (v.m_Data); }
+    inline iterator		insert (iterator ip, const T& v = T());
+    inline iterator		insert (iterator ip, size_type n, const T& v);
+    inline iterator		insert (iterator ip, const_iterator i1, const_iterator i2);
+    inline iterator		erase (iterator ep, size_type n = 1);
+    inline iterator		erase (iterator ep1, iterator ep2);
+    inline void			manage (pointer p, size_type n)		{ m_Data.manage (p, n * sizeof(T)); }
+    inline bool			is_linked (void) const			{ return (m_Data.is_linked()); }
+    inline void			unlink (void)				{ m_Data.unlink(); }
+    inline void			copy_link (void)			{ m_Data.copy_link(); }
+    inline void			link (const_pointer p, size_type n)	{ m_Data.link (p, n * sizeof(T)); }
+    inline void			link (pointer p, size_type n)		{ m_Data.link (p, n * sizeof(T)); }
+    inline void			link (const vector<T>& v)		{ m_Data.link (v); }
+    inline void			link (vector<T>& v)			{ m_Data.link (v); }
+    inline void			link (const_pointer first, const_pointer last)	{ m_Data.link (first, last); }
+    inline void			link (pointer first, pointer last)		{ m_Data.link (first, last); }
+				OVERLOAD_POINTER_AND_SIZE_T_V2(link, pointer)
+				OVERLOAD_POINTER_AND_SIZE_T_V2(link, const_pointer)
+private:
+    inline iterator		insert_space (iterator ip, size_type n);
+private:
+    memblock			m_Data;	///< Raw element data, consecutively stored.
+};
+
+/// Allocates space for at least \p n elements.
+template <typename T>
+void vector<T>::reserve (size_type n, bool bExact)
+{
+    const size_type oldCapacity = capacity();
+    m_Data.reserve (n * sizeof(T), bExact);
+    if (capacity() > oldCapacity)
+	construct (begin() + oldCapacity, begin() + capacity());
+}
+
+/// Resizes the vector to contain \p n elements.
+template <typename T>
+void vector<T>::resize (size_type n, bool bExact)
+{
+    if (m_Data.capacity() < n * sizeof(T))
+	reserve (n, bExact);
+    m_Data.memlink::resize (n * sizeof(T));
+}
+
+/// Calls element destructors and frees storage.
+template <typename T>
+void vector<T>::deallocate (void) throw()
+{
+    if (!is_linked())
+	destroy (begin(), begin() + capacity());
+    m_Data.deallocate();
+}
+
+/// Initializes empty vector.
+template <typename T>
+inline vector<T>::vector (void)
+: m_Data ()
+{
+}
+
+/// Initializes a vector of size \p n.
+template <typename T>
+inline vector<T>::vector (size_type n)
+: m_Data ()
+{
+    resize (n);
+}
+
+/// Copies \p n elements from \p v.
+template <typename T>
+vector<T>::vector (size_type n, const T& v)
+: m_Data ()
+{
+    resize (n);
+    ::ustl::fill (begin(), end(), v);
+}
+
+/// Copies \p v.
+template <typename T>
+vector<T>::vector (const vector<T>& v)
+: m_Data ()
+{
+    resize (v.size());
+    ::ustl::copy (v.begin(), v.end(), begin());
+}
+
+/// Copies range [\p i1, \p i2]
+template <typename T>
+vector<T>::vector (const_iterator i1, const_iterator i2)
+: m_Data ()
+{
+    resize (distance (i1, i2));
+    ::ustl::copy (i1, i2, begin());
+}
+
+/// Destructor
+template <typename T>
+inline vector<T>::~vector (void) throw()
+{
+    if (!numeric_limits<value_type>::is_integral)
+	deallocate();
+}
+
+/// Copies the range [\p i1, \p i2]
+template <typename T>
+inline void vector<T>::assign (const_iterator i1, const_iterator i2)
+{
+    assert (i1 <= i2);
+    resize (distance (i1, i2));
+    ::ustl::copy (i1, i2, begin());
+}
+
+/// Copies \p n elements with value \p v.
+template <typename T>
+inline void vector<T>::assign (size_type n, const T& v)
+{
+    resize (n);
+    ::ustl::fill (begin(), end(), v);
+}
+
+/// Copies contents of \p v.
+template <typename T>
+inline const vector<T>& vector<T>::operator= (const vector<T>& v)
+{
+    assign (v.begin(), v.end());
+    return (*this);
+}
+
+/// Inserts \p n uninitialized elements at \p ip.
+template <typename T>
+typename vector<T>::iterator vector<T>::insert_space (iterator ip, size_type n)
+{
+    const uoff_t ipmi = distance (m_Data.begin(), memblock::iterator(ip));
+    reserve (size() + n, false);
+    return (iterator (m_Data.insert (m_Data.iat(ipmi), n * sizeof(T))));
+}
+
+/// Inserts \p n elements with value \p v at offsets \p ip.
+template <typename T>
+typename vector<T>::iterator vector<T>::insert (iterator ip, size_type n, const T& v)
+{
+    ip = insert_space (ip, n);
+    ::ustl::fill (ip, ip + n, v);
+    return (ip);
+}
+
+/// Inserts value \p v at offset \p ip.
+template <typename T>
+typename vector<T>::iterator vector<T>::insert (iterator ip, const T& v)
+{
+    *(ip = insert_space (ip, 1)) = v;
+    return (ip);
+}
+
+/// Inserts range [\p i1, \p i2] at offset \p ip.
+template <typename T>
+typename vector<T>::iterator vector<T>::insert (iterator ip, const_iterator i1, const_iterator i2)
+{
+    assert (i1 <= i2);
+    ip = insert_space (ip, distance (i1, i2));
+    ::ustl::copy (i1, i2, ip);
+    return (ip);
+}
+
+/// Removes \p count elements at offset \p ep.
+template <typename T>
+inline typename vector<T>::iterator vector<T>::erase (iterator ep, size_type n)
+{
+    return (iterator (m_Data.erase (memblock::iterator(ep), n * sizeof(T))));
+}
+
+/// Removes elements from \p ep1 to \p ep2.
+template <typename T>
+inline typename vector<T>::iterator vector<T>::erase (iterator ep1, iterator ep2)
+{
+    assert (ep1 <= ep2);
+    return (erase (ep1, distance(ep1, ep2)));
+}
+
+/// Inserts value \p v at the end of the vector.
+template <typename T>
+void vector<T>::push_back (const T& v)
+{
+    resize (size() + 1, false);
+    back() = v;
+}
+
+/// Use with vector classes to allocate and link to stack space. \p n is in elements.
+#define typed_alloca_link(m,T,n)	(m).link ((T*) alloca ((n) * sizeof(T)), (n))
+
+} // namespace ustl
+
+#endif
+
diff --git a/media/libdrm/mobile2/src/util/xml/DomExpatAgent.cpp b/media/libdrm/mobile2/src/util/xml/DomExpatAgent.cpp
new file mode 100644
index 0000000..4cde706
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/xml/DomExpatAgent.cpp
@@ -0,0 +1,228 @@
+/*
+ * 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.
+ */

+#include <util/xml/DomExpatAgent.h>
+#include <util/xml/XMLElementImpl.h>
+#include <ustring.h>
+#include <uios.h>
+using namespace ustl;
+
+/** see DomExpatAgent.h */
+DomExpatAgent::DomExpatAgent(XMLDocumentImpl* xmlDocPtr)
+{
+    mXMLDocumentPtr = xmlDocPtr;
+    mTopElementPtr = NULL;
+}
+
+/** see DomExpatAgent.h */
+DomExpatAgent::~DomExpatAgent()
+{
+
+}
+
+/** see DomExpatAgent.h */
+bool DomExpatAgent::generateDocumentFromXML(istringstream *xmlStream)
+{
+    char ch;
+    string content;
+
+    if (NULL == mXMLDocumentPtr || NULL == xmlStream)
+    {
+        return false;
+    }
+
+    while ((ch = xmlStream->get()) != '\0')
+    {
+        content += ch;
+    }
+
+    if (ExpatWrapper::decode(content.c_str(), content.length(), 1) == 0)
+
+    {
+        return false;
+    }
+    return true;
+}
+
+/** see DomExpatAgent.h */
+void DomExpatAgent::pushTag(const DOMString *name, const XML_Char **atts)
+{
+    ElementImpl *elementNode = mXMLDocumentPtr->createElement(name);
+
+    if (NULL == elementNode)
+    {
+        return;
+    }
+
+    if (NULL != atts)
+    {
+        while (NULL != *atts)
+        {
+            //set attributes into element node.
+            DOMString key(atts[0]), value(atts[1]);
+            elementNode->setAttribute(&key, &value);
+            atts += 2;
+        }
+    }
+
+   if (!mStack.empty())
+   {
+       mTopElementPtr->appendChild(elementNode);
+   }
+   else
+   {
+       mXMLDocumentPtr->setFirstChild(elementNode);
+   }
+
+   mTopElementPtr = (XMLElementImpl *)elementNode;
+   mStack.push_back(elementNode);
+}
+
+/** see DomExpatAgent.h */
+void DomExpatAgent::popTag(const DOMString *name)
+{
+    if (NULL == name)
+    {
+        return;
+    }
+
+    if (mTopElementPtr != NULL)
+    {
+        if (!name->compare(mTopElementPtr->getTagName()->c_str()))
+        {
+            mStack.pop_back();
+            if (!mStack.empty())
+            {
+                mTopElementPtr =(XMLElementImpl *) mStack.back();
+            }
+            else
+            {
+                mTopElementPtr = NULL;
+            }
+        }
+    }
+}
+
+/** see DomExpatAgent.h */
+void DomExpatAgent::appendText(const DOMString *text)
+{
+    if ((mTopElementPtr != NULL) && (text != NULL))
+    {
+        TextImpl *textNode = mXMLDocumentPtr->createTextNode(text);
+
+        if (NULL == textNode)
+        {
+            return;
+        }
+
+       mTopElementPtr->appendChild(textNode);
+    }
+}
+
+/** see DomExpatAgent.h */
+void DomExpatAgent::startElement(const XML_Char *name, const XML_Char **atts)
+{
+    if (name)
+    {
+        DOMString tagName(name);
+
+        pushTag(&tagName, atts);
+    }
+}
+
+/** see DomExpatAgent.h */
+void DomExpatAgent::dataHandler(const XML_Char *s, int len)
+{
+    if (s != NULL && len >= 1 && *s != '\n')
+    {
+        DOMString text;
+        text.assign((char*)s, len);
+        appendText(&text);
+    }
+}
+
+/** see DomExpatAgent.h */
+void DomExpatAgent::endElement(const XML_Char *name)
+{
+   if (name)
+   {
+       DOMString tagName(name);
+       popTag(&tagName);
+   }
+}
+
+/** see DomExpatAgent.h */
+ostringstream* DomExpatAgent::generateXMLFromDocument()
+{
+    if (NULL == mXMLDocumentPtr)
+    {
+        return NULL;
+    }
+
+    ElementImpl *root = mXMLDocumentPtr->getDocumentElement();
+
+    traverse(root);
+
+    return &mXMLostream;
+}
+
+/** see DomExpatAgent.h */
+void DomExpatAgent::traverse(ElementImpl *root)
+{
+    if (NULL == root)
+    {
+        return;
+    }
+
+    mXMLostream << "<" << *(root->getNodeName());
+
+    if (root->hasAttributes())
+    {
+        mXMLostream << endl;
+        const DOMStringMap* attrMapPtr = (static_cast<XMLElementImpl*>(root))->getAttributeMap();
+        DOMStringMap::const_reverse_iterator pos;
+
+        for (pos=attrMapPtr->rbegin(); pos != attrMapPtr->rend(); pos++)
+        {
+            mXMLostream << pos->first << "=" << "\"" << pos->second << "\"";
+
+            if (pos + 1 != attrMapPtr->rend())
+            {
+                mXMLostream << endl;
+            }
+        }
+    }
+
+    mXMLostream << ">" << endl;
+
+    NodeImpl *child = root->getFirstChild();
+
+    while (child != NULL)
+    {
+        NodeType what = child->getNodeType();
+
+        if (what == ELEMENT_NODE)
+        {
+            traverse(static_cast<ElementImpl*>(child));
+        } else if (what == TEXT_NODE)
+        {
+            mXMLostream << *(static_cast<TextImpl*>(child)->getData()) << endl;
+        }
+
+        child = child->getNextSibling();
+    }
+
+    mXMLostream << "</" << *(root->getNodeName()) << ">" << endl;
+}
diff --git a/media/libdrm/mobile2/src/util/xml/ExpatWrapper.cpp b/media/libdrm/mobile2/src/util/xml/ExpatWrapper.cpp
new file mode 100644
index 0000000..fe99a88
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/xml/ExpatWrapper.cpp
@@ -0,0 +1,77 @@
+/*
+ * 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.
+ */

+#include <util/xml/ExpatWrapper.h>
+#include <ustring.h>
+using namespace ustl;
+
+/** see ExpatWrapper.h */
+ExpatWrapper::ExpatWrapper()
+{
+    mParser = XML_ParserCreate(NULL);
+    ::XML_SetUserData(mParser, this);
+    ::XML_SetElementHandler(mParser, startElementCallback, endElementCallback);
+    ::XML_SetCharacterDataHandler(mParser, dataHandlerCallback);
+
+}
+
+/** see ExpatWrapper.h */
+ExpatWrapper::~ExpatWrapper()
+{
+    if (mParser)
+    {
+        ::XML_ParserFree(mParser);
+    }
+}
+
+/** see ExpatWrapper.h */
+int ExpatWrapper::decode(const char* buf, int len, int isFinal)
+{
+    return ::XML_Parse(mParser, buf, len, isFinal);
+}
+
+/** see ExpatWrapper.h */
+void ExpatWrapper::startElementCallback(void *userData, const XML_Char *name,
+                                        const XML_Char **atts)
+{
+    ((ExpatWrapper *)userData)->startElement(name, atts);
+}
+
+/** see ExpatWrapper.h */
+void ExpatWrapper::endElementCallback(void *userData, const XML_Char *name)
+{
+    ((ExpatWrapper *)userData)->endElement(name);
+}
+
+/** see ExpatWrapper.h */
+void ExpatWrapper::dataHandlerCallback(void *userData, const XML_Char *s, int len)
+{
+    ((ExpatWrapper *)userData)->dataHandler(s, len);
+}
+
+/** see ExpatWrapper.h */
+void ExpatWrapper::startElement(const XML_Char *name, const XML_Char **atts)
+{
+}
+
+/** see ExpatWrapper.h */
+void ExpatWrapper::endElement(const XML_Char *name)
+{
+}
+
+/** see ExpatWrapper.h */
+void ExpatWrapper::dataHandler(const XML_Char *s, int len)
+{
+}
diff --git a/media/libdrm/mobile2/src/util/xml/XMLDocumentImpl.cpp b/media/libdrm/mobile2/src/util/xml/XMLDocumentImpl.cpp
new file mode 100644
index 0000000..c1fbc79
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/xml/XMLDocumentImpl.cpp
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */

+#include <util/xml/XMLDocumentImpl.h>
+#include <util/xml/XMLElementImpl.h>
+
+/** see XMLDocumentImpl.h */
+XMLDocumentImpl::XMLDocumentImpl()
+{}
+
+/** see XMLDocumentImpl.h */
+XMLDocumentImpl::~XMLDocumentImpl()
+{}
+
+/** see XMLDocumentImpl.h */
+ElementImpl* XMLDocumentImpl::getDocumentElement() const
+{
+    XMLElementImpl *element = (XMLElementImpl *)(this->getFirstChild());
+    return element;
+}
+
+/** see XMLDocumentImpl.h */
+ElementImpl* XMLDocumentImpl::createElement(const DOMString* tagName) const throw (DOMException)
+{
+    if (tagName)
+    {
+        XMLElementImpl *element = new XMLElementImpl(tagName);
+        return element;
+    }
+    return NULL;
+}
+
+/** see XMLDocumentImpl.h */
+TextImpl* XMLDocumentImpl::createTextNode(const DOMString* data) const
+{
+    if (data)
+    {
+        TextImpl *text = new TextImpl(data);
+        return text;
+    }
+    return NULL;
+}
+
diff --git a/media/libdrm/mobile2/src/util/xml/XMLElementImpl.cpp b/media/libdrm/mobile2/src/util/xml/XMLElementImpl.cpp
new file mode 100644
index 0000000..5453902
--- /dev/null
+++ b/media/libdrm/mobile2/src/util/xml/XMLElementImpl.cpp
@@ -0,0 +1,136 @@
+/*
+ * 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.
+ */

+#include <util/xml/XMLElementImpl.h>
+#include <util/domcore/TextImpl.h>
+
+/** see XMLElementImpl.h */
+XMLElementImpl::XMLElementImpl(const DOMString *tag)
+{
+    if (tag)
+    {
+        mTagName = *tag;
+    }
+}
+
+/** see XMLElementImpl.h */
+XMLElementImpl::~XMLElementImpl()
+{
+}
+
+/** see XMLElementImpl.h */
+const DOMString* XMLElementImpl::getTagName() const
+{
+    return &mTagName;
+}
+
+/** see XMLElementImpl.h */
+void XMLElementImpl::setAttribute(const DOMString* name, const DOMString* value)
+                                  throw (DOMException)
+{
+    if (name && value)
+    {
+        mAttributeMap[*name] = *value;
+    }
+}
+
+/** see XMLElementImpl.h */
+void XMLElementImpl::removeAttribute(const DOMString* name) throw (DOMException)
+{
+    if (name)
+    {
+       mAttributeMap.erase(*name);
+    }
+}
+
+/** see XMLElementImpl.h */
+const DOMString* XMLElementImpl::getAttribute(const DOMString* name) const
+{
+    if (name)
+    {
+        DOMStringMap::const_iterator pos = mAttributeMap.find(*name);
+
+        if (pos != mAttributeMap.end())
+        {
+           return &(pos->second);
+        }
+
+    }
+    return NULL;
+}
+
+/** see XMLElementImpl.h */
+bool XMLElementImpl::hasAttributes() const
+{
+    return !mAttributeMap.empty();
+}
+
+/** see XMLElementImpl.h */
+const DOMStringMap* XMLElementImpl::getAttributeMap() const
+{
+    return &mAttributeMap;
+}
+
+/** see XMLElementImpl.h */
+const NodeImpl* XMLElementImpl::findSoloChildNode(const char* tag) const
+{
+    if (NULL == tag)
+    {
+        return NULL;
+    }
+
+    string token;
+    NodeListImpl *nodeList = NULL;
+    const NodeImpl *childNode = NULL;
+
+    token.assign(tag);
+    nodeList = getElementsByTagName(&token);
+
+    if (nodeList->getLength() > 0)
+    {
+         childNode = nodeList->item(0);
+    }
+
+    return childNode;
+}
+
+/** see XMLElementImpl.h */
+const string* XMLElementImpl::getSoloText(const char* tag) const
+{
+    const NodeImpl *textNode = this->findSoloChildNode(tag);
+
+    if (textNode)
+    {
+        textNode = textNode->getFirstChild();
+        if (textNode)
+        {
+            return static_cast<const TextImpl*>(textNode)->getData();
+        }
+    }
+
+    return NULL;
+}
+
+/** see XMLElementImpl.h */
+const XMLElementImpl* XMLElementImpl::getSoloElement(const char* tag) const
+{
+    const NodeImpl *node = findSoloChildNode(tag);
+    if (node)
+    {
+        return static_cast<const XMLElementImpl*>(node);
+    }
+
+    return NULL;
+}
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk
new file mode 100644
index 0000000..8020da2
--- /dev/null
+++ b/media/libmedia/Android.mk
@@ -0,0 +1,39 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+	AudioTrack.cpp \
+	IAudioFlinger.cpp \
+	IAudioFlingerClient.cpp \
+	IAudioTrack.cpp \
+	IAudioRecord.cpp \
+	AudioRecord.cpp \
+	AudioSystem.cpp \
+	mediaplayer.cpp \
+	IMediaPlayerService.cpp \
+	IMediaPlayerClient.cpp \
+	IMediaPlayer.cpp \
+	IMediaRecorder.cpp \
+	mediarecorder.cpp \
+	IMediaMetadataRetriever.cpp \
+	mediametadataretriever.cpp \
+	ToneGenerator.cpp \
+	JetPlayer.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+	libui libcutils libutils libsonivox
+
+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..7594ff0
--- /dev/null
+++ b/media/libmedia/AudioRecord.cpp
@@ -0,0 +1,574 @@
+/*
+**
+** 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_NDEBUG 0
+#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 frameCount,
+        uint32_t flags,
+        callback_t cbf,
+        void* user,
+        int notificationFrames)
+    : mStatus(NO_INIT)
+{
+    mStatus = set(streamType, sampleRate, format, channelCount,
+            frameCount, flags, cbf, user, notificationFrames);
+}
+
+AudioRecord::~AudioRecord()
+{
+    if (mStatus == NO_ERROR) {
+        // Make sure that callback function exits in the case where
+        // it is looping on buffer empty condition in obtainBuffer().
+        // Otherwise the callback thread will never exit.
+        stop();
+        if (mClientRecordThread != 0) {
+            mCblk->cv.signal();
+            mClientRecordThread->requestExitAndWait();
+            mClientRecordThread.clear();
+        }
+        mAudioRecord.clear();
+        IPCThreadState::self()->flushCommands();
+    }
+}
+
+status_t AudioRecord::set(
+        int streamType,
+        uint32_t sampleRate,
+        int format,
+        int channelCount,
+        int frameCount,
+        uint32_t flags,
+        callback_t cbf,
+        void* user,
+        int notificationFrames,
+        bool threadCanCallJava)
+{
+
+    LOGV("set(): sampleRate %d, channelCount %d, frameCount %d",sampleRate, channelCount, frameCount);
+    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;
+    }
+
+    // validate parameters
+    if (format != AudioSystem::PCM_16_BIT) {
+        return BAD_VALUE;
+    }
+    if (channelCount != 1 && channelCount != 2) {
+        return BAD_VALUE;
+    }
+
+    // validate framecount
+    size_t inputBuffSizeInBytes = -1;
+    if (AudioSystem::getInputBufferSize(sampleRate, format, channelCount, &inputBuffSizeInBytes)
+            != NO_ERROR) {
+        LOGE("AudioSystem could not query the input buffer size.");
+        return NO_INIT;    
+    }
+    if (inputBuffSizeInBytes == 0) {
+        LOGE("Recording parameters are not supported: sampleRate %d, channelCount %d, format %d",
+            sampleRate, channelCount, format);
+        return BAD_VALUE;
+    }
+    int frameSizeInBytes = channelCount * (format == AudioSystem::PCM_16_BIT ? 2 : 1);
+
+    // We use 2* size of input buffer for ping pong use of record buffer.
+    int minFrameCount = 2 * inputBuffSizeInBytes / frameSizeInBytes;
+    LOGV("AudioRecord::set() minFrameCount = %d", minFrameCount);
+
+    if (frameCount == 0) {
+        frameCount = minFrameCount;
+    } else if (frameCount < minFrameCount) {
+        return BAD_VALUE;
+    }
+
+    if (notificationFrames == 0) {
+        notificationFrames = frameCount/2;
+    }
+
+    // open record channel
+    status_t status;
+    sp<IAudioRecord> record = audioFlinger->openRecord(getpid(), streamType,
+                                                       sampleRate, format,
+                                                       channelCount,
+                                                       frameCount,
+                                                       ((uint16_t)flags) << 16, 
+                                                       &status);
+    if (record == 0) {
+        LOGE("AudioFlinger could not create record track, status: %d", status);
+        return status;
+    }
+    sp<IMemory> cblk = record->getCblk();
+    if (cblk == 0) {
+        return NO_INIT;
+    }
+    if (cbf != 0) {
+        mClientRecordThread = new ClientRecordThread(*this, threadCanCallJava);
+        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);
+    mCblk->out = 0;
+    mSampleRate = sampleRate;
+    mFormat = format;
+    // Update buffer size in case it has been limited by AudioFlinger during track creation
+    mFrameCount = mCblk->frameCount;
+    mChannelCount = channelCount;
+    mActive = 0;
+    mCbf = cbf;
+    mNotificationFrames = notificationFrames;
+    mRemainingFrames = notificationFrames;
+    mUserData = user;
+    // TODO: add audio hardware input latency here
+    mLatency = (1000*mFrameCount) / mSampleRate;
+    mMarkerPosition = 0;
+    mNewPosition = 0;
+    mUpdatePeriod = 0;
+
+    return NO_ERROR;
+}
+
+status_t AudioRecord::initCheck() const
+{
+    return mStatus;
+}
+
+// -------------------------------------------------------------------------
+
+uint32_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;
+}
+
+uint32_t AudioRecord::frameCount() const
+{
+    return mFrameCount;
+}
+
+int AudioRecord::frameSize() const
+{
+    return channelCount()*((format() == AudioSystem::PCM_8_BIT) ? sizeof(uint8_t) : sizeof(int16_t));
+}
+
+// -------------------------------------------------------------------------
+
+status_t AudioRecord::start()
+{
+    status_t ret = NO_ERROR;
+    sp<ClientRecordThread> t = mClientRecordThread;
+
+    LOGV("start");
+
+    if (t != 0) {
+        if (t->exitPending()) {
+            if (t->requestExitAndWait() == WOULD_BLOCK) {
+                LOGE("AudioRecord::start called from thread");
+                return WOULD_BLOCK;
+            }
+        }
+        t->mLock.lock();
+     }
+
+    if (android_atomic_or(1, &mActive) == 0) {
+        mNewPosition = mCblk->user + mUpdatePeriod;
+        mCblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
+        mCblk->waitTimeMs = 0;
+        if (t != 0) {
+           t->run("ClientRecordThread", THREAD_PRIORITY_AUDIO_CLIENT);
+        } else {
+            setpriority(PRIO_PROCESS, 0, THREAD_PRIORITY_AUDIO_CLIENT);
+        }
+        ret = mAudioRecord->start();
+    }
+
+    if (t != 0) {
+        t->mLock.unlock();
+    }
+
+    return ret;
+}
+
+status_t AudioRecord::stop()
+{
+    sp<ClientRecordThread> t = mClientRecordThread;
+
+    LOGV("stop");
+
+    if (t != 0) {
+        t->mLock.lock();
+     }
+
+    if (android_atomic_and(~1, &mActive) == 1) {
+        mAudioRecord->stop();
+        if (t != 0) {
+            t->requestExit();
+        } else {
+            setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_NORMAL);
+        }
+    }
+
+    if (t != 0) {
+        t->mLock.unlock();
+    }
+
+    return NO_ERROR;
+}
+
+bool AudioRecord::stopped() const
+{
+    return !mActive;
+}
+
+status_t AudioRecord::setMarkerPosition(uint32_t marker)
+{
+    if (mCbf == 0) return INVALID_OPERATION;
+
+    mMarkerPosition = marker;
+
+    return NO_ERROR;
+}
+
+status_t AudioRecord::getMarkerPosition(uint32_t *marker)
+{
+    if (marker == 0) return BAD_VALUE;
+
+    *marker = mMarkerPosition;
+
+    return NO_ERROR;
+}
+
+status_t AudioRecord::setPositionUpdatePeriod(uint32_t updatePeriod)
+{
+    if (mCbf == 0) return INVALID_OPERATION;
+
+    uint32_t curPosition;
+    getPosition(&curPosition);
+    mNewPosition = curPosition + updatePeriod;
+    mUpdatePeriod = updatePeriod;
+
+    return NO_ERROR;
+}
+
+status_t AudioRecord::getPositionUpdatePeriod(uint32_t *updatePeriod)
+{
+    if (updatePeriod == 0) return BAD_VALUE;
+
+    *updatePeriod = mUpdatePeriod;
+
+    return NO_ERROR;
+}
+
+status_t AudioRecord::getPosition(uint32_t *position)
+{
+    if (position == 0) return BAD_VALUE;
+
+    *position = mCblk->user;
+
+    return NO_ERROR;
+}
+
+
+// -------------------------------------------------------------------------
+
+status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
+{
+    int active;
+    int timeout = 0;
+    status_t result;
+    audio_track_cblk_t* cblk = mCblk;
+    uint32_t framesReq = audioBuffer->frameCount;
+
+    audioBuffer->frameCount  = 0;
+    audioBuffer->size        = 0;
+
+    uint32_t framesReady = cblk->framesReady();
+
+    if (framesReady == 0) {
+        Mutex::Autolock _l(cblk->lock);
+        goto start_loop_here;
+        while (framesReady == 0) {
+            active = mActive;
+            if (UNLIKELY(!active))
+                return NO_MORE_BUFFERS;
+            if (UNLIKELY(!waitCount))
+                return WOULD_BLOCK;
+            timeout = 0;
+            result = cblk->cv.waitRelative(cblk->lock, milliseconds(WAIT_PERIOD_MS));
+            if (__builtin_expect(result!=NO_ERROR, false)) {
+                cblk->waitTimeMs += WAIT_PERIOD_MS;
+                if (cblk->waitTimeMs >= cblk->bufferTimeoutMs) {
+                    LOGW(   "obtainBuffer timed out (is the CPU pegged?) "
+                            "user=%08x, server=%08x", cblk->user, cblk->server);
+                    timeout = 1;
+                    cblk->waitTimeMs = 0;
+                }
+                if (--waitCount == 0) {
+                    return TIMED_OUT;
+                }
+            }
+            // read the server count again
+        start_loop_here:
+            framesReady = cblk->framesReady();
+        }
+    }
+
+    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)", cblk->user, cblk->server);
+
+    cblk->waitTimeMs = 0;
+    
+    if (framesReq > framesReady) {
+        framesReq = framesReady;
+    }
+
+    uint32_t u = cblk->user;
+    uint32_t bufferEnd = cblk->userBase + cblk->frameCount;
+
+    if (u + framesReq > bufferEnd) {
+        framesReq = bufferEnd - u;
+    }
+
+    audioBuffer->flags       = 0;
+    audioBuffer->channelCount= mChannelCount;
+    audioBuffer->format      = mFormat;
+    audioBuffer->frameCount  = framesReq;
+    audioBuffer->size        = framesReq*mChannelCount*sizeof(int16_t);
+    audioBuffer->raw         = (int8_t*)cblk->buffer(u);
+    active = mActive;
+    return active ? status_t(NO_ERROR) : status_t(STOPPED);
+}
+
+void AudioRecord::releaseBuffer(Buffer* audioBuffer)
+{
+    audio_track_cblk_t* cblk = mCblk;
+    cblk->stepUser(audioBuffer->frameCount);
+}
+
+// -------------------------------------------------------------------------
+
+ssize_t AudioRecord::read(void* buffer, size_t userSize)
+{
+    ssize_t read = 0;
+    Buffer audioBuffer;
+    int8_t *dst = static_cast<int8_t*>(buffer);
+
+    if (ssize_t(userSize) < 0) {
+        // sanity-check. user is most-likely passing an error code.
+        LOGE("AudioRecord::read(buffer=%p, size=%u (%d)",
+                buffer, userSize, userSize);
+        return BAD_VALUE;
+    }
+
+    LOGV("read size: %d", userSize);
+
+    do {
+
+        audioBuffer.frameCount = userSize/mChannelCount/sizeof(int16_t);
+
+        // Calling obtainBuffer() with a negative wait count causes
+        // an (almost) infinite wait time.
+        status_t err = obtainBuffer(&audioBuffer, -1);
+        if (err < 0) {
+            // out of buffers, return #bytes written
+            if (err == status_t(NO_MORE_BUFFERS))
+                break;
+            return ssize_t(err);
+        }
+
+        size_t bytesRead = audioBuffer.size;
+        memcpy(dst, audioBuffer.i8, bytesRead);
+
+        dst += bytesRead;
+        userSize -= bytesRead;
+        read += bytesRead;
+
+        releaseBuffer(&audioBuffer);
+    } while (userSize);
+
+    return read;
+}
+
+// -------------------------------------------------------------------------
+
+bool AudioRecord::processAudioBuffer(const sp<ClientRecordThread>& thread)
+{
+    Buffer audioBuffer;
+    uint32_t frames = mRemainingFrames;
+    size_t readSize;
+
+    // Manage marker callback
+    if (mMarkerPosition > 0) {
+        if (mCblk->user >= mMarkerPosition) {
+            mCbf(EVENT_MARKER, mUserData, (void *)&mMarkerPosition);
+            mMarkerPosition = 0;
+        }
+    }
+
+    // Manage new position callback
+    if (mUpdatePeriod > 0) {
+        while (mCblk->user >= mNewPosition) {
+            mCbf(EVENT_NEW_POS, mUserData, (void *)&mNewPosition);
+            mNewPosition += mUpdatePeriod;
+        }
+    }
+
+    do {
+        audioBuffer.frameCount = frames;
+        // Calling obtainBuffer() with a wait count of 1 
+        // limits wait time to WAIT_PERIOD_MS. This prevents from being 
+        // stuck here not being able to handle timed events (position, markers).
+        status_t err = obtainBuffer(&audioBuffer, 1);
+        if (err < NO_ERROR) {
+            if (err != TIMED_OUT) {
+                LOGE("Error obtaining an audio buffer, giving up.");
+                return false;
+            }
+            break;
+        }
+        if (err == status_t(STOPPED)) return false;
+
+        size_t reqSize = audioBuffer.size;
+        mCbf(EVENT_MORE_DATA, mUserData, &audioBuffer);
+        readSize = audioBuffer.size;
+
+        // Sanity check on returned size
+        if (ssize_t(readSize) <= 0) break;
+        if (readSize > reqSize) readSize = reqSize;
+
+        audioBuffer.size = readSize;
+        audioBuffer.frameCount = readSize/mChannelCount/sizeof(int16_t);
+        frames -= audioBuffer.frameCount;
+
+        releaseBuffer(&audioBuffer);
+
+    } while (frames);
+
+    
+    // Manage overrun callback
+    if (mActive && (mCblk->framesAvailable_l() == 0)) {
+        LOGV("Overrun user: %x, server: %x, flowControlFlag %d", mCblk->user, mCblk->server, mCblk->flowControlFlag);
+        if (mCblk->flowControlFlag == 0) {
+            mCbf(EVENT_OVERRUN, mUserData, 0);
+            mCblk->flowControlFlag = 1;
+        }
+    }
+
+    if (frames == 0) {
+        mRemainingFrames = mNotificationFrames;
+    } else {
+        mRemainingFrames = frames;
+    }
+    return true;
+}
+
+// =========================================================================
+
+AudioRecord::ClientRecordThread::ClientRecordThread(AudioRecord& receiver, bool bCanCallJava)
+    : Thread(bCanCallJava), 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..63dfc3b
--- /dev/null
+++ b/media/libmedia/AudioSystem.cpp
@@ -0,0 +1,383 @@
+/*
+ * 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"
+//#define LOG_NDEBUG 0
+
+#include <utils/Log.h>
+#include <utils/IServiceManager.h>
+#include <media/AudioSystem.h>
+#include <math.h>
+
+namespace android {
+
+// client singleton for AudioFlinger binder interface
+Mutex AudioSystem::gLock;
+sp<IAudioFlinger> AudioSystem::gAudioFlinger;
+sp<AudioSystem::AudioFlingerClient> AudioSystem::gAudioFlingerClient;
+audio_error_callback AudioSystem::gAudioErrorCallback = NULL;
+// Cached values
+int AudioSystem::gOutSamplingRate[NUM_AUDIO_OUTPUT_TYPES];
+int AudioSystem::gOutFrameCount[NUM_AUDIO_OUTPUT_TYPES];
+uint32_t AudioSystem::gOutLatency[NUM_AUDIO_OUTPUT_TYPES];
+bool AudioSystem::gA2dpEnabled;
+// Cached values for recording queries
+uint32_t AudioSystem::gPrevInSamplingRate = 16000;
+int AudioSystem::gPrevInFormat = AudioSystem::PCM_16_BIT;
+int AudioSystem::gPrevInChannelCount = 1;
+size_t AudioSystem::gInBuffSize = 0;
+
+
+// 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 (gAudioFlingerClient == NULL) {
+            gAudioFlingerClient = new AudioFlingerClient();
+        } else {
+            if (gAudioErrorCallback) {
+                gAudioErrorCallback(NO_ERROR);
+            }
+         }
+        binder->linkToDeath(gAudioFlingerClient);
+        gAudioFlinger = interface_cast<IAudioFlinger>(binder);
+        gAudioFlinger->registerClient(gAudioFlingerClient);
+        // Cache frequently accessed parameters 
+        for (int output = 0; output < NUM_AUDIO_OUTPUT_TYPES; output++) {
+            gOutFrameCount[output] = (int)gAudioFlinger->frameCount(output);
+            gOutSamplingRate[output] = (int)gAudioFlinger->sampleRate(output);
+            gOutLatency[output] = gAudioFlinger->latency(output);
+        }
+        gA2dpEnabled = gAudioFlinger->isA2dpEnabled();
+    }
+    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_SCO;
+    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_SCO);
+    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) >= 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) >= 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) >= 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) >= 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;
+}
+
+status_t AudioSystem::getOutputSamplingRate(int* samplingRate, int streamType)
+{
+    int output = getOutput(streamType);
+
+    if (gOutSamplingRate[output] == 0) {
+        const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+        if (af == 0) return PERMISSION_DENIED;
+        // gOutSamplingRate is updated by get_audio_flinger()
+    }
+    LOGV("getOutputSamplingRate() streamType %d, output %d, sampling rate %d", streamType, output, gOutSamplingRate[output]);
+    *samplingRate = gOutSamplingRate[output];
+    
+    return NO_ERROR;
+}
+
+status_t AudioSystem::getOutputFrameCount(int* frameCount, int streamType)
+{
+    int output = getOutput(streamType);
+
+    if (gOutFrameCount[output] == 0) {
+        const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+        if (af == 0) return PERMISSION_DENIED;
+        // gOutFrameCount is updated by get_audio_flinger()
+    }
+    LOGV("getOutputFrameCount() streamType %d, output %d, frame count %d", streamType, output, gOutFrameCount[output]);
+
+    *frameCount = gOutFrameCount[output];
+    return NO_ERROR;
+}
+
+status_t AudioSystem::getOutputLatency(uint32_t* latency, int streamType)
+{
+    int output = getOutput(streamType);
+
+    if (gOutLatency[output] == 0) {
+        const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+        if (af == 0) return PERMISSION_DENIED;
+        // gOutLatency is updated by get_audio_flinger()
+    }
+    LOGV("getOutputLatency() streamType %d, output %d, latency %d", streamType, output, gOutLatency[output]);
+
+    *latency = gOutLatency[output];
+    
+    return NO_ERROR;
+}
+
+status_t AudioSystem::getInputBufferSize(uint32_t sampleRate, int format, int channelCount, 
+    size_t* buffSize)
+{
+    // Do we have a stale gInBufferSize or are we requesting the input buffer size for new values
+    if ((gInBuffSize == 0) || (sampleRate != gPrevInSamplingRate) || (format != gPrevInFormat) 
+        || (channelCount != gPrevInChannelCount)) {
+        // save the request params
+        gPrevInSamplingRate = sampleRate;
+        gPrevInFormat = format; 
+        gPrevInChannelCount = channelCount;
+
+        gInBuffSize = 0;
+        const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+        if (af == 0) {
+            return PERMISSION_DENIED;
+        }
+        gInBuffSize = af->getInputBufferSize(sampleRate, format, channelCount);
+    } 
+    *buffSize = gInBuffSize;
+    
+    return NO_ERROR;
+}
+
+// ---------------------------------------------------------------------------
+
+void AudioSystem::AudioFlingerClient::binderDied(const wp<IBinder>& who) {   
+    Mutex::Autolock _l(AudioSystem::gLock);
+    AudioSystem::gAudioFlinger.clear();
+
+    for (int output = 0; output < NUM_AUDIO_OUTPUT_TYPES; output++) {
+        gOutFrameCount[output] = 0;
+        gOutSamplingRate[output] = 0;
+        gOutLatency[output] = 0;
+    }
+    AudioSystem::gInBuffSize = 0;
+
+    if (gAudioErrorCallback) {
+        gAudioErrorCallback(DEAD_OBJECT);
+    }
+    LOGW("AudioFlinger server died!");
+}
+
+void AudioSystem::AudioFlingerClient::a2dpEnabledChanged(bool enabled) {
+    gA2dpEnabled = enabled;        
+    LOGV("AudioFlinger A2DP enabled status changed! %d", enabled);
+}
+
+void AudioSystem::setErrorCallback(audio_error_callback cb) {
+    Mutex::Autolock _l(AudioSystem::gLock);
+    gAudioErrorCallback = cb;
+}
+
+int AudioSystem::getOutput(int streamType)
+{  
+    if (streamType == DEFAULT) {
+        streamType = MUSIC;
+    }
+    if (gA2dpEnabled && routedToA2dpOutput(streamType)) {
+        return AUDIO_OUTPUT_A2DP;
+    } else {
+        return AUDIO_OUTPUT_HARDWARE;
+    }
+}
+
+bool AudioSystem::routedToA2dpOutput(int streamType) {
+    switch(streamType) {
+    case MUSIC:
+    case VOICE_CALL:
+    case BLUETOOTH_SCO:
+    case SYSTEM:
+        return true;
+    default:
+        return false;
+    }
+}
+
+
+
+}; // namespace android
+
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
new file mode 100644
index 0000000..e79f336
--- /dev/null
+++ b/media/libmedia/AudioTrack.cpp
@@ -0,0 +1,1021 @@
+/* //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 <limits.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 {
+
+// ---------------------------------------------------------------------------
+
+AudioTrack::AudioTrack()
+    : mStatus(NO_INIT)
+{
+}
+
+AudioTrack::AudioTrack(
+        int streamType,
+        uint32_t sampleRate,
+        int format,
+        int channelCount,
+        int frameCount,
+        uint32_t flags,
+        callback_t cbf,
+        void* user,
+        int notificationFrames)
+    : mStatus(NO_INIT)
+{
+    mStatus = set(streamType, sampleRate, format, channelCount,
+            frameCount, flags, cbf, user, notificationFrames, 0);
+}
+
+AudioTrack::AudioTrack(
+        int streamType,
+        uint32_t sampleRate,
+        int format,
+        int channelCount,
+        const sp<IMemory>& sharedBuffer,
+        uint32_t flags,
+        callback_t cbf,
+        void* user,
+        int notificationFrames)
+    : mStatus(NO_INIT)
+{
+    mStatus = set(streamType, sampleRate, format, channelCount,
+            0, flags, cbf, user, notificationFrames, sharedBuffer);
+}
+
+AudioTrack::~AudioTrack()
+{
+    LOGV_IF(mSharedBuffer != 0, "Destructor sharedBuffer: %p", mSharedBuffer->pointer());
+
+    if (mStatus == NO_ERROR) {
+        // Make sure that callback function exits in the case where
+        // it is looping on buffer full condition in obtainBuffer().
+        // Otherwise the callback thread will never exit.
+        stop();
+        if (mAudioTrackThread != 0) {
+            mCblk->cv.signal();
+            mAudioTrackThread->requestExitAndWait();
+            mAudioTrackThread.clear();
+        }
+        mAudioTrack.clear();
+        IPCThreadState::self()->flushCommands();
+    }
+}
+
+status_t AudioTrack::set(
+        int streamType,
+        uint32_t sampleRate,
+        int format,
+        int channelCount,
+        int frameCount,
+        uint32_t flags,
+        callback_t cbf,
+        void* user,
+        int notificationFrames,
+        const sp<IMemory>& sharedBuffer,
+        bool threadCanCallJava)
+{
+
+    LOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %d", sharedBuffer->pointer(), sharedBuffer->size());
+
+    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;
+    }
+    int afSampleRate;
+    if (AudioSystem::getOutputSamplingRate(&afSampleRate, streamType) != NO_ERROR) {
+        return NO_INIT;
+    }
+    int afFrameCount;
+    if (AudioSystem::getOutputFrameCount(&afFrameCount, streamType) != NO_ERROR) {
+        return NO_INIT;
+    }
+    uint32_t afLatency;
+    if (AudioSystem::getOutputLatency(&afLatency, streamType) != NO_ERROR) {
+        return NO_INIT;
+    }
+
+    // handle default values first.
+    if (streamType == AudioSystem::DEFAULT) {
+        streamType = AudioSystem::MUSIC;
+    }
+    if (sampleRate == 0) {
+        sampleRate = afSampleRate;
+    }
+    // these below should probably come from the audioFlinger too...
+    if (format == 0) {
+        format = AudioSystem::PCM_16_BIT;
+    }
+    if (channelCount == 0) {
+        channelCount = 2;
+    }
+
+    // validate parameters
+    if (((format != AudioSystem::PCM_8_BIT) || sharedBuffer != 0) &&
+        (format != AudioSystem::PCM_16_BIT)) {
+        LOGE("Invalid format");
+        return BAD_VALUE;
+    }
+    if (channelCount != 1 && channelCount != 2) {
+        LOGE("Invalid channel number");
+        return BAD_VALUE;
+    }
+
+    // Ensure that buffer depth covers at least audio hardware latency
+    uint32_t minBufCount = afLatency / ((1000 * afFrameCount)/afSampleRate);
+    if (minBufCount < 2) minBufCount = 2;
+
+    // When playing from shared buffer, playback will start even if last audioflinger
+    // block is partly filled.
+    if (sharedBuffer != 0 && minBufCount > 1) {
+        minBufCount--;
+    }
+
+    int minFrameCount = (afFrameCount*sampleRate*minBufCount)/afSampleRate;
+
+    if (sharedBuffer == 0) {
+        if (frameCount == 0) {
+            frameCount = minFrameCount;
+        }
+        if (notificationFrames == 0) {
+            notificationFrames = frameCount/2;
+        }
+        // Make sure that application is notified with sufficient margin
+        // before underrun
+        if (notificationFrames > frameCount/2) {
+            notificationFrames = frameCount/2;
+        }
+    } else {
+        // Ensure that buffer alignment matches channelcount
+        if (((uint32_t)sharedBuffer->pointer() & (channelCount | 1)) != 0) {
+            LOGE("Invalid buffer alignement: address %p, channelCount %d", sharedBuffer->pointer(), channelCount);
+            return BAD_VALUE;
+        }
+        frameCount = sharedBuffer->size()/channelCount/sizeof(int16_t);
+    }
+
+    if (frameCount < minFrameCount) {
+      LOGE("Invalid buffer size: minFrameCount %d, frameCount %d", minFrameCount, frameCount);
+      return BAD_VALUE;
+    }
+
+    // create the track
+    status_t status;
+    sp<IAudioTrack> track = audioFlinger->createTrack(getpid(),
+                streamType, sampleRate, format, channelCount, frameCount, flags, sharedBuffer, &status);
+
+    if (track == 0) {
+        LOGE("AudioFlinger could not create track, status: %d", status);
+        return status;
+    }
+    sp<IMemory> cblk = track->getCblk();
+    if (cblk == 0) {
+        LOGE("Could not get control block");
+        return NO_INIT;
+    }
+    if (cbf != 0) {
+        mAudioTrackThread = new AudioTrackThread(*this, threadCanCallJava);
+        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->out = 1;
+    // Update buffer size in case it has been limited by AudioFlinger during track creation
+    mFrameCount = mCblk->frameCount;
+    if (sharedBuffer == 0) {
+        mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
+    } else {
+        mCblk->buffers = sharedBuffer->pointer();
+         // Force buffer full condition as data is already present in shared memory
+        mCblk->stepUser(mFrameCount);
+    }
+    mCblk->volume[0] = mCblk->volume[1] = 0x1000;
+    mVolume[LEFT] = 1.0f;
+    mVolume[RIGHT] = 1.0f;
+    mSampleRate = sampleRate;
+    mStreamType = streamType;
+    mFormat = format;
+    mChannelCount = channelCount;
+    mSharedBuffer = sharedBuffer;
+    mMuted = false;
+    mActive = 0;
+    mCbf = cbf;
+    mNotificationFrames = notificationFrames;
+    mRemainingFrames = notificationFrames;
+    mUserData = user;
+    mLatency = afLatency + (1000*mFrameCount) / mSampleRate;
+    mLoopCount = 0;
+    mMarkerPosition = 0;
+    mNewPosition = 0;
+    mUpdatePeriod = 0;
+
+    return NO_ERROR;
+}
+
+status_t AudioTrack::initCheck() const
+{
+    return mStatus;
+}
+
+// -------------------------------------------------------------------------
+
+uint32_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;
+}
+
+uint32_t AudioTrack::frameCount() const
+{
+    return mFrameCount;
+}
+
+int AudioTrack::frameSize() const
+{
+    return channelCount()*((format() == AudioSystem::PCM_8_BIT) ? sizeof(uint8_t) : sizeof(int16_t));
+}
+
+sp<IMemory>& AudioTrack::sharedBuffer()
+{
+    return mSharedBuffer;
+}
+
+// -------------------------------------------------------------------------
+
+void AudioTrack::start()
+{
+    sp<AudioTrackThread> t = mAudioTrackThread;
+
+    LOGV("start %p", this);
+    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) {
+        mNewPosition = mCblk->server + mUpdatePeriod;
+        mCblk->bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS;
+        mCblk->waitTimeMs = 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 %p", this);
+    if (t != 0) {
+        t->mLock.lock();
+    }
+
+    if (android_atomic_and(~1, &mActive) == 1) {
+        mAudioTrack->stop();
+        // Cancel loops (If we are in the middle of a loop, playback
+        // would not stop until loopCount reaches 0).
+        setLoop(0, 0, 0);
+        // Force flush if a shared buffer is used otherwise audioflinger
+        // will not stop before end of buffer is reached.
+        if (mSharedBuffer != 0) {
+            flush();
+        }
+        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)
+{
+    int afSamplingRate;
+
+    if (AudioSystem::getOutputSamplingRate(&afSamplingRate, mStreamType) != NO_ERROR) {
+        return;
+    }
+    // Resampler implementation limits input sampling rate to 2 x output sampling rate.
+    if (rate <= 0) rate = 1;
+    if (rate > afSamplingRate*2) rate = afSamplingRate*2;
+    if (rate > MAX_SAMPLE_RATE) rate = MAX_SAMPLE_RATE;
+
+    mCblk->sampleRate = rate;
+}
+
+uint32_t AudioTrack::getSampleRate()
+{
+    return uint32_t(mCblk->sampleRate);
+}
+
+status_t AudioTrack::setLoop(uint32_t loopStart, uint32_t loopEnd, int loopCount)
+{
+    audio_track_cblk_t* cblk = mCblk;
+
+
+    Mutex::Autolock _l(cblk->lock);
+
+    if (loopCount == 0) {
+        cblk->loopStart = UINT_MAX;
+        cblk->loopEnd = UINT_MAX;
+        cblk->loopCount = 0;
+        mLoopCount = 0;
+        return NO_ERROR;
+    }
+
+    if (loopStart >= loopEnd ||
+        loopEnd - loopStart > mFrameCount) {
+        LOGE("setLoop invalid value: loopStart %d, loopEnd %d, loopCount %d, framecount %d, user %d", loopStart, loopEnd, loopCount, mFrameCount, cblk->user);
+        return BAD_VALUE;
+    }
+
+    if ((mSharedBuffer != 0) && (loopEnd   > mFrameCount)) {
+        LOGE("setLoop invalid value: loop markers beyond data: loopStart %d, loopEnd %d, framecount %d",
+            loopStart, loopEnd, mFrameCount);
+        return BAD_VALUE;
+    }   
+
+    cblk->loopStart = loopStart;
+    cblk->loopEnd = loopEnd;
+    cblk->loopCount = loopCount;
+    mLoopCount = loopCount;
+
+    return NO_ERROR;
+}
+
+status_t AudioTrack::getLoop(uint32_t *loopStart, uint32_t *loopEnd, int *loopCount)
+{
+    if (loopStart != 0) {
+        *loopStart = mCblk->loopStart;
+    }
+    if (loopEnd != 0) {
+        *loopEnd = mCblk->loopEnd;
+    }
+    if (loopCount != 0) {
+        if (mCblk->loopCount < 0) {
+            *loopCount = -1;
+        } else {
+            *loopCount = mCblk->loopCount;
+        }
+    }
+
+    return NO_ERROR;
+}
+
+status_t AudioTrack::setMarkerPosition(uint32_t marker)
+{
+    if (mCbf == 0) return INVALID_OPERATION;
+
+    mMarkerPosition = marker;
+
+    return NO_ERROR;
+}
+
+status_t AudioTrack::getMarkerPosition(uint32_t *marker)
+{
+    if (marker == 0) return BAD_VALUE;
+
+    *marker = mMarkerPosition;
+
+    return NO_ERROR;
+}
+
+status_t AudioTrack::setPositionUpdatePeriod(uint32_t updatePeriod)
+{
+    if (mCbf == 0) return INVALID_OPERATION;
+
+    uint32_t curPosition;
+    getPosition(&curPosition);
+    mNewPosition = curPosition + updatePeriod;
+    mUpdatePeriod = updatePeriod;
+
+    return NO_ERROR;
+}
+
+status_t AudioTrack::getPositionUpdatePeriod(uint32_t *updatePeriod)
+{
+    if (updatePeriod == 0) return BAD_VALUE;
+
+    *updatePeriod = mUpdatePeriod;
+
+    return NO_ERROR;
+}
+
+status_t AudioTrack::setPosition(uint32_t position)
+{
+    Mutex::Autolock _l(mCblk->lock);
+
+    if (!stopped()) return INVALID_OPERATION;
+
+    if (position > mCblk->user) return BAD_VALUE;
+
+    mCblk->server = position;
+    mCblk->forceReady = 1;
+    
+    return NO_ERROR;
+}
+
+status_t AudioTrack::getPosition(uint32_t *position)
+{
+    if (position == 0) return BAD_VALUE;
+
+    *position = mCblk->server;
+
+    return NO_ERROR;
+}
+
+status_t AudioTrack::reload()
+{
+    if (!stopped()) return INVALID_OPERATION;
+    
+    flush();
+
+    mCblk->stepUser(mFrameCount);
+
+    return NO_ERROR;
+}
+
+// -------------------------------------------------------------------------
+
+status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
+{
+    int active;
+    int timeout = 0;
+    status_t result;
+    audio_track_cblk_t* cblk = mCblk;
+    uint32_t framesReq = audioBuffer->frameCount;
+
+    audioBuffer->frameCount  = 0;
+    audioBuffer->size = 0;
+
+    uint32_t framesAvail = cblk->framesAvailable();
+
+    if (framesAvail == 0) {
+        Mutex::Autolock _l(cblk->lock);
+        goto start_loop_here;
+        while (framesAvail == 0) {
+            active = mActive;
+            if (UNLIKELY(!active)) {
+                LOGV("Not active and NO_MORE_BUFFERS");
+                return NO_MORE_BUFFERS;
+            }
+            if (UNLIKELY(!waitCount))
+                return WOULD_BLOCK;
+            timeout = 0;
+            result = cblk->cv.waitRelative(cblk->lock, milliseconds(WAIT_PERIOD_MS));
+            if (__builtin_expect(result!=NO_ERROR, false)) { 
+                cblk->waitTimeMs += WAIT_PERIOD_MS;
+                if (cblk->waitTimeMs >= cblk->bufferTimeoutMs) {
+                    // timing out when a loop has been set and we have already written upto loop end
+                    // is a normal condition: no need to wake AudioFlinger up.
+                    if (cblk->user < cblk->loopEnd) {
+                        LOGW(   "obtainBuffer timed out (is the CPU pegged?) %p "
+                                "user=%08x, server=%08x", this, cblk->user, cblk->server);
+                        //unlock cblk mutex before calling mAudioTrack->start() (see issue #1617140) 
+                        cblk->lock.unlock();
+                        mAudioTrack->start();
+                        cblk->lock.lock();
+                        timeout = 1;
+                    }
+                    cblk->waitTimeMs = 0;
+                }
+                
+                if (--waitCount == 0) {
+                    return TIMED_OUT;
+                }
+            }
+            // read the server count again
+        start_loop_here:
+            framesAvail = cblk->framesAvailable_l();
+        }
+    }
+
+    cblk->waitTimeMs = 0;
+    
+    if (framesReq > framesAvail) {
+        framesReq = framesAvail;
+    }
+
+    uint32_t u = cblk->user;
+    uint32_t bufferEnd = cblk->userBase + cblk->frameCount;
+
+    if (u + framesReq > bufferEnd) {
+        framesReq = bufferEnd - u;
+    }
+
+    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)", cblk->user, cblk->server);
+
+    audioBuffer->flags       = mMuted ? Buffer::MUTE : 0;
+    audioBuffer->channelCount= mChannelCount;
+    audioBuffer->format      = AudioSystem::PCM_16_BIT;
+    audioBuffer->frameCount  = framesReq;
+    audioBuffer->size = framesReq*mChannelCount*sizeof(int16_t);
+    audioBuffer->raw         = (int8_t *)cblk->buffer(u);
+    active = mActive;
+    return active ? status_t(NO_ERROR) : status_t(STOPPED);
+}
+
+void AudioTrack::releaseBuffer(Buffer* audioBuffer)
+{
+    audio_track_cblk_t* cblk = mCblk;
+    cblk->stepUser(audioBuffer->frameCount);
+}
+
+// -------------------------------------------------------------------------
+
+ssize_t AudioTrack::write(const void* buffer, size_t userSize)
+{
+
+    if (mSharedBuffer != 0) return INVALID_OPERATION;
+
+    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 %p: %d bytes, mActive=%d", this, userSize, mActive);
+
+    ssize_t written = 0;
+    const int8_t *src = (const int8_t *)buffer;
+    Buffer audioBuffer;
+
+    do {
+        audioBuffer.frameCount = userSize/mChannelCount;
+        if (mFormat == AudioSystem::PCM_16_BIT) {
+            audioBuffer.frameCount >>= 1;
+        }
+        // Calling obtainBuffer() with a negative wait count causes
+        // an (almost) infinite wait time.
+        status_t err = obtainBuffer(&audioBuffer, -1);
+        if (err < 0) {
+            // out of buffers, return #bytes written
+            if (err == status_t(NO_MORE_BUFFERS))
+                break;
+            return ssize_t(err);
+        }
+
+        size_t toWrite;
+        if (mFormat == AudioSystem::PCM_8_BIT) {
+            // Divide capacity by 2 to take expansion into account
+            toWrite = audioBuffer.size>>1;
+            // 8 to 16 bit conversion
+            int count = toWrite;
+            int16_t *dst = (int16_t *)(audioBuffer.i8);
+            while(count--) {
+                *dst++ = (int16_t)(*src++^0x80) << 8;
+            }
+        }else {
+            toWrite = audioBuffer.size;
+            memcpy(audioBuffer.i8, src, toWrite);
+            src += toWrite;
+        }
+        userSize -= toWrite;
+        written += toWrite;
+
+        releaseBuffer(&audioBuffer);
+    } while (userSize);
+
+    return written;
+}
+
+// -------------------------------------------------------------------------
+
+bool AudioTrack::processAudioBuffer(const sp<AudioTrackThread>& thread)
+{
+    Buffer audioBuffer;
+    uint32_t frames;
+    size_t writtenSize;
+
+    // Manage underrun callback
+    if (mActive && (mCblk->framesReady() == 0)) {
+        LOGV("Underrun user: %x, server: %x, flowControlFlag %d", mCblk->user, mCblk->server, mCblk->flowControlFlag);
+        if (mCblk->flowControlFlag == 0) {
+            mCbf(EVENT_UNDERRUN, mUserData, 0);
+            if (mCblk->server == mCblk->frameCount) {
+                mCbf(EVENT_BUFFER_END, mUserData, 0);                
+            }
+            mCblk->flowControlFlag = 1;
+            if (mSharedBuffer != 0) return false;
+        }
+    }
+    
+    // Manage loop end callback
+    while (mLoopCount > mCblk->loopCount) {
+        int loopCount = -1;
+        mLoopCount--;
+        if (mLoopCount >= 0) loopCount = mLoopCount;
+
+        mCbf(EVENT_LOOP_END, mUserData, (void *)&loopCount);
+    }
+
+    // Manage marker callback
+    if(mMarkerPosition > 0) {
+        if (mCblk->server >= mMarkerPosition) {
+            mCbf(EVENT_MARKER, mUserData, (void *)&mMarkerPosition);
+            mMarkerPosition = 0;
+        }
+    }
+
+    // Manage new position callback
+    if(mUpdatePeriod > 0) {
+        while (mCblk->server >= mNewPosition) {
+            mCbf(EVENT_NEW_POS, mUserData, (void *)&mNewPosition);
+            mNewPosition += mUpdatePeriod;
+        }
+    }
+
+    // If Shared buffer is used, no data is requested from client.
+    if (mSharedBuffer != 0) {
+        frames = 0;
+    } else {
+        frames = mRemainingFrames;
+    }
+
+    do {
+
+        audioBuffer.frameCount = frames;
+        
+        // Calling obtainBuffer() with a wait count of 1 
+        // limits wait time to WAIT_PERIOD_MS. This prevents from being 
+        // stuck here not being able to handle timed events (position, markers, loops). 
+        status_t err = obtainBuffer(&audioBuffer, 1);
+        if (err < NO_ERROR) {
+            if (err != TIMED_OUT) {
+                LOGE("Error obtaining an audio buffer, giving up.");
+                return false;
+            }
+            break;
+        }
+        if (err == status_t(STOPPED)) return false;
+
+        // Divide buffer size by 2 to take into account the expansion
+        // due to 8 to 16 bit conversion: the callback must fill only half
+        // of the destination buffer
+        if (mFormat == AudioSystem::PCM_8_BIT) {
+            audioBuffer.size >>= 1;
+        }
+
+        size_t reqSize = audioBuffer.size;
+        mCbf(EVENT_MORE_DATA, mUserData, &audioBuffer);
+        writtenSize = audioBuffer.size;
+
+        // Sanity check on returned size
+        if (ssize_t(writtenSize) <= 0) break;
+        if (writtenSize > reqSize) writtenSize = reqSize;
+
+        if (mFormat == AudioSystem::PCM_8_BIT) {
+            // 8 to 16 bit conversion
+            const int8_t *src = audioBuffer.i8 + writtenSize-1;
+            int count = writtenSize;
+            int16_t *dst = audioBuffer.i16 + writtenSize-1;
+            while(count--) {
+                *dst-- = (int16_t)(*src--^0x80) << 8;
+            }
+            writtenSize <<= 1;
+        }
+
+        audioBuffer.size = writtenSize;
+        audioBuffer.frameCount = writtenSize/mChannelCount/sizeof(int16_t);
+        frames -= audioBuffer.frameCount;
+
+        releaseBuffer(&audioBuffer);
+    }
+    while (frames);
+
+    if (frames == 0) {
+        mRemainingFrames = mNotificationFrames;
+    } else {
+        mRemainingFrames = frames;
+    }
+    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)\n", mFormat, mChannelCount, mFrameCount);
+    result.append(buffer);
+    snprintf(buffer, 255, "  sample rate(%d), status(%d), muted(%d)\n", mSampleRate, mStatus, mMuted);
+    result.append(buffer);
+    snprintf(buffer, 255, "  active(%d), latency (%d)\n", mActive, mLatency);
+    result.append(buffer);
+    ::write(fd, result.string(), result.size());
+    return NO_ERROR;
+}
+
+// =========================================================================
+
+AudioTrack::AudioTrackThread::AudioTrackThread(AudioTrack& receiver, bool bCanCallJava)
+    : Thread(bCanCallJava), 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), userBase(0), serverBase(0), buffers(0), frameCount(0),
+    loopStart(UINT_MAX), loopEnd(UINT_MAX), loopCount(0), volumeLR(0), flowControlFlag(1), forceReady(0)
+{
+}
+
+uint32_t audio_track_cblk_t::stepUser(uint32_t frameCount)
+{
+    uint32_t u = this->user;
+
+    u += frameCount;
+    // Ensure that user is never ahead of server for AudioRecord
+    if (out) {
+        // If stepServer() has been called once, switch to normal obtainBuffer() timeout period
+        if (bufferTimeoutMs == MAX_STARTUP_TIMEOUT_MS-1) {
+            bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
+        }
+    } else if (u > this->server) {
+        LOGW("stepServer occured after track reset");
+        u = this->server;
+    }
+
+    if (u >= userBase + this->frameCount) {
+        userBase += this->frameCount;
+    }
+
+    this->user = u;
+
+    // Clear flow control error condition as new data has been written/read to/from buffer.
+    flowControlFlag = 0;
+
+    return u;
+}
+
+bool audio_track_cblk_t::stepServer(uint32_t frameCount)
+{
+    // 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;
+
+    s += frameCount;
+    if (out) {
+        // Mark that we have read the first buffer so that next time stepUser() is called
+        // we switch to normal obtainBuffer() timeout period
+        if (bufferTimeoutMs == MAX_STARTUP_TIMEOUT_MS) {
+            bufferTimeoutMs = MAX_RUN_TIMEOUT_MS - 1;
+        }        
+        // It is possible that we receive a flush()
+        // while the mixer is processing a block: in this case,
+        // stepServer() is called After the flush() has reset u & s and
+        // we have s > u
+        if (s > this->user) {
+            LOGW("stepServer occured after track reset");
+            s = this->user;
+        }
+    }
+
+    if (s >= loopEnd) {
+        LOGW_IF(s > loopEnd, "stepServer: s %u > loopEnd %u", s, loopEnd);
+        s = loopStart;
+        if (--loopCount == 0) {
+            loopEnd = UINT_MAX;
+            loopStart = UINT_MAX;
+        }
+    }
+    if (s >= serverBase + this->frameCount) {
+        serverBase += this->frameCount;
+    }
+
+    this->server = s;
+
+    cv.signal();
+    lock.unlock();
+    return true;
+}
+
+void* audio_track_cblk_t::buffer(uint32_t offset) const
+{
+    return (int16_t *)this->buffers + (offset-userBase)*this->channels;
+}
+
+uint32_t audio_track_cblk_t::framesAvailable()
+{
+    Mutex::Autolock _l(lock);
+    return framesAvailable_l();
+}
+
+uint32_t audio_track_cblk_t::framesAvailable_l()
+{
+    uint32_t u = this->user;
+    uint32_t s = this->server;
+
+    if (out) {
+        uint32_t limit = (s < loopStart) ? s : loopStart;
+        return limit + frameCount - u;
+    } else {
+        return frameCount + u - s;
+    }
+}
+
+uint32_t audio_track_cblk_t::framesReady()
+{
+    uint32_t u = this->user;
+    uint32_t s = this->server;
+
+    if (out) {
+        if (u < loopEnd) {
+            return u - s;
+        } else {
+            Mutex::Autolock _l(lock);
+            if (loopCount >= 0) {
+                return (loopEnd - loopStart)*loopCount + u - s;
+            } else {
+                return UINT_MAX;
+            }
+        }
+    } else {
+        return s - u;
+    }
+}
+
+// -------------------------------------------------------------------------
+
+}; // namespace android
+
diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp
new file mode 100644
index 0000000..5cbb25c
--- /dev/null
+++ b/media/libmedia/IAudioFlinger.cpp
@@ -0,0 +1,553 @@
+/* //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,
+    LATENCY,
+    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,
+    REGISTER_CLIENT,
+    GET_INPUTBUFFERSIZE,
+    WAKE_UP,
+    IS_A2DP_ENABLED
+};
+
+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 frameCount,
+                                uint32_t flags,
+                                const sp<IMemory>& sharedBuffer,
+                                status_t *status)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        data.writeInt32(pid);
+        data.writeInt32(streamType);
+        data.writeInt32(sampleRate);
+        data.writeInt32(format);
+        data.writeInt32(channelCount);
+        data.writeInt32(frameCount);
+        data.writeInt32(flags);
+        data.writeStrongBinder(sharedBuffer->asBinder());
+        status_t lStatus = remote()->transact(CREATE_TRACK, data, &reply);
+        if (lStatus != NO_ERROR) {
+            LOGE("createTrack error: %s", strerror(-lStatus));
+        }
+        lStatus = reply.readInt32();
+        if (status) {
+            *status = lStatus;
+        }
+        return interface_cast<IAudioTrack>(reply.readStrongBinder());
+    }
+
+    virtual sp<IAudioRecord> openRecord(
+                                pid_t pid,
+                                int streamType,
+                                uint32_t sampleRate,
+                                int format,
+                                int channelCount,
+                                int frameCount,
+                                uint32_t flags,
+                                status_t *status)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        data.writeInt32(pid);
+        data.writeInt32(streamType);
+        data.writeInt32(sampleRate);
+        data.writeInt32(format);
+        data.writeInt32(channelCount);
+        data.writeInt32(frameCount);
+        data.writeInt32(flags);
+        remote()->transact(OPEN_RECORD, data, &reply);
+        status_t lStatus = reply.readInt32();
+        if (status) {
+            *status = lStatus;
+        }
+        return interface_cast<IAudioRecord>(reply.readStrongBinder());
+    }
+
+    virtual uint32_t sampleRate(int output) const
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        data.writeInt32(output);
+        remote()->transact(SAMPLE_RATE, data, &reply);
+        return reply.readInt32();
+    }
+
+    virtual int channelCount(int output) const
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        data.writeInt32(output);
+        remote()->transact(CHANNEL_COUNT, data, &reply);
+        return reply.readInt32();
+    }
+
+    virtual int format(int output) const
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        data.writeInt32(output);
+        remote()->transact(FORMAT, data, &reply);
+        return reply.readInt32();
+    }
+
+    virtual size_t frameCount(int output) const
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        data.writeInt32(output);
+        remote()->transact(FRAME_COUNT, data, &reply);
+        return reply.readInt32();
+    }
+
+    virtual uint32_t latency(int output) const
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        data.writeInt32(output);
+        remote()->transact(LATENCY, 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();
+    }
+    
+    virtual void registerClient(const sp<IAudioFlingerClient>& client)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        data.writeStrongBinder(client->asBinder());
+        remote()->transact(REGISTER_CLIENT, data, &reply);
+    }
+    
+    virtual size_t getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        data.writeInt32(sampleRate);
+        data.writeInt32(format);
+        data.writeInt32(channelCount);
+        remote()->transact(GET_INPUTBUFFERSIZE, data, &reply);
+        return reply.readInt32();
+    }
+    
+    virtual void wakeUp()
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        remote()->transact(WAKE_UP, data, &reply);
+        return;
+    }
+
+    virtual bool isA2dpEnabled() const
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        remote()->transact(IS_A2DP_ENABLED, data, &reply);
+        return (bool)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<IMemory> buffer = interface_cast<IMemory>(data.readStrongBinder());
+            status_t status;
+            sp<IAudioTrack> track = createTrack(pid,
+                    streamType, sampleRate, format,
+                    channelCount, bufferCount, flags, buffer, &status);
+            reply->writeInt32(status);
+            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();
+            status_t status;
+            sp<IAudioRecord> record = openRecord(pid, streamType,
+                    sampleRate, format, channelCount, bufferCount, flags, &status);
+            reply->writeInt32(status);
+            reply->writeStrongBinder(record->asBinder());
+            return NO_ERROR;
+        } break;
+        case SAMPLE_RATE: {
+            CHECK_INTERFACE(IAudioFlinger, data, reply);
+            int output = data.readInt32();
+            reply->writeInt32( sampleRate(output) );
+            return NO_ERROR;
+        } break;
+        case CHANNEL_COUNT: {
+            CHECK_INTERFACE(IAudioFlinger, data, reply);
+            int output = data.readInt32();
+            reply->writeInt32( channelCount(output) );
+            return NO_ERROR;
+        } break;
+        case FORMAT: {
+            CHECK_INTERFACE(IAudioFlinger, data, reply);
+            int output = data.readInt32();
+            reply->writeInt32( format(output) );
+            return NO_ERROR;
+        } break;
+        case FRAME_COUNT: {
+            CHECK_INTERFACE(IAudioFlinger, data, reply);
+            int output = data.readInt32();
+            reply->writeInt32( frameCount(output) );
+            return NO_ERROR;
+        } break;
+        case LATENCY: {
+            CHECK_INTERFACE(IAudioFlinger, data, reply);
+            int output = data.readInt32();
+            reply->writeInt32( latency(output) );
+            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;
+        case REGISTER_CLIENT: {
+            CHECK_INTERFACE(IAudioFlinger, data, reply);
+            sp<IAudioFlingerClient> client = interface_cast<IAudioFlingerClient>(data.readStrongBinder());
+            registerClient(client);
+            return NO_ERROR;
+        } break;
+        case GET_INPUTBUFFERSIZE: {
+            CHECK_INTERFACE(IAudioFlinger, data, reply);
+            uint32_t sampleRate = data.readInt32();
+            int format = data.readInt32();
+            int channelCount = data.readInt32();
+            reply->writeInt32( getInputBufferSize(sampleRate, format, channelCount) );
+            return NO_ERROR;
+        } break;
+        case WAKE_UP: {
+            CHECK_INTERFACE(IAudioFlinger, data, reply);
+            wakeUp();
+            return NO_ERROR;
+        } break;
+        case IS_A2DP_ENABLED: {
+            CHECK_INTERFACE(IAudioFlinger, data, reply);
+            reply->writeInt32( (int)isA2dpEnabled() );
+            return NO_ERROR;
+        } break;
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
diff --git a/media/libmedia/IAudioFlingerClient.cpp b/media/libmedia/IAudioFlingerClient.cpp
new file mode 100644
index 0000000..5feb11f
--- /dev/null
+++ b/media/libmedia/IAudioFlingerClient.cpp
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2009 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 "IAudioFlingerClient"
+#include <utils/Log.h>
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/Parcel.h>
+
+#include <media/IAudioFlingerClient.h>
+
+namespace android {
+
+enum {
+    AUDIO_OUTPUT_CHANGED = IBinder::FIRST_CALL_TRANSACTION
+};
+
+class BpAudioFlingerClient : public BpInterface<IAudioFlingerClient>
+{
+public:
+    BpAudioFlingerClient(const sp<IBinder>& impl)
+        : BpInterface<IAudioFlingerClient>(impl)
+    {
+    }
+
+    void a2dpEnabledChanged(bool enabled)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlingerClient::getInterfaceDescriptor());
+        data.writeInt32((int)enabled);
+        remote()->transact(AUDIO_OUTPUT_CHANGED, data, &reply);
+    }
+};
+
+IMPLEMENT_META_INTERFACE(AudioFlingerClient, "android.media.IAudioFlingerClient");
+
+// ----------------------------------------------------------------------
+
+#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 BnAudioFlingerClient::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    switch(code) {
+        case AUDIO_OUTPUT_CHANGED: {
+            CHECK_INTERFACE(IAudioFlingerClient, data, reply);
+            bool enabled = (bool)data.readInt32();
+            a2dpEnabledChanged(enabled);
+            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/IMediaMetadataRetriever.cpp b/media/libmedia/IMediaMetadataRetriever.cpp
new file mode 100644
index 0000000..85b5944
--- /dev/null
+++ b/media/libmedia/IMediaMetadataRetriever.cpp
@@ -0,0 +1,218 @@
+/*
+**
+** 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.
+*/
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <utils/Parcel.h>
+#include <SkBitmap.h>
+#include <media/IMediaMetadataRetriever.h>
+
+namespace android {
+
+enum {
+    DISCONNECT = IBinder::FIRST_CALL_TRANSACTION,
+    SET_DATA_SOURCE_URL,
+    SET_DATA_SOURCE_FD,
+    SET_MODE,
+    GET_MODE,
+    CAPTURE_FRAME,
+    EXTARCT_ALBUM_ART,
+    EXTRACT_METADATA,
+};
+
+class BpMediaMetadataRetriever: public BpInterface<IMediaMetadataRetriever>
+{
+public:
+    BpMediaMetadataRetriever(const sp<IBinder>& impl)
+        : BpInterface<IMediaMetadataRetriever>(impl)
+    {
+    }
+
+    // disconnect from media metadata retriever service
+    void disconnect()
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
+        remote()->transact(DISCONNECT, data, &reply);
+    }
+
+    status_t setDataSource(const char* srcUrl)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
+        data.writeCString(srcUrl);
+        remote()->transact(SET_DATA_SOURCE_URL, data, &reply);
+        return reply.readInt32();
+    }
+
+    status_t setDataSource(int fd, int64_t offset, int64_t length)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
+        data.writeFileDescriptor(fd);
+        data.writeInt64(offset);
+        data.writeInt64(length);
+        remote()->transact(SET_DATA_SOURCE_FD, data, &reply);
+        return reply.readInt32();
+    }
+
+    status_t setMode(int mode)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
+        data.writeInt32(mode);
+        remote()->transact(SET_MODE, data, &reply);
+        return reply.readInt32();
+    }
+
+    status_t getMode(int* mode) const
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
+        remote()->transact(GET_MODE, data, &reply);
+        *mode = reply.readInt32();
+        return reply.readInt32();
+    }
+
+    sp<IMemory> captureFrame()
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
+        remote()->transact(CAPTURE_FRAME, data, &reply);
+        status_t ret = reply.readInt32();
+        if (ret != NO_ERROR) {
+            return NULL;
+        }
+        return interface_cast<IMemory>(reply.readStrongBinder());
+    }
+
+    sp<IMemory> extractAlbumArt()
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
+        remote()->transact(EXTARCT_ALBUM_ART, data, &reply);
+        status_t ret = reply.readInt32();
+        if (ret != NO_ERROR) {
+            return NULL;
+        }
+        return interface_cast<IMemory>(reply.readStrongBinder());
+    }
+
+    const char* extractMetadata(int keyCode)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
+        data.writeInt32(keyCode);
+        remote()->transact(EXTRACT_METADATA, data, &reply);
+        status_t ret = reply.readInt32();
+        if (ret != NO_ERROR) {
+            return NULL;
+        }
+        return reply.readCString();
+    }
+};
+
+IMPLEMENT_META_INTERFACE(MediaMetadataRetriever, "android.hardware.IMediaMetadataRetriever");
+
+// ----------------------------------------------------------------------
+
+#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 BnMediaMetadataRetriever::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    switch (code) {
+        case DISCONNECT: {
+            CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
+            disconnect();
+            return NO_ERROR;
+        } break;
+        case SET_DATA_SOURCE_URL: {
+            CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
+            const char* srcUrl = data.readCString();
+            reply->writeInt32(setDataSource(srcUrl));
+            return NO_ERROR;
+        } break;
+        case SET_DATA_SOURCE_FD: {
+            CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
+            int fd = dup(data.readFileDescriptor());
+            int64_t offset = data.readInt64();
+            int64_t length = data.readInt64();
+            reply->writeInt32(setDataSource(fd, offset, length));
+            return NO_ERROR;
+        } break;
+        case SET_MODE: {
+            CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
+            int mode = data.readInt32();
+            reply->writeInt32(setMode(mode));
+            return NO_ERROR;
+        } break;
+        case GET_MODE: {
+            CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
+            int mode;
+            status_t status = getMode(&mode);
+            reply->writeInt32(mode);
+            reply->writeInt32(status);
+            return NO_ERROR;
+        } break;
+        case CAPTURE_FRAME: {
+            CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
+            sp<IMemory> bitmap = captureFrame();
+            if (bitmap != 0) {  // Don't send NULL across the binder interface
+                reply->writeInt32(NO_ERROR);
+                reply->writeStrongBinder(bitmap->asBinder());
+            } else {
+                reply->writeInt32(UNKNOWN_ERROR);
+            }
+            return NO_ERROR;
+        } break;
+        case EXTARCT_ALBUM_ART: {
+            CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
+            sp<IMemory> albumArt = extractAlbumArt();
+            if (albumArt != 0) {  // Don't send NULL across the binder interface
+                reply->writeInt32(NO_ERROR);
+                reply->writeStrongBinder(albumArt->asBinder());
+            } else {
+                reply->writeInt32(UNKNOWN_ERROR);
+            }
+            return NO_ERROR;
+        } break;
+        case EXTRACT_METADATA: {
+            CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
+            int keyCode = data.readInt32();
+            const char* value = extractMetadata(keyCode);
+            if (value != NULL) {  // Don't send NULL across the binder interface
+                reply->writeInt32(NO_ERROR);
+                reply->writeCString(value);
+            } else {
+                reply->writeInt32(UNKNOWN_ERROR);
+            }
+            return NO_ERROR;
+        } break;
+        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..f37519f
--- /dev/null
+++ b/media/libmedia/IMediaPlayer.cpp
@@ -0,0 +1,275 @@
+/*
+**
+** 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,
+    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 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 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..370e3fb
--- /dev/null
+++ b/media/libmedia/IMediaPlayerService.cpp
@@ -0,0 +1,198 @@
+/*
+**
+** 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>
+#include <media/IMediaRecorder.h>
+
+namespace android {
+
+enum {
+    CREATE_URL = IBinder::FIRST_CALL_TRANSACTION,
+    CREATE_FD,
+    DECODE_URL,
+    DECODE_FD,
+    CREATE_MEDIA_RECORDER,
+    CREATE_METADATA_RETRIEVER,
+};
+
+class BpMediaPlayerService: public BpInterface<IMediaPlayerService>
+{
+public:
+    BpMediaPlayerService(const sp<IBinder>& impl)
+        : BpInterface<IMediaPlayerService>(impl)
+    {
+    }
+
+    virtual sp<IMediaMetadataRetriever> createMetadataRetriever(pid_t pid)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
+        data.writeInt32(pid);
+        remote()->transact(CREATE_METADATA_RETRIEVER, data, &reply);
+        return interface_cast<IMediaMetadataRetriever>(reply.readStrongBinder());
+    }
+
+    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<IMediaRecorder> createMediaRecorder(pid_t pid)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
+        data.writeInt32(pid);
+        remote()->transact(CREATE_MEDIA_RECORDER, data, &reply);
+        return interface_cast<IMediaRecorder>(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, int* pFormat)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
+        data.writeCString(url);
+        remote()->transact(DECODE_URL, data, &reply);
+        *pSampleRate = uint32_t(reply.readInt32());
+        *pNumChannels = reply.readInt32();
+        *pFormat = 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, int* pFormat)
+    {
+        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();
+        *pFormat = 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;
+            int format;
+            sp<IMemory> player = decode(url, &sampleRate, &numChannels, &format);
+            reply->writeInt32(sampleRate);
+            reply->writeInt32(numChannels);
+            reply->writeInt32(format);
+            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;
+            int format;
+            sp<IMemory> player = decode(fd, offset, length, &sampleRate, &numChannels, &format);
+            reply->writeInt32(sampleRate);
+            reply->writeInt32(numChannels);
+            reply->writeInt32(format);
+            reply->writeStrongBinder(player->asBinder());
+            return NO_ERROR;
+        } break;
+        case CREATE_MEDIA_RECORDER: {
+            CHECK_INTERFACE(IMediaPlayerService, data, reply);
+            pid_t pid = data.readInt32();
+            sp<IMediaRecorder> recorder = createMediaRecorder(pid);
+            reply->writeStrongBinder(recorder->asBinder());
+            return NO_ERROR;
+        } break;
+        case CREATE_METADATA_RETRIEVER: {
+            CHECK_INTERFACE(IMediaPlayerService, data, reply);
+            pid_t pid = data.readInt32();
+            sp<IMediaMetadataRetriever> retriever = createMetadataRetriever(pid);
+            reply->writeStrongBinder(retriever->asBinder());
+            return NO_ERROR;
+        } break;
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
+
diff --git a/media/libmedia/IMediaRecorder.cpp b/media/libmedia/IMediaRecorder.cpp
new file mode 100644
index 0000000..f187bf5
--- /dev/null
+++ b/media/libmedia/IMediaRecorder.cpp
@@ -0,0 +1,417 @@
+/*
+ **
+ ** Copyright 2008, HTC Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ **     http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "IMediaRecorder"
+#include <utils/Log.h>
+#include <utils/Parcel.h>
+#include <ui/ISurface.h>
+#include <ui/ICamera.h>
+#include <media/IMediaPlayerClient.h>
+#include <media/IMediaRecorder.h>
+
+namespace android {
+
+enum {
+    RELEASE = IBinder::FIRST_CALL_TRANSACTION,
+    INIT,
+    CLOSE,
+    RESET,
+    STOP,
+    START,
+    PREPARE,
+    GET_MAX_AMPLITUDE,
+    SET_VIDEO_SOURCE,
+    SET_AUDIO_SOURCE,
+    SET_OUTPUT_FORMAT,
+    SET_VIDEO_ENCODER,
+    SET_AUDIO_ENCODER,
+    SET_OUTPUT_FILE_PATH,
+    SET_OUTPUT_FILE_FD,
+    SET_VIDEO_SIZE,
+    SET_VIDEO_FRAMERATE,
+    SET_PREVIEW_SURFACE,
+    SET_CAMERA,
+    SET_LISTENER
+};
+
+class BpMediaRecorder: public BpInterface<IMediaRecorder>
+{
+public:
+    BpMediaRecorder(const sp<IBinder>& impl)
+    : BpInterface<IMediaRecorder>(impl)
+    {
+    }
+
+    status_t setCamera(const sp<ICamera>& camera)
+    {
+        LOGV("setCamera(%p)", camera.get());
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+        data.writeStrongBinder(camera->asBinder());
+        remote()->transact(SET_CAMERA, data, &reply);
+        return reply.readInt32();
+    }
+
+    status_t setPreviewSurface(const sp<ISurface>& surface)
+    {
+        LOGV("setPreviewSurface(%p)", surface.get());
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+        data.writeStrongBinder(surface->asBinder());
+        remote()->transact(SET_PREVIEW_SURFACE, data, &reply);
+        return reply.readInt32();
+    }
+
+    status_t init()
+    {
+        LOGV("init");
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+        remote()->transact(INIT, data, &reply);
+        return reply.readInt32();
+    }
+
+    status_t setVideoSource(int vs)
+    {
+        LOGV("setVideoSource(%d)", vs);
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+        data.writeInt32(vs);
+        remote()->transact(SET_VIDEO_SOURCE, data, &reply);
+        return reply.readInt32();
+    }
+
+    status_t setAudioSource(int as)
+    {
+        LOGV("setAudioSource(%d)", as);
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+        data.writeInt32(as);
+        remote()->transact(SET_AUDIO_SOURCE, data, &reply);
+        return reply.readInt32();
+    }
+
+    status_t setOutputFormat(int of)
+    {
+        LOGV("setOutputFormat(%d)", of);
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+        data.writeInt32(of);
+        remote()->transact(SET_OUTPUT_FORMAT, data, &reply);
+        return reply.readInt32();
+    }
+
+    status_t setVideoEncoder(int ve)
+    {
+        LOGV("setVideoEncoder(%d)", ve);
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+        data.writeInt32(ve);
+        remote()->transact(SET_VIDEO_ENCODER, data, &reply);
+        return reply.readInt32();
+    }
+
+    status_t setAudioEncoder(int ae)
+    {
+        LOGV("setAudioEncoder(%d)", ae);
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+        data.writeInt32(ae);
+        remote()->transact(SET_AUDIO_ENCODER, data, &reply);
+        return reply.readInt32();
+    }
+
+    status_t setOutputFile(const char* path)
+    {
+        LOGV("setOutputFile(%s)", path);
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+        data.writeCString(path);
+        remote()->transact(SET_OUTPUT_FILE_PATH, data, &reply);
+        return reply.readInt32();
+    }
+
+    status_t setOutputFile(int fd, int64_t offset, int64_t length) {
+        LOGV("setOutputFile(%d, %lld, %lld)", fd, offset, length);
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+        data.writeFileDescriptor(fd);
+        data.writeInt64(offset);
+        data.writeInt64(length);
+        remote()->transact(SET_OUTPUT_FILE_FD, data, &reply);
+        return reply.readInt32();
+    }
+
+    status_t setVideoSize(int width, int height)
+    {
+        LOGV("setVideoSize(%dx%d)", width, height);
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+        data.writeInt32(width);
+        data.writeInt32(height);
+        remote()->transact(SET_VIDEO_SIZE, data, &reply);
+        return reply.readInt32();
+    }
+
+    status_t setVideoFrameRate(int frames_per_second)
+    {
+        LOGV("setVideoFrameRate(%d)", frames_per_second);
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+        data.writeInt32(frames_per_second);
+        remote()->transact(SET_VIDEO_FRAMERATE, data, &reply);
+        return reply.readInt32();
+    }
+
+    status_t setListener(const sp<IMediaPlayerClient>& listener)
+    {
+        LOGV("setListener(%p)", listener.get());
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+        data.writeStrongBinder(listener->asBinder());
+        remote()->transact(SET_LISTENER, data, &reply);
+        return reply.readInt32();
+    }
+
+    status_t prepare()
+    {
+        LOGV("prepare");
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+        remote()->transact(PREPARE, data, &reply);
+        return reply.readInt32();
+    }
+
+    status_t getMaxAmplitude(int* max)
+    {
+        LOGV("getMaxAmplitude");
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+        remote()->transact(GET_MAX_AMPLITUDE, data, &reply);
+        *max = reply.readInt32();
+        return reply.readInt32();
+    }
+
+    status_t start()
+    {
+        LOGV("start");
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+        remote()->transact(START, data, &reply);
+        return reply.readInt32();
+    }
+
+    status_t stop()
+    {
+        LOGV("stop");
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+        remote()->transact(STOP, data, &reply);
+        return reply.readInt32();
+    }
+
+    status_t reset()
+    {
+        LOGV("reset");
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+        remote()->transact(RESET, data, &reply);
+        return reply.readInt32();
+    }
+
+    status_t close()
+    {
+        LOGV("close");
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+        remote()->transact(CLOSE, data, &reply);
+        return reply.readInt32();
+    }
+
+    status_t release()
+    {
+        LOGV("release");
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+        remote()->transact(RELEASE, data, &reply);
+        return reply.readInt32();
+    }
+};
+
+IMPLEMENT_META_INTERFACE(MediaRecorder, "android.hardware.IMediaRecorder");
+
+// ----------------------------------------------------------------------
+
+#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 BnMediaRecorder::onTransact(
+                                     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    switch(code) {
+        case RELEASE: {
+            LOGV("RELEASE");
+            CHECK_INTERFACE(IMediaRecorder, data, reply);
+            reply->writeInt32(release());
+            return NO_ERROR;
+        } break;
+        case INIT: {
+            LOGV("INIT");
+            CHECK_INTERFACE(IMediaRecorder, data, reply);
+            reply->writeInt32(init());
+            return NO_ERROR;
+        } break;
+        case CLOSE: {
+            LOGV("CLOSE");
+            CHECK_INTERFACE(IMediaRecorder, data, reply);
+            reply->writeInt32(close());
+            return NO_ERROR;
+        } break;
+        case RESET: {
+            LOGV("RESET");
+            CHECK_INTERFACE(IMediaRecorder, data, reply);
+            reply->writeInt32(reset());
+            return NO_ERROR;
+        } break;
+        case STOP: {
+            LOGV("STOP");
+            CHECK_INTERFACE(IMediaRecorder, data, reply);
+            reply->writeInt32(stop());
+            return NO_ERROR;
+        } break;
+        case START: {
+            LOGV("START");
+            CHECK_INTERFACE(IMediaRecorder, data, reply);
+            reply->writeInt32(start());
+            return NO_ERROR;
+        } break;
+        case PREPARE: {
+            LOGV("PREPARE");
+            CHECK_INTERFACE(IMediaRecorder, data, reply);
+            reply->writeInt32(prepare());
+            return NO_ERROR;
+        } break;
+        case GET_MAX_AMPLITUDE: {
+            LOGV("GET_MAX_AMPLITUDE");
+            CHECK_INTERFACE(IMediaRecorder, data, reply);
+            int max = 0;
+            status_t ret = getMaxAmplitude(&max);
+            reply->writeInt32(max);
+            reply->writeInt32(ret);
+            return NO_ERROR;
+        } break;
+        case SET_VIDEO_SOURCE: {
+            LOGV("SET_VIDEO_SOURCE");
+            CHECK_INTERFACE(IMediaRecorder, data, reply);
+            int vs = data.readInt32();
+            reply->writeInt32(setVideoSource(vs));
+            return NO_ERROR;
+        } break;
+        case SET_AUDIO_SOURCE: {
+            LOGV("SET_AUDIO_SOURCE");
+            CHECK_INTERFACE(IMediaRecorder, data, reply);
+            int as = data.readInt32();
+            reply->writeInt32(setAudioSource(as));
+            return NO_ERROR;
+        } break;
+        case SET_OUTPUT_FORMAT: {
+            LOGV("SET_OUTPUT_FORMAT");
+            CHECK_INTERFACE(IMediaRecorder, data, reply);
+            int of = data.readInt32();
+            reply->writeInt32(setOutputFormat(of));
+            return NO_ERROR;
+        } break;
+        case SET_VIDEO_ENCODER: {
+            LOGV("SET_VIDEO_ENCODER");
+            CHECK_INTERFACE(IMediaRecorder, data, reply);
+            int ve = data.readInt32();
+            reply->writeInt32(setVideoEncoder(ve));
+            return NO_ERROR;
+        } break;
+        case SET_AUDIO_ENCODER: {
+            LOGV("SET_AUDIO_ENCODER");
+            CHECK_INTERFACE(IMediaRecorder, data, reply);
+            int ae = data.readInt32();
+            reply->writeInt32(setAudioEncoder(ae));
+            return NO_ERROR;
+
+        } break;
+        case SET_OUTPUT_FILE_PATH: {
+            LOGV("SET_OUTPUT_FILE_PATH");
+            CHECK_INTERFACE(IMediaRecorder, data, reply);
+            const char* path = data.readCString();
+            reply->writeInt32(setOutputFile(path));
+            return NO_ERROR;
+        } break;
+        case SET_OUTPUT_FILE_FD: {
+            LOGV("SET_OUTPUT_FILE_FD");
+            CHECK_INTERFACE(IMediaRecorder, data, reply);
+            int fd = dup(data.readFileDescriptor());
+            int64_t offset = data.readInt64();
+            int64_t length = data.readInt64();
+            reply->writeInt32(setOutputFile(fd, offset, length));
+            return NO_ERROR;
+        } break;
+        case SET_VIDEO_SIZE: {
+            LOGV("SET_VIDEO_SIZE");
+            CHECK_INTERFACE(IMediaRecorder, data, reply);
+            int width = data.readInt32();
+            int height = data.readInt32();
+            reply->writeInt32(setVideoSize(width, height));
+            return NO_ERROR;
+        } break;
+        case SET_VIDEO_FRAMERATE: {
+            LOGV("SET_VIDEO_FRAMERATE");
+            CHECK_INTERFACE(IMediaRecorder, data, reply);
+            int frames_per_second = data.readInt32();
+            reply->writeInt32(setVideoFrameRate(frames_per_second));
+            return NO_ERROR;
+        } break;
+        case SET_LISTENER: {
+            LOGV("SET_LISTENER");
+            CHECK_INTERFACE(IMediaRecorder, data, reply);
+            sp<IMediaPlayerClient> listener =
+                interface_cast<IMediaPlayerClient>(data.readStrongBinder());
+            reply->writeInt32(setListener(listener));
+            return NO_ERROR;
+        } break;
+        case SET_PREVIEW_SURFACE: {
+            LOGV("SET_PREVIEW_SURFACE");
+            CHECK_INTERFACE(IMediaRecorder, data, reply);
+            sp<ISurface> surface = interface_cast<ISurface>(data.readStrongBinder());
+            reply->writeInt32(setPreviewSurface(surface));
+            return NO_ERROR;
+        } break;
+        case SET_CAMERA: {
+            LOGV("SET_CAMERA");
+            CHECK_INTERFACE(IMediaRecorder, data, reply);
+            sp<ICamera> camera = interface_cast<ICamera>(data.readStrongBinder());
+            reply->writeInt32(setCamera(camera));
+            return NO_ERROR;
+        } break;
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
diff --git a/media/libmedia/JetPlayer.cpp b/media/libmedia/JetPlayer.cpp
new file mode 100644
index 0000000..2c62104
--- /dev/null
+++ b/media/libmedia/JetPlayer.cpp
@@ -0,0 +1,489 @@
+/*
+ * 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 "JetPlayer-C"
+
+#include <utils/Log.h>
+#include <utils/threads.h>
+
+#include <media/JetPlayer.h>
+
+
+#ifdef HAVE_GETTID
+static pid_t myTid() { return gettid(); }
+#else
+static pid_t myTid() { return getpid(); }
+#endif
+
+
+namespace android
+{
+
+static const int MIX_NUM_BUFFERS = 4;
+static const S_EAS_LIB_CONFIG* pLibConfig = NULL;
+
+//-------------------------------------------------------------------------------------------------
+JetPlayer::JetPlayer(jobject javaJetPlayer, int maxTracks, int trackBufferSize) :
+        mEventCallback(NULL),
+        mJavaJetPlayerRef(javaJetPlayer),
+        mTid(-1),
+        mRender(false),
+        mPaused(false),
+        mMaxTracks(maxTracks),
+        mEasData(NULL),
+        mEasJetFileLoc(NULL),
+        mAudioTrack(NULL),
+        mTrackBufferSize(trackBufferSize)
+{
+    LOGV("JetPlayer constructor");
+    mPreviousJetStatus.currentUserID = -1;
+    mPreviousJetStatus.segmentRepeatCount = -1;
+    mPreviousJetStatus.numQueuedSegments = -1;
+    mPreviousJetStatus.paused = true;
+}
+
+//-------------------------------------------------------------------------------------------------
+JetPlayer::~JetPlayer()
+{
+    LOGV("~JetPlayer");
+    release();
+
+}
+
+//-------------------------------------------------------------------------------------------------
+int JetPlayer::init()
+{
+    //Mutex::Autolock lock(&mMutex);
+
+    EAS_RESULT result;
+
+    // retrieve the EAS library settings
+    if (pLibConfig == NULL)
+        pLibConfig = EAS_Config();
+    if (pLibConfig == NULL) {
+        LOGE("JetPlayer::init(): EAS library configuration could not be retrieved, aborting.");
+        return EAS_FAILURE;
+    }
+
+    // init the EAS library
+    result = EAS_Init(&mEasData);
+    if( result != EAS_SUCCESS) {
+        LOGE("JetPlayer::init(): Error initializing Sonivox EAS library, aborting.");
+        mState = EAS_STATE_ERROR;
+        return result;
+    }
+    // init the JET library with the default app event controller range
+    result = JET_Init(mEasData, NULL, sizeof(S_JET_CONFIG));
+    if( result != EAS_SUCCESS) {
+        LOGE("JetPlayer::init(): Error initializing JET library, aborting.");
+        mState = EAS_STATE_ERROR;
+        return result;
+    }
+
+    // create the output AudioTrack
+    mAudioTrack = new AudioTrack();
+    mAudioTrack->set(AudioSystem::MUSIC,  //TODO parametrize this
+            pLibConfig->sampleRate,
+            1, // format = PCM 16bits per sample,
+            pLibConfig->numChannels,
+            mTrackBufferSize,
+            0);
+
+    // create render and playback thread
+    {
+        Mutex::Autolock l(mMutex);
+        LOGV("JetPlayer::init(): trying to start render thread");
+        createThreadEtc(renderThread, this, "jetRenderThread", ANDROID_PRIORITY_AUDIO);
+        mCondition.wait(mMutex);
+    }
+    if (mTid > 0) {
+        // render thread started, we're ready
+        LOGV("JetPlayer::init(): render thread(%d) successfully started.", mTid);
+        mState = EAS_STATE_READY;
+    } else {
+        LOGE("JetPlayer::init(): failed to start render thread.");
+        mState = EAS_STATE_ERROR;
+        return EAS_FAILURE;
+    }
+
+    return EAS_SUCCESS;
+}
+
+void JetPlayer::setEventCallback(jetevent_callback eventCallback)
+{
+    Mutex::Autolock l(mMutex);
+    mEventCallback = eventCallback;
+}
+
+//-------------------------------------------------------------------------------------------------
+int JetPlayer::release()
+{
+    LOGV("JetPlayer::release()");
+    Mutex::Autolock lock(mMutex);
+    mPaused = true;
+    mRender = false;
+    if (mEasData) {
+        JET_Pause(mEasData);
+        JET_CloseFile(mEasData);
+        JET_Shutdown(mEasData);
+        EAS_Shutdown(mEasData);
+    }
+    if (mEasJetFileLoc) {
+        free(mEasJetFileLoc);
+        mEasJetFileLoc = NULL;
+    }
+    if (mAudioTrack) {
+        mAudioTrack->stop();
+        mAudioTrack->flush();
+        delete mAudioTrack;
+        mAudioTrack = NULL;
+    }
+    if (mAudioBuffer) {
+        delete mAudioBuffer;
+        mAudioBuffer = NULL;
+    }
+    mEasData = NULL;
+    
+    return EAS_SUCCESS;
+}
+
+
+//-------------------------------------------------------------------------------------------------
+int JetPlayer::renderThread(void* p) {
+
+    return ((JetPlayer*)p)->render();
+}
+
+//-------------------------------------------------------------------------------------------------
+int JetPlayer::render() {
+    EAS_RESULT result = EAS_FAILURE;
+    EAS_I32 count;
+    int temp;
+    bool audioStarted = false;
+
+    LOGV("JetPlayer::render(): entering");
+
+    // allocate render buffer
+    mAudioBuffer = 
+        new EAS_PCM[pLibConfig->mixBufferSize * pLibConfig->numChannels * MIX_NUM_BUFFERS];
+    if (!mAudioBuffer) {
+        LOGE("JetPlayer::render(): mAudioBuffer allocate failed");
+        goto threadExit;
+    }
+
+    // signal main thread that we started
+    {
+        Mutex::Autolock l(mMutex);
+        mTid = myTid();
+        LOGV("JetPlayer::render(): render thread(%d) signal", mTid);
+        mCondition.signal();
+    }
+
+   while (1) {
+        mMutex.lock(); // [[[[[[[[ LOCK ---------------------------------------
+
+        // nothing to render, wait for client thread to wake us up
+        while (!mRender)
+        {
+            LOGV("JetPlayer::render(): signal wait");
+            if (audioStarted) { 
+                mAudioTrack->pause(); 
+                // we have to restart the playback once we start rendering again
+                audioStarted = false;
+            }
+            mCondition.wait(mMutex);
+            LOGV("JetPlayer::render(): signal rx'd");
+        }
+        
+        // render midi data into the input buffer
+        int num_output = 0;
+        EAS_PCM* p = mAudioBuffer;
+        for (int i = 0; i < MIX_NUM_BUFFERS; i++) {
+            result = EAS_Render(mEasData, p, pLibConfig->mixBufferSize, &count);
+            if (result != EAS_SUCCESS) {
+                LOGE("JetPlayer::render(): EAS_Render returned error %ld", result);
+            }
+            p += count * pLibConfig->numChannels;
+            num_output += count * pLibConfig->numChannels * sizeof(EAS_PCM);
+            
+             // send events that were generated (if any) to the event callback
+            fireEventsFromJetQueue();
+        }
+
+        // update playback state
+        //LOGV("JetPlayer::render(): updating state");
+        JET_Status(mEasData, &mJetStatus);
+        fireUpdateOnStatusChange();
+        mPaused = mJetStatus.paused;
+
+        mMutex.unlock(); // UNLOCK ]]]]]]]] -----------------------------------
+
+        // check audio output track
+        if (mAudioTrack == NULL) {
+            LOGE("JetPlayer::render(): output AudioTrack was not created");
+            goto threadExit;
+        }
+
+        // Write data to the audio hardware
+        //LOGV("JetPlayer::render(): writing to audio output");
+        if ((temp = mAudioTrack->write(mAudioBuffer, num_output)) < 0) {
+            LOGE("JetPlayer::render(): Error in writing:%d",temp);
+            return temp;
+        }
+
+        // start audio output if necessary
+        if (!audioStarted) {
+            LOGV("JetPlayer::render(): starting audio playback");
+            mAudioTrack->start();
+            audioStarted = true;
+        }
+
+    }//while (1)
+
+threadExit:
+    mAudioTrack->flush();
+    if (mAudioBuffer) {
+        delete [] mAudioBuffer;
+        mAudioBuffer = NULL;
+    }
+    mMutex.lock();
+    mTid = -1;
+    mCondition.signal();
+    mMutex.unlock();
+    return result;
+}
+
+
+//-------------------------------------------------------------------------------------------------
+// fire up an update if any of the status fields has changed
+// precondition: mMutex locked
+void JetPlayer::fireUpdateOnStatusChange()
+{
+    if(  (mJetStatus.currentUserID      != mPreviousJetStatus.currentUserID)
+       ||(mJetStatus.segmentRepeatCount != mPreviousJetStatus.segmentRepeatCount) ) {
+        if(mEventCallback)  {
+            mEventCallback(
+                JetPlayer::JET_USERID_UPDATE,
+                mJetStatus.currentUserID,
+                mJetStatus.segmentRepeatCount,
+                mJavaJetPlayerRef);
+        }
+        mPreviousJetStatus.currentUserID      = mJetStatus.currentUserID;
+        mPreviousJetStatus.segmentRepeatCount = mJetStatus.segmentRepeatCount;
+    }
+
+    if(mJetStatus.numQueuedSegments != mPreviousJetStatus.numQueuedSegments) {
+        if(mEventCallback)  {
+            mEventCallback(
+                JetPlayer::JET_NUMQUEUEDSEGMENT_UPDATE,
+                mJetStatus.numQueuedSegments,
+                -1,
+                mJavaJetPlayerRef);
+        }
+        mPreviousJetStatus.numQueuedSegments  = mJetStatus.numQueuedSegments;
+    }
+
+    if(mJetStatus.paused != mPreviousJetStatus.paused) {
+        if(mEventCallback)  {
+            mEventCallback(JetPlayer::JET_PAUSE_UPDATE,
+                mJetStatus.paused,
+                -1,
+                mJavaJetPlayerRef);
+        }
+        mPreviousJetStatus.paused = mJetStatus.paused;
+    }
+
+}
+
+
+//-------------------------------------------------------------------------------------------------
+// fire up all the JET events in the JET engine queue (until the queue is empty)
+// precondition: mMutex locked
+void JetPlayer::fireEventsFromJetQueue()
+{
+    if(!mEventCallback) {
+        // no callback, just empty the event queue
+        while (JET_GetEvent(mEasData, NULL, NULL)) { }
+        return;
+    }
+
+    EAS_U32 rawEvent;
+    while (JET_GetEvent(mEasData, &rawEvent, NULL)) {
+        mEventCallback(
+            JetPlayer::JET_EVENT,
+            rawEvent,
+            -1,
+            mJavaJetPlayerRef);
+    }
+}
+
+
+//-------------------------------------------------------------------------------------------------
+int JetPlayer::loadFromFile(const char* path)
+{
+    LOGV("JetPlayer::loadFromFile(): path=%s", path);
+
+    Mutex::Autolock lock(mMutex);
+
+    mEasJetFileLoc = (EAS_FILE_LOCATOR) malloc(sizeof(EAS_FILE));
+    memset(mJetFilePath, 0, 256);
+    strncpy(mJetFilePath, path, strlen(path));
+    mEasJetFileLoc->path = mJetFilePath;
+
+    mEasJetFileLoc->fd = 0;
+    mEasJetFileLoc->length = 0;
+    mEasJetFileLoc->offset = 0;
+
+    EAS_RESULT result = JET_OpenFile(mEasData, mEasJetFileLoc);
+    if(result != EAS_SUCCESS)
+        mState = EAS_STATE_ERROR;
+    else
+        mState = EAS_STATE_OPEN;
+    return( result );
+}
+
+
+//-------------------------------------------------------------------------------------------------
+int JetPlayer::loadFromFD(const int fd, const long long offset, const long long length)
+{
+    LOGV("JetPlayer::loadFromFD(): fd=%d offset=%lld length=%lld", fd, offset, length);
+    
+    Mutex::Autolock lock(mMutex);
+
+    mEasJetFileLoc = (EAS_FILE_LOCATOR) malloc(sizeof(EAS_FILE));
+    mEasJetFileLoc->fd = fd;
+    mEasJetFileLoc->offset = offset;
+    mEasJetFileLoc->length = length;
+    mEasJetFileLoc->path = NULL;
+    
+    EAS_RESULT result = JET_OpenFile(mEasData, mEasJetFileLoc);
+    if(result != EAS_SUCCESS)
+        mState = EAS_STATE_ERROR;
+    else
+        mState = EAS_STATE_OPEN;
+    return( result );
+}
+
+
+//-------------------------------------------------------------------------------------------------
+int JetPlayer::closeFile()
+{
+    Mutex::Autolock lock(mMutex);
+    return JET_CloseFile(mEasData);
+}
+
+
+//-------------------------------------------------------------------------------------------------
+int JetPlayer::play()
+{
+    LOGV("JetPlayer::play(): entering");
+    Mutex::Autolock lock(mMutex);
+
+    EAS_RESULT result = JET_Play(mEasData);
+
+    mPaused = false;
+    mRender = true;
+
+    JET_Status(mEasData, &mJetStatus);
+    this->dumpJetStatus(&mJetStatus);
+    
+    fireUpdateOnStatusChange();
+
+    // wake up render thread
+    LOGV("JetPlayer::play(): wakeup render thread");
+    mCondition.signal();
+
+    return result;
+}
+
+//-------------------------------------------------------------------------------------------------
+int JetPlayer::pause()
+{
+    Mutex::Autolock lock(mMutex);
+    mPaused = true;
+    EAS_RESULT result = JET_Pause(mEasData);
+
+    mRender = false;
+
+    JET_Status(mEasData, &mJetStatus);
+    this->dumpJetStatus(&mJetStatus);
+    fireUpdateOnStatusChange();
+
+
+    return result;
+}
+
+
+//-------------------------------------------------------------------------------------------------
+int JetPlayer::queueSegment(int segmentNum, int libNum, int repeatCount, int transpose,
+        EAS_U32 muteFlags, EAS_U8 userID)
+{
+    LOGV("JetPlayer::queueSegment segmentNum=%d, libNum=%d, repeatCount=%d, transpose=%d",
+        segmentNum, libNum, repeatCount, transpose);
+    Mutex::Autolock lock(mMutex);
+    return JET_QueueSegment(mEasData, segmentNum, libNum, repeatCount, transpose, muteFlags, userID);
+}
+
+//-------------------------------------------------------------------------------------------------
+int JetPlayer::setMuteFlags(EAS_U32 muteFlags, bool sync)
+{
+    Mutex::Autolock lock(mMutex);
+    return JET_SetMuteFlags(mEasData, muteFlags, sync);
+}
+
+//-------------------------------------------------------------------------------------------------
+int JetPlayer::setMuteFlag(int trackNum, bool muteFlag, bool sync)
+{
+    Mutex::Autolock lock(mMutex);
+    return JET_SetMuteFlag(mEasData, trackNum, muteFlag, sync);
+}
+
+//-------------------------------------------------------------------------------------------------
+int JetPlayer::triggerClip(int clipId)
+{
+    LOGV("JetPlayer::triggerClip clipId=%d", clipId);
+    Mutex::Autolock lock(mMutex);
+    return JET_TriggerClip(mEasData, clipId);
+}
+
+//-------------------------------------------------------------------------------------------------
+int JetPlayer::clearQueue()
+{
+    LOGV("JetPlayer::clearQueue");
+    Mutex::Autolock lock(mMutex);
+    return JET_Clear_Queue(mEasData);
+}
+
+//-------------------------------------------------------------------------------------------------
+void JetPlayer::dump()
+{
+    LOGE("JetPlayer dump: JET file=%s", mEasJetFileLoc->path);
+}
+
+void JetPlayer::dumpJetStatus(S_JET_STATUS* pJetStatus)
+{
+    if(pJetStatus!=NULL)
+        LOGV(">> current JET player status: userID=%d segmentRepeatCount=%d numQueuedSegments=%d paused=%d",
+                pJetStatus->currentUserID, pJetStatus->segmentRepeatCount,
+                pJetStatus->numQueuedSegments, pJetStatus->paused);
+    else
+        LOGE(">> JET player status is NULL");
+}
+
+
+} // end 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..5416629
--- /dev/null
+++ b/media/libmedia/ToneGenerator.cpp
@@ -0,0 +1,730 @@
+/*
+ * 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 },       { 40, 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 },       { 40, 200, 40, 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) {
+
+    LOGV("ToneGenerator constructor: streamType=%d, volume=%f\n", streamType, volume);
+
+    mState = TONE_IDLE;
+
+    if (AudioSystem::getOutputSamplingRate(&mSamplingRate, streamType) != NO_ERROR) {
+        LOGE("Unable to marshal AudioFlinger");
+        return;
+    }
+    mStreamType = streamType;
+    mVolume = volume;
+    mpAudioTrack = 0;
+    mpToneDesc = 0;
+    mpNewToneDesc = 0;
+    // Generate tone by chunks of 20 ms to keep cadencing precision
+    mProcessSize = (mSamplingRate * 20) / 1000;
+
+    if (initAudioTrack()) {
+        LOGV("ToneGenerator INIT OK, time: %d\n", (unsigned int)(systemTime()/1000000));
+    } else {
+        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 (toneType >= NUM_TONES)
+        return lResult;
+
+    if (mState == TONE_IDLE) {
+        LOGV("startTone: try to re-init AudioTrack");
+        if (!initAudioTrack()) {
+            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));
+            lResult = true;
+            mState = TONE_STARTING;
+            mLock.unlock();
+            mpAudioTrack->start();
+            mLock.lock();
+            if (mState == TONE_STARTING) {
+                LOGV("Wait for start callback");
+                if (mWaitCbkCond.waitRelative(mLock, seconds(1)) != NO_ERROR) {
+                    LOGE("--- Immediate start timed out");
+                    mState = TONE_IDLE;
+                    lResult = false;
+                }
+            }
+        } else {
+            mState == TONE_IDLE;
+        }
+    } else {
+        LOGV("Delayed start\n");
+
+        mState = TONE_RESTARTING;
+        if (mWaitCbkCond.waitRelative(mLock, seconds(1)) == NO_ERROR) {
+            if (mState != TONE_IDLE) {
+                lResult = true;
+            }
+            LOGV("cond received");
+        } else {
+            LOGE("--- Delayed start timed out");
+            mState = TONE_IDLE;
+        }
+    }
+    mLock.unlock();
+
+    LOGV_IF(lResult, "Tone started, time %d\n", (unsigned int)(systemTime()/1000000));
+    LOGW_IF(!lResult, "Tone start failed!!!, 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("--- Stop timed out");
+            mState = TONE_IDLE;
+            mpAudioTrack->stop();
+        }
+    }
+
+    clearWaveGens();
+
+    mLock.unlock();
+}
+
+//---------------------------------- private methods ---------------------------
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+//
+//    Method:        ToneGenerator::initAudioTrack()
+//
+//    Description:    Allocates and configures AudioTrack used for PCM output.
+//
+//    Input:
+//        none
+//
+//    Output:
+//        none
+//
+////////////////////////////////////////////////////////////////////////////////
+bool ToneGenerator::initAudioTrack() {
+
+    if (mpAudioTrack) {
+        delete mpAudioTrack;
+        mpAudioTrack = 0;
+    }
+
+   // Open audio track in mono, PCM 16bit, default sampling rate, default buffer size
+    mpAudioTrack
+            = new AudioTrack(mStreamType, 0, AudioSystem::PCM_16_BIT, 1, 0, 0, audioCallback, this, 0);
+
+    if (mpAudioTrack == 0) {
+        LOGE("AudioTrack allocation failed");
+        goto initAudioTrack_exit;
+    }
+    LOGV("Create Track: %p\n", mpAudioTrack);
+
+    if (mpAudioTrack->initCheck() != NO_ERROR) {
+        LOGE("AudioTrack->initCheck failed");
+        goto initAudioTrack_exit;
+    }
+
+    mpAudioTrack->setVolume(mVolume, mVolume);
+
+    mState = TONE_INIT;
+
+    return true;
+
+initAudioTrack_exit:
+
+    // Cleanup
+    if (mpAudioTrack) {
+        LOGV("Delete Track I: %p\n", mpAudioTrack);
+        delete mpAudioTrack;
+        mpAudioTrack = 0;
+    }
+
+    return false;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+//
+//    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(int event, void* user, void *info) {
+    
+    if (event != AudioTrack::EVENT_MORE_DATA) return;
+    
+    const AudioTrack::Buffer *buffer = static_cast<const AudioTrack::Buffer *>(info);
+    ToneGenerator *lpToneGen = static_cast<ToneGenerator *>(user);
+    short *lpOut = buffer->i16;
+    unsigned int lNumSmp = buffer->size/sizeof(short);
+
+    if (buffer->size == 0) return;
+
+
+    // Clear output buffer: WaveGenerator accumulates into lpOut buffer
+    memset(lpOut, 0, buffer->size);
+
+    while (lNumSmp) {
+        unsigned int lReqSmp = lNumSmp < lpToneGen->mProcessSize*2 ? lNumSmp : lpToneGen->mProcessSize;
+        unsigned int lGenSmp;
+        unsigned int lWaveCmd = WaveGenerator::WAVEGEN_CONT;
+        bool lSignal = false;
+ 
+        lpToneGen->mLock.lock();
+
+        // 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_EndLoop;
+        }
+        
+    
+        // Exit if tone sequence is over
+        if (lpToneGen->mpToneDesc->segments[lpToneGen->mCurSegment] == 0) {
+            if (lpToneGen->mState == TONE_PLAYING) {
+                lpToneGen->mState = TONE_STOPPING;            
+            }
+            goto audioCallback_EndLoop;
+        }
+    
+        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);
+            }
+        }
+        
+        lNumSmp -= lReqSmp;
+        lpOut += lReqSmp;
+    
+audioCallback_EndLoop:
+    
+        switch (lpToneGen->mState) {
+        case TONE_RESTARTING:
+            LOGV("Cbk restarting track\n");
+            if (lpToneGen->prepareWave()) {
+                lpToneGen->mState = TONE_STARTING;
+            } else {
+                LOGW("Cbk restarting prepareWave() failed\n");
+                lpToneGen->mState = TONE_IDLE;
+                lpToneGen->mpAudioTrack->stop();
+                // Force loop exit
+                lNumSmp = 0;
+            }
+            lSignal = true;
+            break;
+        case TONE_STOPPING:
+            lpToneGen->mState = TONE_INIT;
+            LOGV("Cbk Stopping track\n");
+            lSignal = true;
+            lpToneGen->mpAudioTrack->stop();
+            
+            // Force loop exit
+            lNumSmp = 0;
+            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..09afc6c
--- /dev/null
+++ b/media/libmedia/mediametadataretriever.cpp
@@ -0,0 +1,188 @@
+/*
+**
+** 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_NDEBUG 0
+#define LOG_TAG "MediaMetadataRetriever"
+
+#include <utils/IServiceManager.h>
+#include <utils/IPCThreadState.h>
+#include <media/mediametadataretriever.h>
+#include <media/IMediaPlayerService.h>
+#include <utils/Log.h>
+#include <dlfcn.h>
+
+namespace android {
+
+// client singleton for binder interface to service
+Mutex MediaMetadataRetriever::sServiceLock;
+sp<IMediaPlayerService> MediaMetadataRetriever::sService;
+sp<MediaMetadataRetriever::DeathNotifier> MediaMetadataRetriever::sDeathNotifier;
+
+const sp<IMediaPlayerService>& MediaMetadataRetriever::getService()
+{
+    Mutex::Autolock lock(sServiceLock);
+    if (sService.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 (sDeathNotifier == NULL) {
+            sDeathNotifier = new DeathNotifier();
+        }
+        binder->linkToDeath(sDeathNotifier);
+        sService = interface_cast<IMediaPlayerService>(binder);
+    }
+    LOGE_IF(sService == 0, "no MediaPlayerService!?");
+    return sService;
+}
+
+MediaMetadataRetriever::MediaMetadataRetriever()
+{
+    LOGV("constructor");
+    const sp<IMediaPlayerService>& service(getService());
+    if (service == 0) {
+        LOGE("failed to obtain MediaMetadataRetrieverService");
+        return;
+    }
+    sp<IMediaMetadataRetriever> retriever(service->createMetadataRetriever(getpid()));
+    if (retriever == 0) {
+        LOGE("failed to create IMediaMetadataRetriever object from server");
+    }
+    mRetriever = retriever;
+}
+
+MediaMetadataRetriever::~MediaMetadataRetriever()
+{
+    LOGV("destructor");
+    disconnect();
+    IPCThreadState::self()->flushCommands();
+}
+
+void MediaMetadataRetriever::disconnect()
+{
+    LOGV("disconnect");
+    sp<IMediaMetadataRetriever> retriever;
+    {
+        Mutex::Autolock _l(mLock);
+        retriever = mRetriever;
+        mRetriever.clear();
+    }
+    if (retriever != 0) {
+        retriever->disconnect();
+    }
+}
+
+status_t MediaMetadataRetriever::setDataSource(const char* srcUrl)
+{
+    LOGV("setDataSource");
+    if (mRetriever == 0) {
+        LOGE("retriever is not initialized");
+        return INVALID_OPERATION;
+    }
+    if (srcUrl == NULL) {
+        LOGE("data source is a null pointer");
+        return UNKNOWN_ERROR;
+    }
+    LOGV("data source (%s)", srcUrl);
+    return mRetriever->setDataSource(srcUrl);
+}
+
+status_t MediaMetadataRetriever::setDataSource(int fd, int64_t offset, int64_t length)
+{
+    LOGV("setDataSource(%d, %lld, %lld)", fd, offset, length);
+    if (mRetriever == 0) {
+        LOGE("retriever is not initialized");
+        return INVALID_OPERATION;
+    }
+    if (fd < 0 || offset < 0 || length < 0) {
+        LOGE("Invalid negative argument");
+        return UNKNOWN_ERROR;
+    }
+    return mRetriever->setDataSource(fd, offset, length);
+}
+
+status_t MediaMetadataRetriever::setMode(int mode)
+{
+    LOGV("setMode(%d)", mode);
+    if (mRetriever == 0) {
+        LOGE("retriever is not initialized");
+        return INVALID_OPERATION;
+    }
+    return mRetriever->setMode(mode);
+}
+
+status_t MediaMetadataRetriever::getMode(int* mode)
+{
+    LOGV("getMode");
+    if (mRetriever == 0) {
+        LOGE("retriever is not initialized");
+        return INVALID_OPERATION;
+    }
+    return mRetriever->getMode(mode);
+}
+
+sp<IMemory> MediaMetadataRetriever::captureFrame()
+{
+    LOGV("captureFrame");
+    if (mRetriever == 0) {
+        LOGE("retriever is not initialized");
+        return NULL;
+    }
+    return mRetriever->captureFrame();
+}
+
+const char* MediaMetadataRetriever::extractMetadata(int keyCode)
+{
+    LOGV("extractMetadata(%d)", keyCode);
+    if (mRetriever == 0) {
+        LOGE("retriever is not initialized");
+        return NULL;
+    }
+    return mRetriever->extractMetadata(keyCode);
+}
+
+sp<IMemory> MediaMetadataRetriever::extractAlbumArt()
+{
+    LOGV("extractAlbumArt");
+    if (mRetriever == 0) {
+        LOGE("retriever is not initialized");
+        return NULL;
+    }
+    return mRetriever->extractAlbumArt();
+}
+
+void MediaMetadataRetriever::DeathNotifier::binderDied(const wp<IBinder>& who) {
+    Mutex::Autolock lock(MediaMetadataRetriever::sServiceLock);
+    MediaMetadataRetriever::sService.clear();
+    LOGW("MediaMetadataRetriever server died!");
+}
+
+MediaMetadataRetriever::DeathNotifier::~DeathNotifier()
+{
+    Mutex::Autolock lock(sServiceLock);
+    if (sService != 0) {
+        sService->asBinder()->unlinkToDeath(this);
+    }
+}
+
+}; // namespace android
diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp
new file mode 100644
index 0000000..bd8579c
--- /dev/null
+++ b/media/libmedia/mediaplayer.cpp
@@ -0,0 +1,624 @@
+/* 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 <media/AudioTrack.h>
+
+#include <utils/MemoryBase.h>
+
+namespace android {
+
+// client singleton for binder interface to service
+Mutex MediaPlayer::sServiceLock;
+sp<IMediaPlayerService> MediaPlayer::sMediaPlayerService;
+sp<MediaPlayer::DeathNotifier> MediaPlayer::sDeathNotifier;
+SortedVector< wp<MediaPlayer> > MediaPlayer::sObitRecipients;
+
+// establish binder interface to service
+const sp<IMediaPlayerService>& MediaPlayer::getMediaPlayerService()
+{
+    Mutex::Autolock _l(sServiceLock);
+    if (sMediaPlayerService.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 (sDeathNotifier == NULL) {
+            sDeathNotifier = new DeathNotifier();
+        }
+        binder->linkToDeath(sDeathNotifier);
+        sMediaPlayerService = interface_cast<IMediaPlayerService>(binder);
+    }
+    LOGE_IF(sMediaPlayerService==0, "no MediaPlayerService!?");
+    return sMediaPlayerService;
+}
+
+void MediaPlayer::addObitRecipient(const wp<MediaPlayer>& recipient)
+{
+    Mutex::Autolock _l(sServiceLock);
+    sObitRecipients.add(recipient);
+}
+
+void MediaPlayer::removeObitRecipient(const wp<MediaPlayer>& recipient)
+{
+    Mutex::Autolock _l(sServiceLock);
+    sObitRecipients.remove(recipient);
+}
+
+MediaPlayer::MediaPlayer()
+{
+    LOGV("constructor");
+    mListener = NULL;
+    mCookie = NULL;
+    mDuration = -1;
+    mStreamType = AudioSystem::MUSIC;
+    mCurrentPosition = -1;
+    mSeekPosition = -1;
+    mCurrentState = MEDIA_PLAYER_IDLE;
+    mPrepareSync = false;
+    mPrepareStatus = NO_ERROR;
+    mLoop = false;
+    mLeftVolume = mRightVolume = 1.0;
+    mVideoWidth = mVideoHeight = 0;
+}
+
+void MediaPlayer::onFirstRef()
+{
+    addObitRecipient(this);
+}
+
+MediaPlayer::~MediaPlayer()
+{
+    LOGV("destructor");
+    removeObitRecipient(this);
+    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();
+    }
+}
+
+// always call with lock held
+void MediaPlayer::clear_l()
+{
+    mDuration = -1;
+    mCurrentPosition = -1;
+    mSeekPosition = -1;
+    mVideoWidth = mVideoHeight = 0;
+}
+
+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;
+            err = NO_ERROR;
+        } else {
+            LOGE("Unable to to create media player");
+        }
+    }
+
+    if (p != 0) {
+        p->disconnect();
+    }
+
+    return err;
+}
+
+status_t MediaPlayer::setDataSource(const char *url)
+{
+    LOGV("setDataSource(%s)", url);
+    status_t err = BAD_VALUE;
+    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 NO_INIT;
+    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 -EALREADY;
+    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;
+        } 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;
+        } 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;
+        } 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) return INVALID_OPERATION;
+    *w = mVideoWidth;
+    return NO_ERROR;
+}
+
+status_t MediaPlayer::getVideoHeight(int *h)
+{
+    LOGV("getVideoHeight");
+    Mutex::Autolock _l(mLock);
+    if (mPlayer == 0) return INVALID_OPERATION;
+    *h = mVideoHeight;
+    return NO_ERROR;
+}
+
+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) {
+            LOGE("reset() failed with return code (%d)", ret);
+            mCurrentState = MEDIA_PLAYER_STATE_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;
+}
+
+bool MediaPlayer::isLooping() {
+    LOGV("isLooping");
+    Mutex::Autolock _l(mLock);
+    if (mPlayer != 0) {
+        return mLoop;
+    }
+    LOGV("isLooping: no active player");
+    return false;
+}
+
+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);
+        mLock.unlock();   // release the lock when done.
+        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:
+        // Always log errors
+        LOGE("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;
+    case MEDIA_SET_VIDEO_SIZE:
+        LOGV("New video size %d x %d", ext1, ext2);
+        mVideoWidth = ext1;
+        mVideoHeight = ext2;
+        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::DeathNotifier::binderDied(const wp<IBinder>& who) {
+    LOGW("MediaPlayer server died!");
+
+    // Need to do this with the lock held
+    SortedVector< wp<MediaPlayer> > list;
+    {
+        Mutex::Autolock _l(MediaPlayer::sServiceLock);
+        MediaPlayer::sMediaPlayerService.clear();
+        list = sObitRecipients;
+    }
+
+    // Notify application when media server dies.
+    // Don't hold the static lock during callback in case app
+    // makes a call that needs the lock.
+    size_t count = list.size();
+    for (size_t iter = 0; iter < count; ++iter) {
+        sp<MediaPlayer> player = list[iter].promote();
+        if ((player != 0) && (player->mPlayer != 0)) {
+            player->notify(MEDIA_ERROR, MEDIA_ERROR_SERVER_DIED, 0);
+        }
+    }
+}
+
+MediaPlayer::DeathNotifier::~DeathNotifier()
+{
+    Mutex::Autolock _l(sServiceLock);
+    sObitRecipients.clear();
+    if (sMediaPlayerService != 0) {
+        sMediaPlayerService->asBinder()->unlinkToDeath(this);
+    }
+}
+
+/*static*/ sp<IMemory> MediaPlayer::decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat)
+{
+    LOGV("decode(%s)", url);
+    sp<IMemory> p;
+    const sp<IMediaPlayerService>& service = getMediaPlayerService();
+    if (service != 0) {
+        p = sMediaPlayerService->decode(url, pSampleRate, pNumChannels, pFormat);
+    } 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, int* pFormat)
+{
+    LOGV("decode(%d, %lld, %lld)", fd, offset, length);
+    sp<IMemory> p;
+    const sp<IMediaPlayerService>& service = getMediaPlayerService();
+    if (service != 0) {
+        p = sMediaPlayerService->decode(fd, offset, length, pSampleRate, pNumChannels, pFormat);
+    } else {
+        LOGE("Unable to locate media service");
+    }
+    return p;
+
+}
+
+}; // namespace android
diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp
new file mode 100644
index 0000000..98aac39
--- /dev/null
+++ b/media/libmedia/mediarecorder.cpp
@@ -0,0 +1,617 @@
+/*
+ **
+ ** 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 "MediaRecorder"
+#include <utils/Log.h>
+#include <ui/Surface.h>
+#include <media/mediarecorder.h>
+#include <utils/IServiceManager.h>
+#include <media/IMediaPlayerService.h>
+#include <media/IMediaRecorder.h>
+
+namespace android {
+
+status_t MediaRecorder::setCamera(const sp<ICamera>& camera)
+{
+    LOGV("setCamera(%p)", camera.get());
+    if(mMediaRecorder == NULL) {
+        LOGE("media recorder is not initialized yet");
+        return INVALID_OPERATION;
+    }
+    if (!(mCurrentState & MEDIA_RECORDER_IDLE)) {
+        LOGE("setCamera called in an invalid state(%d)", mCurrentState);
+        return INVALID_OPERATION;
+    }
+
+    status_t ret = mMediaRecorder->setCamera(camera);
+    if (OK != ret) {
+        LOGV("setCamera failed: %d", ret);
+        mCurrentState = MEDIA_RECORDER_ERROR;
+        return UNKNOWN_ERROR;
+    }
+    return ret;
+}
+
+status_t MediaRecorder::setPreviewSurface(const sp<Surface>& surface)
+{
+    LOGV("setPreviewSurface(%p)", surface.get());
+    if(mMediaRecorder == NULL) {
+        LOGE("media recorder is not initialized yet");
+        return INVALID_OPERATION;
+    }
+    if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) {
+        LOGE("setPreviewSurface called in an invalid state(%d)", mCurrentState);
+        return INVALID_OPERATION;
+    }
+    if (!mIsVideoSourceSet) {
+        LOGE("try to set preview surface without setting the video source first");
+        return INVALID_OPERATION;
+    }
+
+    status_t ret = mMediaRecorder->setPreviewSurface(surface->getISurface());
+    if (OK != ret) {
+        LOGV("setPreviewSurface failed: %d", ret);
+        mCurrentState = MEDIA_RECORDER_ERROR;
+        return UNKNOWN_ERROR;
+    }
+    return ret;
+}
+
+status_t MediaRecorder::init()
+{
+    LOGV("init");
+    if(mMediaRecorder == NULL) {
+        LOGE("media recorder is not initialized yet");
+        return INVALID_OPERATION;
+    }
+    if (!(mCurrentState & MEDIA_RECORDER_IDLE)) {
+        LOGE("init called in an invalid state(%d)", mCurrentState);
+        return INVALID_OPERATION;
+    }
+
+    status_t ret = mMediaRecorder->init();
+    if (OK != ret) {
+        LOGV("init failed: %d", ret);
+        mCurrentState = MEDIA_RECORDER_ERROR;
+        return UNKNOWN_ERROR;
+    }
+
+    ret = mMediaRecorder->setListener(this);
+    if (OK != ret) {
+        LOGV("setListener failed: %d", ret);
+        mCurrentState = MEDIA_RECORDER_ERROR;
+        return UNKNOWN_ERROR;
+    }
+
+    mCurrentState = MEDIA_RECORDER_INITIALIZED;
+    return ret;
+}
+
+status_t MediaRecorder::setVideoSource(int vs)
+{
+    LOGV("setVideoSource(%d)", vs);
+    if(mMediaRecorder == NULL) {
+        LOGE("media recorder is not initialized yet");
+        return INVALID_OPERATION;
+    }
+    if (mIsVideoSourceSet) {
+        LOGE("video source has already been set");
+        return INVALID_OPERATION;
+    }
+    if (mCurrentState & MEDIA_RECORDER_IDLE) {
+        LOGV("Call init() since the media recorder is not initialized yet");
+        status_t ret = init();
+        if (OK != ret) {
+            return ret;
+        }
+    }
+    if (!(mCurrentState & MEDIA_RECORDER_INITIALIZED)) {
+        LOGE("setVideoSource called in an invalid state(%d)", mCurrentState);
+        return INVALID_OPERATION;
+    }
+
+    status_t ret = mMediaRecorder->setVideoSource(vs);
+    if (OK != ret) {
+        LOGV("setVideoSource failed: %d", ret);
+        mCurrentState = MEDIA_RECORDER_ERROR;
+        return UNKNOWN_ERROR;
+    }
+    mIsVideoSourceSet = true;
+    return ret;
+}
+
+status_t MediaRecorder::setAudioSource(int as)
+{
+    LOGV("setAudioSource(%d)", as);
+    if(mMediaRecorder == NULL) {
+        LOGE("media recorder is not initialized yet");
+        return INVALID_OPERATION;
+    }
+    if (mCurrentState & MEDIA_RECORDER_IDLE) {
+        LOGV("Call init() since the media recorder is not initialized yet");
+        status_t ret = init();
+        if (OK != ret) {
+            return ret;
+        }
+    }
+    if (mIsAudioSourceSet) {
+        LOGE("audio source has already been set");
+        return INVALID_OPERATION;
+    }
+    if (!(mCurrentState & MEDIA_RECORDER_INITIALIZED)) {
+        LOGE("setAudioSource called in an invalid state(%d)", mCurrentState);
+        return INVALID_OPERATION;
+    }
+
+    status_t ret = mMediaRecorder->setAudioSource(as);
+    if (OK != ret) {
+        LOGV("setAudioSource failed: %d", ret);
+        mCurrentState = MEDIA_RECORDER_ERROR;
+        return UNKNOWN_ERROR;
+    }
+    mIsAudioSourceSet = true;
+    return ret;
+}
+
+status_t MediaRecorder::setOutputFormat(int of)
+{
+    LOGV("setOutputFormat(%d)", of);
+    if(mMediaRecorder == NULL) {
+        LOGE("media recorder is not initialized yet");
+        return INVALID_OPERATION;
+    }
+    if (!(mCurrentState & MEDIA_RECORDER_INITIALIZED)) {
+        LOGE("setOutputFormat called in an invalid state: %d", mCurrentState);
+        return INVALID_OPERATION;
+    }
+    if (mIsVideoSourceSet && of >= OUTPUT_FORMAT_RAW_AMR) {
+        LOGE("output format (%d) is meant for audio recording only and incompatible with video recording", of);
+        return INVALID_OPERATION;
+    }
+
+    status_t ret = mMediaRecorder->setOutputFormat(of);
+    if (OK != ret) {
+        LOGE("setOutputFormat failed: %d", ret);
+        mCurrentState = MEDIA_RECORDER_ERROR;
+        return UNKNOWN_ERROR;
+    }
+    mCurrentState = MEDIA_RECORDER_DATASOURCE_CONFIGURED;
+    return ret;
+}
+
+status_t MediaRecorder::setVideoEncoder(int ve)
+{
+    LOGV("setVideoEncoder(%d)", ve);
+    if(mMediaRecorder == NULL) {
+        LOGE("media recorder is not initialized yet");
+        return INVALID_OPERATION;
+    }
+    if (!mIsVideoSourceSet) {
+        LOGE("try to set the video encoder without setting the video source first");
+        return INVALID_OPERATION;
+    }
+    if (mIsVideoEncoderSet) {
+        LOGE("video encoder has already been set");
+        return INVALID_OPERATION;
+    }
+    if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) {
+        LOGE("setVideoEncoder called in an invalid state(%d)", mCurrentState);
+        return INVALID_OPERATION;
+    }
+
+    status_t ret = mMediaRecorder->setVideoEncoder(ve);
+    if (OK != ret) {
+        LOGV("setVideoEncoder failed: %d", ret);
+        mCurrentState = MEDIA_RECORDER_ERROR;
+        return UNKNOWN_ERROR;
+    }
+    mIsVideoEncoderSet = true;
+    return ret;
+}
+
+status_t MediaRecorder::setAudioEncoder(int ae)
+{
+    LOGV("setAudioEncoder(%d)", ae);
+    if(mMediaRecorder == NULL) {
+        LOGE("media recorder is not initialized yet");
+        return INVALID_OPERATION;
+    }
+    if (!mIsAudioSourceSet) {
+        LOGE("try to set the audio encoder without setting the audio source first");
+        return INVALID_OPERATION;
+    }
+    if (mIsAudioEncoderSet) {
+        LOGE("audio encoder has already been set");
+        return INVALID_OPERATION;
+    }
+    if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) {
+        LOGE("setAudioEncoder called in an invalid state(%d)", mCurrentState);
+        return INVALID_OPERATION;
+    }
+
+    status_t ret = mMediaRecorder->setAudioEncoder(ae);
+    if (OK != ret) {
+        LOGV("setAudioEncoder failed: %d", ret);
+        mCurrentState = MEDIA_RECORDER_ERROR;
+        return UNKNOWN_ERROR;
+    }
+    mIsAudioEncoderSet = true;
+    return ret;
+}
+
+status_t MediaRecorder::setOutputFile(const char* path)
+{
+    LOGV("setOutputFile(%s)", path);
+    if(mMediaRecorder == NULL) {
+        LOGE("media recorder is not initialized yet");
+        return INVALID_OPERATION;
+    }
+    if (mIsOutputFileSet) {
+        LOGE("output file has already been set");
+        return INVALID_OPERATION;
+    }
+    if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) {
+        LOGE("setOutputFile called in an invalid state(%d)", mCurrentState);
+        return INVALID_OPERATION;
+    }
+
+    status_t ret = mMediaRecorder->setOutputFile(path);
+    if (OK != ret) {
+        LOGV("setOutputFile failed: %d", ret);
+        mCurrentState = MEDIA_RECORDER_ERROR;
+        return UNKNOWN_ERROR;
+    }
+    mIsOutputFileSet = true;
+    return ret;
+}
+
+status_t MediaRecorder::setOutputFile(int fd, int64_t offset, int64_t length)
+{
+    LOGV("setOutputFile(%d, %lld, %lld)", fd, offset, length);
+    if(mMediaRecorder == NULL) {
+        LOGE("media recorder is not initialized yet");
+        return INVALID_OPERATION;
+    }
+    if (mIsOutputFileSet) {
+        LOGE("output file has already been set");
+        return INVALID_OPERATION;
+    }
+    if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) {
+        LOGE("setOutputFile called in an invalid state(%d)", mCurrentState);
+        return INVALID_OPERATION;
+    }
+
+    status_t ret = mMediaRecorder->setOutputFile(fd, offset, length);
+    if (OK != ret) {
+        LOGV("setOutputFile failed: %d", ret);
+        mCurrentState = MEDIA_RECORDER_ERROR;
+        return UNKNOWN_ERROR;
+    }
+    mIsOutputFileSet = true;
+    return ret;
+}
+
+status_t MediaRecorder::setVideoSize(int width, int height)
+{
+    LOGV("setVideoSize(%d, %d)", width, height);
+    if(mMediaRecorder == NULL) {
+        LOGE("media recorder is not initialized yet");
+        return INVALID_OPERATION;
+    }
+    if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) {
+        LOGE("setVideoSize called in an invalid state: %d", mCurrentState);
+        return INVALID_OPERATION;
+    }
+    if (!mIsVideoSourceSet) {
+        LOGE("try to set video size without setting video source first");
+        return INVALID_OPERATION;
+    }
+
+    status_t ret = mMediaRecorder->setVideoSize(width, height);
+    if (OK != ret) {
+        LOGE("setVideoSize failed: %d", ret);
+        mCurrentState = MEDIA_RECORDER_ERROR;
+        return UNKNOWN_ERROR;
+    }
+    return ret;
+}
+
+status_t MediaRecorder::setVideoFrameRate(int frames_per_second)
+{
+    LOGV("setVideoFrameRate(%d)", frames_per_second);
+    if(mMediaRecorder == NULL) {
+        LOGE("media recorder is not initialized yet");
+        return INVALID_OPERATION;
+    }
+    if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) {
+        LOGE("setVideoFrameRate called in an invalid state: %d", mCurrentState);
+        return INVALID_OPERATION;
+    }
+    if (!mIsVideoSourceSet) {
+        LOGE("try to set video frame rate without setting video source first");
+        return INVALID_OPERATION; 
+    }
+
+    status_t ret = mMediaRecorder->setVideoFrameRate(frames_per_second);
+    if (OK != ret) {
+        LOGE("setVideoFrameRate failed: %d", ret);
+        mCurrentState = MEDIA_RECORDER_ERROR;
+        return UNKNOWN_ERROR;
+    }
+    return ret;
+}
+
+status_t MediaRecorder::prepare()
+{
+    LOGV("prepare");
+    if(mMediaRecorder == NULL) {
+        LOGE("media recorder is not initialized yet");
+        return INVALID_OPERATION;
+    }
+    if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) {
+        LOGE("prepare called in an invalid state: %d", mCurrentState);
+        return INVALID_OPERATION;
+    }
+    if (mIsAudioSourceSet != mIsAudioEncoderSet) {
+        if (mIsAudioSourceSet) {
+            LOGE("audio source is set, but audio encoder is not set");
+        } else {  // must not happen, since setAudioEncoder checks this already
+            LOGE("audio encoder is set, but audio source is not set");
+        }
+        return INVALID_OPERATION;
+    }
+
+    if (mIsVideoSourceSet != mIsVideoEncoderSet) {
+        if (mIsVideoSourceSet) {
+            LOGE("video source is set, but video encoder is not set");
+        } else {  // must not happen, since setVideoEncoder checks this already
+            LOGE("video encoder is set, but video source is not set");
+        }
+        return INVALID_OPERATION;
+    }
+
+    status_t ret = mMediaRecorder->prepare();
+    if (OK != ret) {
+        LOGE("prepare failed: %d", ret);
+        mCurrentState = MEDIA_RECORDER_ERROR;
+        return UNKNOWN_ERROR;
+    }
+    mCurrentState = MEDIA_RECORDER_PREPARED;
+    return ret;
+}
+
+status_t MediaRecorder::getMaxAmplitude(int* max)
+{
+    LOGV("getMaxAmplitude");
+    if(mMediaRecorder == NULL) {
+        LOGE("media recorder is not initialized yet");
+        return INVALID_OPERATION;
+    }
+    if (mCurrentState & MEDIA_RECORDER_ERROR) {
+        LOGE("getMaxAmplitude called in an invalid state: %d", mCurrentState);
+        return INVALID_OPERATION;
+    }
+
+    status_t ret = mMediaRecorder->getMaxAmplitude(max);
+    if (OK != ret) {
+        LOGE("getMaxAmplitude failed: %d", ret);
+        mCurrentState = MEDIA_RECORDER_ERROR;
+        return UNKNOWN_ERROR;
+    }
+    return ret;
+}
+
+status_t MediaRecorder::start()
+{
+    LOGV("start");
+    if (mMediaRecorder == NULL) {
+        LOGE("media recorder is not initialized yet");
+        return INVALID_OPERATION;
+    }
+    if (!(mCurrentState & MEDIA_RECORDER_PREPARED)) {
+        LOGE("start called in an invalid state: %d", mCurrentState);
+        return INVALID_OPERATION;
+    }
+
+    status_t ret = mMediaRecorder->start();
+    if (OK != ret) {
+        LOGE("start failed: %d", ret);
+        mCurrentState = MEDIA_RECORDER_ERROR;
+        return UNKNOWN_ERROR;
+    }
+    mCurrentState = MEDIA_RECORDER_RECORDING;
+    return ret;
+}
+
+status_t MediaRecorder::stop()
+{
+    LOGV("stop");
+    if (mMediaRecorder == NULL) {
+        LOGE("media recorder is not initialized yet");
+        return INVALID_OPERATION;
+    }
+    if (!(mCurrentState & MEDIA_RECORDER_RECORDING)) {
+        LOGE("stop called in an invalid state: %d", mCurrentState);
+        return INVALID_OPERATION;
+    }
+
+    status_t ret = mMediaRecorder->stop();
+    if (OK != ret) {
+        LOGE("stop failed: %d", ret);
+        mCurrentState = MEDIA_RECORDER_ERROR;
+        return UNKNOWN_ERROR;
+    }
+    mCurrentState = MEDIA_RECORDER_IDLE;
+    return ret;
+}
+
+// Reset should be OK in any state
+status_t MediaRecorder::reset()
+{
+    LOGV("reset");
+    if (mMediaRecorder == NULL) {
+        LOGE("media recorder is not initialized yet");
+        return INVALID_OPERATION;
+    }
+    
+    doCleanUp();
+    status_t ret = UNKNOWN_ERROR;
+    switch(mCurrentState) {
+        case MEDIA_RECORDER_IDLE:
+            ret = OK;
+            break;
+
+        case MEDIA_RECORDER_RECORDING:
+        case MEDIA_RECORDER_DATASOURCE_CONFIGURED:
+        case MEDIA_RECORDER_PREPARED:
+        case MEDIA_RECORDER_ERROR: {
+            ret = doReset();
+            if (OK != ret) {
+               return ret;  // No need to continue
+            }
+        }  // Intentional fall through
+        case MEDIA_RECORDER_INITIALIZED:
+            ret = close();
+            break;
+
+        default: {
+            LOGE("Unexpected non-existing state: %d", mCurrentState);
+            break;
+        }
+    }
+    return ret;
+}
+
+status_t MediaRecorder::close()
+{
+    LOGV("close");
+    if (!(mCurrentState & MEDIA_RECORDER_INITIALIZED)) {
+        LOGE("close called in an invalid state: %d", mCurrentState);
+        return INVALID_OPERATION;
+    }
+    status_t ret = mMediaRecorder->close();
+    if (OK != ret) {
+        LOGE("close failed: %d", ret);
+        mCurrentState = MEDIA_RECORDER_ERROR;
+        return UNKNOWN_ERROR;
+    } else {
+        mCurrentState = MEDIA_RECORDER_IDLE;
+    }
+    return ret;
+}
+
+status_t MediaRecorder::doReset()
+{
+    LOGV("doReset");
+    status_t ret = mMediaRecorder->reset();
+    if (OK != ret) {
+        LOGE("doReset failed: %d", ret);
+        mCurrentState = MEDIA_RECORDER_ERROR;
+        return UNKNOWN_ERROR;
+    } else {
+        mCurrentState = MEDIA_RECORDER_INITIALIZED;
+    }
+    return ret;
+}
+
+void MediaRecorder::doCleanUp()
+{
+    LOGV("doCleanUp");
+    mIsAudioSourceSet  = false;
+    mIsVideoSourceSet  = false;
+    mIsAudioEncoderSet = false;
+    mIsVideoEncoderSet = false;
+    mIsOutputFileSet   = false;
+}
+
+// Release should be OK in any state
+status_t MediaRecorder::release()
+{
+    LOGV("release");
+    if (mMediaRecorder != NULL) {
+        return mMediaRecorder->release();
+    }
+    return INVALID_OPERATION;
+}
+
+MediaRecorder::MediaRecorder()
+{
+    LOGV("constructor");
+    sp<IServiceManager> sm = defaultServiceManager();
+    sp<IBinder> binder;
+
+    do {
+        binder = sm->getService(String16("media.player"));
+        if (binder != NULL) {
+            break;
+        }
+        LOGW("MediaPlayerService not published, waiting...");
+        usleep(500000); // 0.5 s
+    } while(true);
+
+    sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
+    if (service != NULL) {
+        mMediaRecorder = service->createMediaRecorder(getpid());
+    }
+    if (mMediaRecorder != NULL) {
+        mCurrentState = MEDIA_RECORDER_IDLE;
+    }
+    doCleanUp();
+}
+
+status_t MediaRecorder::initCheck()
+{
+    return mMediaRecorder != 0 ? NO_ERROR : NO_INIT;
+}
+
+MediaRecorder::~MediaRecorder()
+{
+    LOGV("destructor");
+    if (mMediaRecorder != NULL) {
+        mMediaRecorder.clear();
+    }
+}
+
+status_t MediaRecorder::setListener(const sp<MediaRecorderListener>& listener)
+{
+    LOGV("setListener");
+    Mutex::Autolock _l(mLock);
+    mListener = listener;
+
+    return NO_ERROR;
+}
+
+void MediaRecorder::notify(int msg, int ext1, int ext2)
+{
+    LOGV("message received msg=%d, ext1=%d, ext2=%d", msg, ext1, ext2);
+
+    sp<MediaRecorderListener> listener;
+    mLock.lock();
+    listener = mListener;
+    mLock.unlock();
+
+    if (listener != NULL) {
+        Mutex::Autolock _l(mNotifyLock);
+        LOGV("callback application");
+        listener->notify(msg, ext1, ext2);
+        LOGV("back from callback");
+    }
+}
+
+}; // namespace android
+
diff --git a/media/libmediaplayerservice/Android.mk b/media/libmediaplayerservice/Android.mk
new file mode 100644
index 0000000..f710921
--- /dev/null
+++ b/media/libmediaplayerservice/Android.mk
@@ -0,0 +1,36 @@
+LOCAL_PATH:= $(call my-dir)
+
+#
+# libmediaplayerservice
+#
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:=               \
+	MediaRecorderClient.cpp \
+	MediaPlayerService.cpp \
+	MetadataRetrieverClient.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 \
+	libopencoreauthor \
+	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..40705c6
--- /dev/null
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -0,0 +1,1173 @@
+/*
+**
+** 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 <cutils/properties.h>
+
+#include <media/MediaPlayerInterface.h>
+#include <media/mediarecorder.h>
+#include <media/MediaMetadataRetrieverInterface.h>
+#include <media/AudioTrack.h>
+
+#include "MediaRecorderClient.h"
+#include "MediaPlayerService.h"
+#include "MetadataRetrieverClient.h"
+
+#include "MidiFile.h"
+#include "VorbisPlayer.h"
+#include <media/PVPlayer.h>
+
+/* 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
+
+
+namespace android {
+
+// TODO: Temp hack until we can register players
+typedef struct {
+    const char *extension;
+    const player_type playertype;
+} extmap;
+extmap FILE_EXTS [] =  {
+        {".mid", SONIVOX_PLAYER},
+        {".midi", SONIVOX_PLAYER},
+        {".smf", SONIVOX_PLAYER},
+        {".xmf", SONIVOX_PLAYER},
+        {".imy", SONIVOX_PLAYER},
+        {".rtttl", SONIVOX_PLAYER},
+        {".rtx", SONIVOX_PLAYER},
+        {".ota", SONIVOX_PLAYER},
+        {".ogg", VORBIS_PLAYER},
+        {".oga", VORBIS_PLAYER},
+};
+
+// TODO: Find real cause of Audio/Video delay in PV framework and remove this workaround
+/* static */ const uint32_t MediaPlayerService::AudioOutput::kAudioVideoDelayMs = 96;
+/* static */ int MediaPlayerService::AudioOutput::mMinBufferCount = 4;
+/* static */ bool MediaPlayerService::AudioOutput::mIsOnEmulator = false;
+
+void MediaPlayerService::instantiate() {
+    defaultServiceManager()->addService(
+            String16("media.player"), new MediaPlayerService());
+}
+
+MediaPlayerService::MediaPlayerService()
+{
+    LOGV("MediaPlayerService created");
+    mNextConnId = 1;
+}
+
+MediaPlayerService::~MediaPlayerService()
+{
+    LOGV("MediaPlayerService destroyed");
+}
+
+sp<IMediaRecorder> MediaPlayerService::createMediaRecorder(pid_t pid)
+{
+    sp<MediaRecorderClient> recorder = new MediaRecorderClient(pid);
+    LOGV("Create new media recorder client from pid %d", pid);
+    return recorder;
+}
+
+sp<IMediaMetadataRetriever> MediaPlayerService::createMetadataRetriever(pid_t pid)
+{
+    sp<MetadataRetrieverClient> retriever = new MetadataRetrieverClient(pid);
+    LOGV("Create new media retriever from pid %d", pid);
+    return retriever;
+}
+
+sp<IMediaPlayer> MediaPlayerService::create(pid_t pid, const sp<IMediaPlayerClient>& client, const char* url)
+{
+    int32_t connId = android_atomic_inc(&mNextConnId);
+    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(%d), format(%d), frame count(%ld)\n",
+            mMsecsPerFrame, mChannelCount, mFormat, mFrameCount);
+    result.append(buffer);
+    snprintf(buffer, 255, "  sample rate(%d), size(%d), error(%d), command complete(%s)\n",
+            mSampleRate, mSize, mError, mCommandComplete?"true":"false");
+    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)\n",
+            mMsecsPerFrame, mLatency);
+    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
+}
+
+#if defined(__arm__)
+extern "C" void get_malloc_leak_info(uint8_t** info, size_t* overallSize,
+        size_t* infoSize, size_t* totalMemory, size_t* backtraceSize);
+extern "C" void free_malloc_leak_info(uint8_t* info);
+
+void memStatus(int fd, const Vector<String16>& args)
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+
+    typedef struct {
+        size_t size;
+        size_t dups;
+        intptr_t * backtrace;
+    } AllocEntry;
+
+    uint8_t *info = NULL;
+    size_t overallSize = 0;
+    size_t infoSize = 0;
+    size_t totalMemory = 0;
+    size_t backtraceSize = 0;
+
+    get_malloc_leak_info(&info, &overallSize, &infoSize, &totalMemory, &backtraceSize);
+    if (info) {
+        uint8_t *ptr = info;
+        size_t count = overallSize / infoSize;
+
+        snprintf(buffer, SIZE, " Allocation count %i\n", count);
+        result.append(buffer);
+
+        AllocEntry * entries = new AllocEntry[count];
+
+        for (size_t i = 0; i < count; i++) {
+            // Each entry should be size_t, size_t, intptr_t[backtraceSize]
+            AllocEntry *e = &entries[i];
+
+            e->size = *reinterpret_cast<size_t *>(ptr);
+            ptr += sizeof(size_t);
+
+            e->dups = *reinterpret_cast<size_t *>(ptr);
+            ptr += sizeof(size_t);
+
+            e->backtrace = reinterpret_cast<intptr_t *>(ptr);
+            ptr += sizeof(intptr_t) * backtraceSize;
+        }
+
+        // Now we need to sort the entries.  They come sorted by size but
+        // not by stack trace which causes problems using diff.
+        bool moved;
+        do {
+            moved = false;
+            for (size_t i = 0; i < (count - 1); i++) {
+                AllocEntry *e1 = &entries[i];
+                AllocEntry *e2 = &entries[i+1];
+
+                bool swap = e1->size < e2->size;
+                if (e1->size == e2->size) {
+                    for(size_t j = 0; j < backtraceSize; j++) {
+                        if (e1->backtrace[j] == e2->backtrace[j]) {
+                            continue;
+                        }
+                        swap = e1->backtrace[j] < e2->backtrace[j];
+                        break;
+                    }
+                }
+                if (swap) {
+                    AllocEntry t = entries[i];
+                    entries[i] = entries[i+1];
+                    entries[i+1] = t;
+                    moved = true;
+                }
+            }
+        } while (moved);
+
+        for (size_t i = 0; i < count; i++) {
+            AllocEntry *e = &entries[i];
+
+            snprintf(buffer, SIZE, "size %8i, dup %4i", e->size, e->dups);
+            result.append(buffer);
+            for (size_t ct = 0; (ct < backtraceSize) && e->backtrace[ct]; ct++) {
+                if (ct) {
+                    result.append(", ");
+                }
+                snprintf(buffer, SIZE, "0x%08x", e->backtrace[ct]);
+                result.append(buffer);
+            }
+            result.append("\n");
+        }
+
+        delete[] entries;
+        free_malloc_leak_info(info);
+    }
+
+    write(fd, result.string(), result.size());
+}
+#endif
+
+status_t MediaPlayerService::dump(int fd, const Vector<String16>& args)
+{
+    const size_t SIZE = 256;
+    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");
+        }
+
+#if defined(__arm__)
+        bool dumpMem = false;
+        for (size_t i = 0; i < args.size(); i++) {
+            if (args[i] == String16("-m")) {
+                dumpMem = true;
+            }
+        }
+        if (dumpMem) {
+            memStatus(fd, args);
+        }
+#endif
+    }
+    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) == 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(FILE_EXTS); ++i) {
+        int len = strlen(FILE_EXTS[i].extension);
+        int start = lenURL - len;
+        if (start > 0) {
+            if (!strncmp(url + start, FILE_EXTS[i].extension, len)) {
+                return FILE_EXTS[i].playertype;
+            }
+        }
+    }
+
+    // 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);
+        } 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::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, int* pFormat)
+{
+    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();
+    *pFormat = cache->format();
+    LOGV("return memory @ %p, sampleRate=%u, channelCount = %d, format = %d", mem->pointer(), *pSampleRate, *pNumChannels, *pFormat);
+
+Exit:
+    if (player != 0) player->reset();
+    return mem;
+}
+
+sp<IMemory> MediaPlayerService::decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat)
+{
+    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();
+    *pFormat = cache->format();
+    LOGV("return memory @ %p, sampleRate=%u, channelCount = %d, format = %d", mem->pointer(), *pSampleRate, *pNumChannels, *pFormat);
+
+Exit:
+    if (player != 0) player->reset();
+    ::close(fd);
+    return mem;
+}
+
+#undef LOG_TAG
+#define LOG_TAG "AudioSink"
+MediaPlayerService::AudioOutput::AudioOutput()
+{
+    mTrack = 0;
+    mStreamType = AudioSystem::MUSIC;
+    mLeftVolume = 1.0;
+    mRightVolume = 1.0;
+    mLatency = 0;
+    mMsecsPerFrame = 0;
+    setMinBufferCount();
+}
+
+MediaPlayerService::AudioOutput::~AudioOutput()
+{
+    close();
+}
+
+void MediaPlayerService::AudioOutput::setMinBufferCount()
+{
+    char value[PROPERTY_VALUE_MAX];
+    if (property_get("ro.kernel.qemu", value, 0)) {
+        mIsOnEmulator = true;
+        mMinBufferCount = 12;  // to prevent systematic buffer underrun for emulator
+    }
+}
+
+bool MediaPlayerService::AudioOutput::isOnEmulator()
+{
+    setMinBufferCount();
+    return mIsOnEmulator;
+}
+
+int MediaPlayerService::AudioOutput::getMinBufferCount()
+{
+    setMinBufferCount();
+    return mMinBufferCount;
+}
+
+ssize_t MediaPlayerService::AudioOutput::bufferSize() const
+{
+    if (mTrack == 0) return NO_INIT;
+    return mTrack->frameCount() * frameSize();
+}
+
+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->frameSize();
+}
+
+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 format, int bufferCount)
+{
+    // Check argument "bufferCount" against the mininum buffer count
+    if (bufferCount < mMinBufferCount) {
+        LOGD("bufferCount (%d) is too small and increased to %d", bufferCount, mMinBufferCount);
+        bufferCount = mMinBufferCount;
+
+    }
+    LOGV("open(%u, %d, %d, %d)", sampleRate, channelCount, format, bufferCount);
+    if (mTrack) close();
+    int afSampleRate;
+    int afFrameCount;
+    int frameCount;
+
+    if (AudioSystem::getOutputFrameCount(&afFrameCount, mStreamType) != NO_ERROR) {
+        return NO_INIT;
+    }
+    if (AudioSystem::getOutputSamplingRate(&afSampleRate, mStreamType) != NO_ERROR) {
+        return NO_INIT;
+    }
+
+    frameCount = (sampleRate*afFrameCount*bufferCount)/afSampleRate;
+    AudioTrack *t = new AudioTrack(mStreamType, sampleRate, format, channelCount, frameCount);
+    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 = t->latency() + kAudioVideoDelayMs;
+    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(1024), 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 format, int bufferCount)
+{
+    LOGV("open(%u, %d, %d, %d)", sampleRate, channelCount, format, bufferCount);
+    if (mHeap->getHeapID() < 0) return NO_INIT;
+    mSampleRate = sampleRate;
+    mChannelCount = (uint16_t)channelCount;
+    mFormat = (uint16_t)format;
+    mMsecsPerFrame = 1.e3 / (float) sampleRate;
+    return NO_ERROR;
+}
+
+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);
+    if (mSize + size > mHeap->getSize()) {
+        LOGE("Heap size overflow! req size: %d, max size: %d", (mSize + size), mHeap->getSize());
+        size = mHeap->getSize() - mSize;
+    }
+    memcpy(p, buffer, size);
+    mSize += size;
+    return size;
+}
+
+// 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..f138886
--- /dev/null
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -0,0 +1,238 @@
+/*
+**
+** 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>
+
+namespace android {
+
+class IMediaRecorder;
+class IMediaMetadataRetriever;
+
+#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 format, 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;
+
+        static bool             isOnEmulator();
+        static int              getMinBufferCount();
+    private:
+        static void             setMinBufferCount();
+
+        AudioTrack*             mTrack;
+        int                     mStreamType;
+        float                   mLeftVolume;
+        float                   mRightVolume;
+        float                   mMsecsPerFrame;
+        uint32_t                mLatency;
+
+        // TODO: Find real cause of Audio/Video delay in PV framework and remove this workaround
+        static const uint32_t   kAudioVideoDelayMs;
+        static bool             mIsOnEmulator;
+        static int              mMinBufferCount;  // 12 for emulator; otherwise 4
+
+    };
+
+    class AudioCache : public MediaPlayerBase::AudioSink
+    {
+    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 frameSize() * mFrameCount; }
+        virtual ssize_t         frameCount() const { return mFrameCount; }
+        virtual ssize_t         channelCount() const { return (ssize_t)mChannelCount; }
+        virtual ssize_t         frameSize() const { return ssize_t(mChannelCount * ((mFormat == AudioSystem::PCM_16_BIT)?sizeof(int16_t):sizeof(u_int8_t))); }
+        virtual uint32_t        latency() const;
+        virtual float           msecsPerFrame() const;
+        virtual status_t        open(uint32_t sampleRate, int channelCount, int format, 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; }
+                uint32_t        format() const { return (uint32_t)mFormat; }
+                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;
+        uint16_t            mChannelCount;
+        uint16_t			mFormat;
+        ssize_t             mFrameCount;
+        uint32_t            mSampleRate;
+        uint32_t            mSize;
+        int                 mError;
+        bool                mCommandComplete;
+    };
+
+public:
+    static  void                instantiate();
+
+    // IMediaPlayerService interface
+    virtual sp<IMediaRecorder>  createMediaRecorder(pid_t pid);
+    virtual sp<IMediaMetadataRetriever> createMetadataRetriever(pid_t pid);
+
+    // House keeping for media player clients
+    virtual sp<IMediaPlayer>    create(pid_t pid, const sp<IMediaPlayerClient>& client, const char* url);
+    virtual sp<IMediaPlayer>    create(pid_t pid, const sp<IMediaPlayerClient>& client, int fd, int64_t offset, int64_t length);
+    virtual sp<IMemory>         decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat);
+    virtual sp<IMemory>         decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat);
+
+    virtual status_t            dump(int fd, const Vector<String16>& args);
+
+            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        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/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
new file mode 100644
index 0000000..4b45acb
--- /dev/null
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -0,0 +1,273 @@
+/*
+ ** Copyright 2008, HTC Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ **     http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "MediaRecorderService"
+#include <utils/Log.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <string.h>
+#include <cutils/atomic.h>
+#include <android_runtime/ActivityManager.h>
+#include <utils/IPCThreadState.h>
+#include <utils/IServiceManager.h>
+#include <utils/MemoryHeapBase.h>
+#include <utils/MemoryBase.h>
+#include <media/PVMediaRecorder.h>
+
+#include "MediaRecorderClient.h"
+
+namespace android {
+
+status_t MediaRecorderClient::setCamera(const sp<ICamera>& camera)
+{
+    LOGV("setCamera");
+    Mutex::Autolock lock(mLock);
+    if (mRecorder == NULL) {
+        LOGE("recorder is not initialized");
+        return NO_INIT;
+    }
+    return mRecorder->setCamera(camera);
+}
+
+status_t MediaRecorderClient::setPreviewSurface(const sp<ISurface>& surface)
+{
+    LOGV("setPreviewSurface");
+    Mutex::Autolock lock(mLock);
+    if (mRecorder == NULL) {
+        LOGE("recorder is not initialized");
+        return NO_INIT;
+    }
+    return mRecorder->setPreviewSurface(surface);
+}
+
+status_t MediaRecorderClient::setVideoSource(int vs)
+{
+    LOGV("setVideoSource(%d)", vs);
+    Mutex::Autolock lock(mLock);
+    if (mRecorder == NULL)	{
+        LOGE("recorder is not initialized");
+    }
+    return mRecorder->setVideoSource((video_source)vs);
+}
+
+status_t MediaRecorderClient::setAudioSource(int as)
+{
+    LOGV("setAudioSource(%d)", as);
+    Mutex::Autolock lock(mLock);
+    if (mRecorder == NULL)  {
+        LOGE("recorder is not initialized");
+    }
+    return mRecorder->setAudioSource((audio_source)as);
+}
+
+status_t MediaRecorderClient::setOutputFormat(int of)
+{
+    LOGV("setOutputFormat(%d)", of);
+    Mutex::Autolock lock(mLock);
+    if (mRecorder == NULL) {
+        LOGE("recorder is not initialized");
+        return NO_INIT;
+    }
+    return mRecorder->setOutputFormat((output_format)of);
+}
+
+status_t MediaRecorderClient::setVideoEncoder(int ve)
+{
+    LOGV("setVideoEncoder(%d)", ve);
+    Mutex::Autolock lock(mLock);
+    if (mRecorder == NULL) {
+        LOGE("recorder is not initialized");
+        return NO_INIT;
+    }
+    return mRecorder->setVideoEncoder((video_encoder)ve);
+}
+
+status_t MediaRecorderClient::setAudioEncoder(int ae)
+{
+    LOGV("setAudioEncoder(%d)", ae);
+    Mutex::Autolock lock(mLock);
+    if (mRecorder == NULL) {
+        LOGE("recorder is not initialized");
+        return NO_INIT;
+    }
+    return mRecorder->setAudioEncoder((audio_encoder)ae);
+}
+
+status_t MediaRecorderClient::setOutputFile(const char* path)
+{
+    LOGV("setOutputFile(%s)", path);
+    Mutex::Autolock lock(mLock);
+    if (mRecorder == NULL) {
+        LOGE("recorder is not initialized");
+        return NO_INIT;
+    }
+    return mRecorder->setOutputFile(path);
+}
+
+status_t MediaRecorderClient::setOutputFile(int fd, int64_t offset, int64_t length)
+{
+    LOGV("setOutputFile(%d, %lld, %lld)", fd, offset, length);
+    Mutex::Autolock lock(mLock);
+    if (mRecorder == NULL) {
+        LOGE("recorder is not initialized");
+        return NO_INIT;
+    }
+    return mRecorder->setOutputFile(fd, offset, length);
+}
+
+status_t MediaRecorderClient::setVideoSize(int width, int height)
+{
+    LOGV("setVideoSize(%dx%d)", width, height);
+    Mutex::Autolock lock(mLock);
+    if (mRecorder == NULL) {
+        LOGE("recorder is not initialized");
+        return NO_INIT;
+    }
+    return mRecorder->setVideoSize(width, height);
+}
+
+status_t MediaRecorderClient::setVideoFrameRate(int frames_per_second)
+{
+    LOGV("setVideoFrameRate(%d)", frames_per_second);
+    Mutex::Autolock lock(mLock);
+    if (mRecorder == NULL) {
+        LOGE("recorder is not initialized");
+        return NO_INIT;
+    }
+    return mRecorder->setVideoFrameRate(frames_per_second);
+}
+
+status_t MediaRecorderClient::prepare()
+{
+    LOGV("prepare");
+    Mutex::Autolock lock(mLock);
+    if (mRecorder == NULL) {
+        LOGE("recorder is not initialized");
+        return NO_INIT;
+    }
+    return mRecorder->prepare();
+}
+
+
+status_t MediaRecorderClient::getMaxAmplitude(int* max)
+{
+    LOGV("getMaxAmplitude");
+    Mutex::Autolock lock(mLock);
+    if (mRecorder == NULL) {
+        LOGE("recorder is not initialized");
+        return NO_INIT;
+    }
+    return mRecorder->getMaxAmplitude(max);
+}
+
+status_t MediaRecorderClient::start()
+{
+    LOGV("start");
+    Mutex::Autolock lock(mLock);
+    if (mRecorder == NULL) {
+        LOGE("recorder is not initialized");
+        return NO_INIT;
+    }
+    return mRecorder->start();
+
+}
+
+status_t MediaRecorderClient::stop()
+{
+    LOGV("stop");
+    Mutex::Autolock lock(mLock);
+    if (mRecorder == NULL) {
+        LOGE("recorder is not initialized");
+        return NO_INIT;
+    }
+    return mRecorder->stop();
+}
+
+status_t MediaRecorderClient::init()
+{
+    LOGV("init");
+    Mutex::Autolock lock(mLock);
+    if (mRecorder == NULL) {
+        LOGE("recorder is not initialized");
+        return NO_INIT;
+    }
+    return mRecorder->init();
+}
+
+status_t MediaRecorderClient::close()
+{
+    LOGV("close");
+    Mutex::Autolock lock(mLock);
+    if (mRecorder == NULL) {
+        LOGE("recorder is not initialized");
+        return NO_INIT;
+    }
+    return mRecorder->close();
+}
+
+
+status_t MediaRecorderClient::reset()
+{
+    LOGV("reset");
+    Mutex::Autolock lock(mLock);
+    if (mRecorder == NULL) {
+        LOGE("recorder is not initialized");
+        return NO_INIT;
+    }
+    return mRecorder->reset();
+}
+
+status_t MediaRecorderClient::release()
+{
+    LOGV("release");
+    Mutex::Autolock lock(mLock);
+    if (mRecorder != NULL) {
+        delete mRecorder;
+        mRecorder = NULL;
+    }
+    return NO_ERROR;
+}
+
+MediaRecorderClient::MediaRecorderClient(pid_t pid)
+{
+    LOGV("Client constructor");
+    mPid = pid;
+    mRecorder = new PVMediaRecorder();
+}
+
+MediaRecorderClient::~MediaRecorderClient()
+{
+    LOGV("Client destructor");
+    release();
+}
+
+status_t MediaRecorderClient::setListener(const sp<IMediaPlayerClient>& listener)
+{
+    LOGV("setListener");
+    Mutex::Autolock lock(mLock);
+    if (mRecorder == NULL) {
+        LOGE("recorder is not initialized");
+        return NO_INIT;
+    }
+    return mRecorder->setListener(listener);
+}
+
+}; // namespace android
+
diff --git a/media/libmediaplayerservice/MediaRecorderClient.h b/media/libmediaplayerservice/MediaRecorderClient.h
new file mode 100644
index 0000000..93fd802
--- /dev/null
+++ b/media/libmediaplayerservice/MediaRecorderClient.h
@@ -0,0 +1,66 @@
+/*
+ **
+ ** Copyright 2008, HTC Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ **     http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+#ifndef ANDROID_MEDIARECORDERCLIENT_H
+#define ANDROID_MEDIARECORDERCLIENT_H
+
+#include <media/IMediaRecorder.h>
+
+namespace android {
+
+class PVMediaRecorder;
+class ISurface;
+
+class MediaRecorderClient : public BnMediaRecorder
+{
+public:
+    virtual	    status_t		setCamera(const sp<ICamera>& camera);
+    virtual     status_t        setPreviewSurface(const sp<ISurface>& surface);
+    virtual     status_t        setVideoSource(int vs);
+    virtual     status_t        setAudioSource(int as);
+    virtual     status_t        setOutputFormat(int of);
+    virtual     status_t        setVideoEncoder(int ve);
+    virtual     status_t        setAudioEncoder(int ae);
+    virtual     status_t        setOutputFile(const char* path);
+    virtual     status_t        setOutputFile(int fd, int64_t offset, int64_t length);
+    virtual     status_t        setVideoSize(int width, int height);
+    virtual     status_t        setVideoFrameRate(int frames_per_second);
+    virtual     status_t        setListener(const sp<IMediaPlayerClient>& listener);
+    virtual     status_t        prepare();
+    virtual     status_t        getMaxAmplitude(int* max);
+    virtual     status_t        start();
+    virtual     status_t        stop();
+    virtual	    status_t        reset();
+    virtual     status_t        init();
+    virtual     status_t        close();
+    virtual     status_t        release();
+
+private:
+    friend class                 MediaPlayerService;  // for accessing private constructor
+
+                                 MediaRecorderClient(pid_t pid);
+    virtual 		         ~MediaRecorderClient();
+
+    pid_t			 mPid;
+    Mutex			 mLock;
+    PVMediaRecorder              *mRecorder;
+};
+
+}; // namespace android
+
+#endif // ANDROID_MEDIARECORDERCLIENT_H
+
diff --git a/media/libmediaplayerservice/MetadataRetrieverClient.cpp b/media/libmediaplayerservice/MetadataRetrieverClient.cpp
new file mode 100644
index 0000000..a320bd5
--- /dev/null
+++ b/media/libmediaplayerservice/MetadataRetrieverClient.cpp
@@ -0,0 +1,250 @@
+/*
+**
+** Copyright (C) 2008 The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "MetadataRetrieverClient"
+#include <utils/Log.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <unistd.h>
+
+#include <string.h>
+#include <cutils/atomic.h>
+#include <utils/MemoryDealer.h>
+#include <android_runtime/ActivityManager.h>
+#include <utils/IPCThreadState.h>
+#include <utils/IServiceManager.h>
+#include <media/MediaMetadataRetrieverInterface.h>
+#include <media/MediaPlayerInterface.h>
+#include <media/PVMetadataRetriever.h>
+#include <private/media/VideoFrame.h>
+
+#include "MetadataRetrieverClient.h"
+
+
+namespace android {
+
+MetadataRetrieverClient::MetadataRetrieverClient(pid_t pid)
+{
+    LOGV("MetadataRetrieverClient constructor pid(%d)", pid);
+    mPid = pid;
+    mThumbnailDealer = NULL;
+    mAlbumArtDealer = NULL;
+    mThumbnail = NULL;
+    mAlbumArt = NULL;
+
+    mRetriever = new PVMetadataRetriever();
+    if (mRetriever == NULL) {
+        LOGE("failed to initialize the retriever");
+    }
+}
+
+MetadataRetrieverClient::~MetadataRetrieverClient()
+{
+    LOGV("MetadataRetrieverClient destructor");
+    disconnect();
+}
+
+status_t MetadataRetrieverClient::dump(int fd, const Vector<String16>& args) const
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+    result.append(" MetadataRetrieverClient\n");
+    snprintf(buffer, 255, "  pid(%d)\n", mPid);
+    result.append(buffer);
+    write(fd, result.string(), result.size());
+    write(fd, "\n", 1);
+    return NO_ERROR;
+}
+
+void MetadataRetrieverClient::disconnect()
+{
+    LOGV("disconnect from pid %d", mPid);
+    Mutex::Autolock lock(mLock);
+    mRetriever.clear();
+    mThumbnailDealer.clear();
+    mAlbumArtDealer.clear();
+    mThumbnail.clear();
+    mAlbumArt.clear();
+    IPCThreadState::self()->flushCommands();
+}
+
+status_t MetadataRetrieverClient::setDataSource(const char *url)
+{
+    LOGV("setDataSource(%s)", url);
+    Mutex::Autolock lock(mLock);
+    if (url == NULL) {
+        return UNKNOWN_ERROR;
+    }
+    if (mRetriever == NULL) {
+        LOGE("retriever is not initialized");
+        return NO_INIT;
+    }
+    return mRetriever->setDataSource(url);
+}
+
+status_t MetadataRetrieverClient::setDataSource(int fd, int64_t offset, int64_t length)
+{
+    LOGV("setDataSource fd=%d, offset=%lld, length=%lld", fd, offset, length);
+    Mutex::Autolock lock(mLock);
+    if (mRetriever == NULL) {
+        LOGE("retriever is not initialized");
+        ::close(fd);
+        return NO_INIT;
+    }
+
+    struct stat sb;
+    int ret = fstat(fd, &sb);
+    if (ret != 0) {
+        LOGE("fstat(%d) failed: %d, %s", fd, ret, strerror(errno));
+        return UNKNOWN_ERROR;
+    }
+    LOGV("st_dev  = %llu", sb.st_dev);
+    LOGV("st_mode = %u", sb.st_mode);
+    LOGV("st_uid  = %lu", sb.st_uid);
+    LOGV("st_gid  = %lu", sb.st_gid);
+    LOGV("st_size = %llu", sb.st_size);
+
+    if (offset >= sb.st_size) {
+        LOGE("offset (%lld) bigger than file size (%llu)", offset, sb.st_size);
+        ::close(fd);
+        return UNKNOWN_ERROR;
+    }
+    if (offset + length > sb.st_size) {
+        length = sb.st_size - offset;
+        LOGE("calculated length = %lld", length);
+    }
+    status_t status = mRetriever->setDataSource(fd, offset, length);
+    ::close(fd);
+    return status;
+}
+
+status_t MetadataRetrieverClient::setMode(int mode)
+{
+    LOGV("setMode");
+    Mutex::Autolock lock(mLock);
+    if (mRetriever == NULL) {
+        LOGE("retriever is not initialized");
+        return NO_INIT;
+    }
+    return mRetriever->setMode(mode);
+}
+
+status_t MetadataRetrieverClient::getMode(int* mode) const
+{
+    LOGV("getMode");
+    Mutex::Autolock lock(mLock);
+    if (mRetriever == NULL) {
+        LOGE("retriever is not initialized");
+        return NO_INIT;
+    }
+    return mRetriever->getMode(mode);
+}
+
+sp<IMemory> MetadataRetrieverClient::captureFrame()
+{
+    LOGV("captureFrame");
+    Mutex::Autolock lock(mLock);
+    mThumbnail.clear();
+    mThumbnailDealer.clear();
+    if (mRetriever == NULL) {
+        LOGE("retriever is not initialized");
+        return NULL;
+    }
+    VideoFrame *frame = mRetriever->captureFrame();
+    if (frame == NULL) {
+        LOGE("failed to capture a video frame");
+        return NULL;
+    }
+    size_t size = sizeof(VideoFrame) + frame->mSize;
+    mThumbnailDealer = new MemoryDealer(size);
+    if (mThumbnailDealer == NULL) {
+        LOGE("failed to create MemoryDealer");
+        delete frame;
+        return NULL;
+    }
+    mThumbnail = mThumbnailDealer->allocate(size);
+    if (mThumbnail == NULL) {
+        LOGE("not enough memory for VideoFrame size=%u", size);
+        mThumbnailDealer.clear();
+        delete frame;
+        return NULL;
+    }
+    VideoFrame *frameCopy = static_cast<VideoFrame *>(mThumbnail->pointer());
+    frameCopy->mWidth = frame->mWidth;
+    frameCopy->mHeight = frame->mHeight;
+    frameCopy->mDisplayWidth = frame->mDisplayWidth;
+    frameCopy->mDisplayHeight = frame->mDisplayHeight;
+    frameCopy->mSize = frame->mSize;
+    frameCopy->mData = (uint8_t *)frameCopy + sizeof(VideoFrame);
+    memcpy(frameCopy->mData, frame->mData, frame->mSize);
+    delete frame;  // Fix memory leakage
+    return mThumbnail;
+}
+
+sp<IMemory> MetadataRetrieverClient::extractAlbumArt()
+{
+    LOGV("extractAlbumArt");
+    Mutex::Autolock lock(mLock);
+    mAlbumArt.clear();
+    mAlbumArtDealer.clear();
+    if (mRetriever == NULL) {
+        LOGE("retriever is not initialized");
+        return NULL;
+    }
+    MediaAlbumArt *albumArt = mRetriever->extractAlbumArt();
+    if (albumArt == NULL) {
+        LOGE("failed to extract an album art");
+        return NULL;
+    }
+    size_t size = sizeof(MediaAlbumArt) + albumArt->mSize;
+    mAlbumArtDealer = new MemoryDealer(size);
+    if (mAlbumArtDealer == NULL) {
+        LOGE("failed to create MemoryDealer object");
+        delete albumArt;
+        return NULL;
+    }
+    mAlbumArt = mAlbumArtDealer->allocate(size);
+    if (mAlbumArt == NULL) {
+        LOGE("not enough memory for MediaAlbumArt size=%u", size);
+        mAlbumArtDealer.clear();
+        delete albumArt;
+        return NULL;
+    }
+    MediaAlbumArt *albumArtCopy = static_cast<MediaAlbumArt *>(mAlbumArt->pointer());
+    albumArtCopy->mSize = albumArt->mSize;
+    albumArtCopy->mData = (uint8_t *)albumArtCopy + sizeof(MediaAlbumArt);
+    memcpy(albumArtCopy->mData, albumArt->mData, albumArt->mSize);
+    delete albumArt;  // Fix memory leakage
+    return mAlbumArt;
+}
+
+const char* MetadataRetrieverClient::extractMetadata(int keyCode)
+{
+    LOGV("extractMetadata");
+    Mutex::Autolock lock(mLock);
+    if (mRetriever == NULL) {
+        LOGE("retriever is not initialized");
+        return NULL;
+    }
+    return mRetriever->extractMetadata(keyCode);
+}
+
+}; // namespace android
diff --git a/media/libmediaplayerservice/MetadataRetrieverClient.h b/media/libmediaplayerservice/MetadataRetrieverClient.h
new file mode 100644
index 0000000..ce29c98
--- /dev/null
+++ b/media/libmediaplayerservice/MetadataRetrieverClient.h
@@ -0,0 +1,71 @@
+/*
+**
+** Copyright (C) 2008 The Android Open Source Project 
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#ifndef ANDROID_MEDIAMETADATARETRIEVERSERVICE_H
+#define ANDROID_MEDIAMETADATARETRIEVERSERVICE_H
+
+#include <utils.h>
+#include <utils/KeyedVector.h>
+#include <utils/IMemory.h>
+
+#include <media/MediaMetadataRetrieverInterface.h>
+
+
+namespace android {
+
+class IMediaPlayerService;
+class MemoryDealer;
+
+class MetadataRetrieverClient : public BnMediaMetadataRetriever
+{
+public:
+    MetadataRetrieverClient(const sp<IMediaPlayerService>& service, pid_t pid, int32_t connId);
+
+    // Implements IMediaMetadataRetriever interface
+    // These methods are called in IMediaMetadataRetriever.cpp?
+    virtual void                    disconnect();
+    virtual status_t                setDataSource(const char *url);
+    virtual status_t                setDataSource(int fd, int64_t offset, int64_t length);
+    virtual status_t                setMode(int mode);
+    virtual status_t                getMode(int* mode) const;
+    virtual sp<IMemory>             captureFrame();
+    virtual sp<IMemory>             extractAlbumArt();
+    virtual const char*             extractMetadata(int keyCode);
+
+    virtual status_t                dump(int fd, const Vector<String16>& args) const;
+
+private:
+    friend class MediaPlayerService;
+
+    explicit MetadataRetrieverClient(pid_t pid);
+    virtual ~MetadataRetrieverClient();
+
+    mutable Mutex                          mLock;
+    sp<MediaMetadataRetrieverBase>         mRetriever;
+    pid_t                                  mPid;
+
+    // Keep the shared memory copy of album art and capture frame (for thumbnail)
+    sp<MemoryDealer>                       mAlbumArtDealer;
+    sp<MemoryDealer>                       mThumbnailDealer;
+    sp<IMemory>                            mAlbumArt;
+    sp<IMemory>                            mThumbnail;
+};
+
+}; // namespace android
+
+#endif // ANDROID_MEDIAMETADATARETRIEVERSERVICE_H
+
diff --git a/media/libmediaplayerservice/MidiFile.cpp b/media/libmediaplayerservice/MidiFile.cpp
new file mode 100644
index 0000000..d03caa5
--- /dev/null
+++ b/media/libmediaplayerservice/MidiFile.cpp
@@ -0,0 +1,558 @@
+/* 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
+
+// ----------------------------------------------------------------------------
+
+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(AudioSystem::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);
+    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::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);
+    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);
+        }
+        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, AudioSystem::PCM_16_BIT, 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");
+
+    // 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();
+    }
+
+    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..302f1cf
--- /dev/null
+++ b/media/libmediaplayerservice/MidiFile.h
@@ -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.
+*/
+
+#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    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;
+    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..0ad335f
--- /dev/null
+++ b/media/libmediaplayerservice/VorbisPlayer.cpp
@@ -0,0 +1,529 @@
+/*
+** 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(AudioSystem::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, AudioSystem::PCM_16_BIT, 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 {
+                    mAudioSink->stop();
+                    audioStarted = false;
+                    mRender = false;
+                    mPaused = true;
+                    int endpos = ov_time_tell(&mVorbisFile);
+
+                    LOGV("send MEDIA_PLAYBACK_COMPLETE");
+                    sendEvent(MEDIA_PLAYBACK_COMPLETE);
+
+                    // 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();
+}
diff --git a/media/sdutils/Android.mk b/media/sdutils/Android.mk
new file mode 100644
index 0000000..2009b3c
--- /dev/null
+++ b/media/sdutils/Android.mk
@@ -0,0 +1,15 @@
+ifeq ($(TARGET_ARCH),arm)
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+	sdutil.cpp \
+
+LOCAL_SHARED_LIBRARIES := libhardware_legacy libcutils libutils libc
+
+LOCAL_MODULE:= sdutil
+
+include $(BUILD_EXECUTABLE)
+
+endif
diff --git a/media/sdutils/sdutil.cpp b/media/sdutils/sdutil.cpp
new file mode 100644
index 0000000..a9aabf0
--- /dev/null
+++ b/media/sdutils/sdutil.cpp
@@ -0,0 +1,166 @@
+/*
+ * 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.
+ */
+
+#include <hardware_legacy/IMountService.h>
+#include <utils/BpBinder.h>
+#include <utils/IServiceManager.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+
+namespace android {
+
+static sp<IMountService> gMountService;
+
+static void init() {
+    sp<IServiceManager> sm = defaultServiceManager();
+    sp<IBinder> binder = sm->getService(String16("mount"));
+    gMountService = interface_cast<IMountService>(binder);
+    if (gMountService == 0) {
+        fprintf(stderr, "could not get MountService\n");
+        exit(1);
+    }
+}
+
+static bool isMounted(const char* mountPoint) {
+    char s[2000];
+    FILE *f = fopen("/proc/mounts", "r");
+    bool mounted = false;
+
+    while (fgets(s, sizeof(s), f))
+    {
+        char *c, *path = NULL;
+
+        for (c = s; *c; c++) 
+        {
+            if (*c == ' ') 
+            {
+                *c = 0;
+                path = c + 1;
+                break;
+            }
+        }
+
+        for (c = path; *c; c++) 
+        {
+            if (*c == ' ') 
+            {
+                *c = '\0';
+                break;
+            }
+        }
+
+        if (strcmp(mountPoint, path) == 0) {
+            mounted = true;
+            break;
+        }
+    }
+
+    fclose(f);
+    return mounted;
+}
+
+static void millisecondSleep(int milliseconds) {
+	struct timespec reqt, remt;	
+	reqt.tv_sec = milliseconds / 1000;
+	reqt.tv_nsec = 1000000 * (milliseconds % 1000);
+	nanosleep(&reqt, &remt) ;
+
+}
+
+static int mount(const char* path) {
+    String16 string(path);
+    gMountService->mountMedia(string);
+    
+    for (int i = 0; i < 10; i++) {
+        if (isMounted(path)) {
+            return 0;
+        }
+        millisecondSleep(500);
+    }
+        
+    fprintf(stderr, "failed to mount %s\n", path);   
+    return -1;
+}
+
+static int unmount(const char* path) {
+    String16 string(path);
+    gMountService->unmountMedia(string);
+
+    for (int i = 0; i < 10; i++) {
+        if (!isMounted(path)) {
+            return 0;
+        }
+        millisecondSleep(500);
+    }
+        
+    fprintf(stderr, "failed to unmount %s\n", path);   
+    return -1;
+}
+
+static int format(const char* path) {
+    String16 string(path);
+
+    if (isMounted(path))
+        return -EBUSY;
+    gMountService->formatMedia(string);
+
+    return 0;
+}
+
+static int umsEnable(bool enable) {
+    gMountService->setMassStorageEnabled(enable);
+    return 0;
+}
+
+};
+
+int main(int argc, char **argv)
+{
+    const char* command = (argc > 1 ? argv[1] : "");
+    const char* argument = (argc > 2 ? argv[2] : "");
+    
+    if (strcmp(command, "mount") == 0) {
+        android::init();
+        return android::mount(argument);
+    } else if (strcmp(command, "format") == 0) {
+        android::init();
+        return android::format(argument);
+    } else if (strcmp(command, "unmount") == 0) {
+        android::init();
+        return android::unmount(argument);
+    } else if (strcmp(command, "ums") == 0) {
+        if (strcmp(argument, "enable") == 0) {
+            android::init();
+            return android::umsEnable(true);
+        } else if (strcmp(argument, "disable") == 0) {
+            android::init();
+            return android::umsEnable(false);
+        }
+    }
+    
+    fprintf(stderr, "usage:\n"
+                    "    sdutil mount <mount path>          - mounts the SD card at the given mount point\n"
+                    "    sdutil unmount <mount path>        - unmounts the SD card at the given mount point\n"
+                    "    sdutil format <mount path>         - formats the SD card at the given mount point\n"
+                    "    sdutil ums enable                  - enables USB mass storage\n"
+                    "    sdutil ums disable                 - disnables USB mass storage\n"
+                    );
+    return -1;
+}
diff --git a/media/tests/MediaFrameworkTest/Android.mk b/media/tests/MediaFrameworkTest/Android.mk
new file mode 100644
index 0000000..9c45e6e
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/Android.mk
@@ -0,0 +1,12 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
+
+LOCAL_PACKAGE_NAME := mediaframeworktest
+
+include $(BUILD_PACKAGE)
diff --git a/media/tests/MediaFrameworkTest/AndroidManifest.xml b/media/tests/MediaFrameworkTest/AndroidManifest.xml
new file mode 100644
index 0000000..a32f590
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/AndroidManifest.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.mediaframeworktest">
+    
+    <uses-permission android:name="android.permission.RECORD_AUDIO" />
+    <application>    
+        <uses-library android:name="android.test.runner" />
+        <activity android:label="@string/app_name"
+                android:name="MediaFrameworkTest">         
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER"/>
+            </intent-filter>
+        </activity>
+    </application>   
+    <instrumentation android:name=".MediaFrameworkTestRunner"
+         android:targetPackage="com.android.mediaframeworktest"
+         android:label="MediaFramework tests InstrumentationRunner">
+     </instrumentation>
+     
+      <instrumentation android:name=".MediaFrameworkPerfTestRunner"
+         android:targetPackage="com.android.mediaframeworktest"
+         android:label="MediaFramework Performance tests InstrumentationRunner">
+     </instrumentation>
+
+     <instrumentation android:name=".MediaFrameworkUnitTestRunner"
+         android:targetPackage="com.android.mediaframeworktest"
+         android:label="MediaFramework unit tests InstrumentationRunner">
+     </instrumentation>
+     
+     <instrumentation android:name=".MediaRecorderStressTestRunner"
+         android:targetPackage="com.android.mediaframeworktest"
+         android:label="MediaRecorder stress tests InstrumentationRunner">
+     </instrumentation>
+
+</manifest>
diff --git a/media/tests/MediaFrameworkTest/res/drawable/icon.png b/media/tests/MediaFrameworkTest/res/drawable/icon.png
new file mode 100644
index 0000000..64e3601
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/res/drawable/icon.png
Binary files differ
diff --git a/media/tests/MediaFrameworkTest/res/layout/movie_view.xml b/media/tests/MediaFrameworkTest/res/layout/movie_view.xml
new file mode 100644
index 0000000..35fedfa
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/res/layout/movie_view.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 	 	
+	android:layout_width="fill_parent" 
+	android:layout_height="fill_parent"
+	android:orientation="vertical">
+
+	<FrameLayout
+		android:layout_width="fill_parent"
+		android:layout_height="0px"
+		android:layout_weight="1">
+		
+	<VideoView 
+	 android:id="@+id/surface_view" 
+        android:layout_width="320px"
+        android:layout_height="240px"
+	/>
+	</FrameLayout>
+	
+	<LinearLayout 	
+	android:layout_width="fill_parent" 
+	android:layout_height="wrap_content"
+	android:orientation="vertical">
+	
+	 <EditText android:id="@+id/url"
+        android:layout_width="fill_parent" 
+        android:layout_height="wrap_content"
+        android:layout_weight="0"
+        android:singleLine="true"
+        android:paddingBottom="8dip">
+        <requestFocus />
+    </EditText>
+
+    <Button android:id="@+id/open"
+        android:layout_width="wrap_content" 
+        android:layout_height="wrap_content" 
+        android:layout_weight="0"
+        android:text="@string/open_url">
+    </Button>
+    
+    </LinearLayout>
+    
+</LinearLayout>
diff --git a/media/tests/MediaFrameworkTest/res/layout/surface_view.xml b/media/tests/MediaFrameworkTest/res/layout/surface_view.xml
new file mode 100644
index 0000000..c25e476
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/res/layout/surface_view.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    
+  android:layout_width="fill_parent" 
+  android:layout_height="fill_parent"
+  android:orientation="vertical">
+
+  <FrameLayout
+    android:layout_width="fill_parent"
+    android:layout_height="0px"
+    android:layout_weight="1">
+    
+  <SurfaceView
+     android:id="@+id/surface_view"
+     android:layout_width="320dip"
+     android:layout_height="240dip"
+     android:layout_centerInParent="true"
+     />
+     
+  <VideoView 
+   android:id="@+id/video_view" 
+        android:layout_width="320px"
+        android:layout_height="240px"
+  />
+  
+  </FrameLayout>
+    
+</LinearLayout>
+
diff --git a/media/tests/MediaFrameworkTest/res/raw/shortmp3.mp3 b/media/tests/MediaFrameworkTest/res/raw/shortmp3.mp3
new file mode 100644
index 0000000..3af32a15
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/res/raw/shortmp3.mp3
Binary files differ
diff --git a/media/tests/MediaFrameworkTest/res/raw/testmidi.mid b/media/tests/MediaFrameworkTest/res/raw/testmidi.mid
new file mode 100644
index 0000000..df84e20
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/res/raw/testmidi.mid
Binary files differ
diff --git a/media/tests/MediaFrameworkTest/res/raw/testmp3.mp3 b/media/tests/MediaFrameworkTest/res/raw/testmp3.mp3
new file mode 100644
index 0000000..89c44b0
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/res/raw/testmp3.mp3
Binary files differ
diff --git a/media/tests/MediaFrameworkTest/res/values/strings.xml b/media/tests/MediaFrameworkTest/res/values/strings.xml
new file mode 100644
index 0000000..a24309f
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/res/values/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="app_name">mediaPlayerApiTest</string>
+    <string name="open_url">Open</string>
+</resources>
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkPerfTestRunner.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkPerfTestRunner.java
new file mode 100755
index 0000000..eaaa798
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkPerfTestRunner.java
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+
+package com.android.mediaframeworktest;
+
+import com.android.mediaframeworktest.performance.MediaPlayerPerformance;
+
+import junit.framework.TestSuite;
+
+import android.test.InstrumentationTestRunner;
+import android.test.InstrumentationTestSuite;
+
+
+/**
+ * Instrumentation Test Runner for all MediaPlayer tests.
+ * 
+ * Running all tests:
+ *
+ * adb shell am instrument \
+ *   -w com.android.smstests.MediaPlayerInstrumentationTestRunner
+ */
+
+public class MediaFrameworkPerfTestRunner extends InstrumentationTestRunner {
+
+
+  @Override
+  public TestSuite getAllTests() {
+      TestSuite suite = new InstrumentationTestSuite(this);
+      suite.addTestSuite(MediaPlayerPerformance.class);
+      return suite;
+  }
+
+  @Override
+  public ClassLoader getLoader() {
+      return MediaFrameworkTestRunner.class.getClassLoader();
+  }
+}
+
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTest.java
new file mode 100644
index 0000000..e65cf41
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTest.java
@@ -0,0 +1,149 @@
+/*
+ * 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.
+ */
+
+package com.android.mediaframeworktest;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.AssetFileDescriptor;
+import android.graphics.Color;
+import android.media.MediaPlayer;
+import android.net.Uri;
+import android.os.Bundle;
+import android.provider.Downloads;
+import android.util.Log;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.Menu;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.view.View.OnClickListener;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.MediaController;
+import android.widget.VideoView;
+import com.android.mediaframeworktest.MediaNames;
+
+import java.io.File;
+import java.io.FileDescriptor;
+
+ 
+public class MediaFrameworkTest extends Activity {
+    
+    //public static Surface video_sf;
+    public static SurfaceView mSurfaceView;
+    private MediaController mMediaController;
+    private String urlpath;
+    private MediaPlayer mpmidi;
+    private MediaPlayer mpmp3;
+    private String testfilepath = "/sdcard/awb.awb";
+    
+    public static AssetFileDescriptor midiafd;
+    public static AssetFileDescriptor mp3afd;
+    
+    
+    public MediaFrameworkTest() {
+    }
+
+    
+    /** Called when the activity is first created. */
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        setContentView(R.layout.surface_view);
+        mSurfaceView = (SurfaceView)findViewById(R.id.surface_view);
+        ViewGroup.LayoutParams lp = mSurfaceView.getLayoutParams();
+        lp.width = 320;
+        lp.height = 240;
+        mSurfaceView.setLayoutParams(lp);
+        mSurfaceView.getHolder().setFixedSize(320, 240);  
+        mSurfaceView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
+        
+        //Get the midi fd
+        midiafd = this.getResources().openRawResourceFd(R.raw.testmidi);
+        
+        //Get the mp3 fd
+        mp3afd = this.getResources().openRawResourceFd(R.raw.testmp3);
+    }
+    
+    public void startPlayback(String filename){
+      String mimetype = "audio/mpeg";
+      Uri path = Uri.parse(filename);
+      Intent intent = new Intent(Intent.ACTION_VIEW);
+      intent.setDataAndType(path, mimetype);
+      startActivity(intent);
+    }
+    
+    @Override public boolean onKeyDown(int keyCode, KeyEvent event) {
+      switch (keyCode) {
+          case KeyEvent.KEYCODE_0:
+            MediaPlayer mp = new MediaPlayer();
+            try{
+              mp.setDataSource(MediaNames.VIDEO_RTSP3GP);
+              Log.v("emily","awb  " + testfilepath);
+              mp.setDisplay(mSurfaceView.getHolder());
+              mp.prepare();
+              mp.start();
+            }catch (Exception e){}
+              break;
+          
+          //start the music player intent with the test URL from PV    
+          case KeyEvent.KEYCODE_1:
+            startPlayback(MediaNames.STREAM_MP3_1);
+            break;
+          
+          case KeyEvent.KEYCODE_2:
+            startPlayback(MediaNames.STREAM_MP3_2);
+            break;
+          
+          case KeyEvent.KEYCODE_3:
+            startPlayback(MediaNames.STREAM_MP3_3);
+            break;
+          
+          case KeyEvent.KEYCODE_4:
+            startPlayback(MediaNames.STREAM_MP3_4);
+            break;
+          
+          case KeyEvent.KEYCODE_5:
+            startPlayback(MediaNames.STREAM_MP3_5);
+            break;
+          
+          case KeyEvent.KEYCODE_6:
+            startPlayback(MediaNames.STREAM_MP3_6);
+            break;
+          
+          case KeyEvent.KEYCODE_7:
+            startPlayback(MediaNames.STREAM_MP3_7);
+            break;
+          
+          case KeyEvent.KEYCODE_8:
+            startPlayback(MediaNames.STREAM_MP3_8);
+            break;
+          
+          case KeyEvent.KEYCODE_9:
+            startPlayback(MediaNames.STREAM_MP3_9);
+            break;
+          
+              
+              
+      }
+      return super.onKeyDown(keyCode, event);
+     
+  }  
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTestRunner.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTestRunner.java
new file mode 100755
index 0000000..73688cc
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTestRunner.java
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+
+package com.android.mediaframeworktest;
+
+import com.android.mediaframeworktest.functional.MediaPlayerApiTest;
+import com.android.mediaframeworktest.functional.SimTonesTest;
+import com.android.mediaframeworktest.functional.MediaMetadataTest;
+import com.android.mediaframeworktest.functional.CameraTest;
+import com.android.mediaframeworktest.functional.MediaRecorderTest;
+import com.android.mediaframeworktest.functional.MediaAudioTrackTest;
+
+import junit.framework.TestSuite;
+
+import android.test.InstrumentationTestRunner;
+import android.test.InstrumentationTestSuite;
+
+
+/**
+ * Instrumentation Test Runner for all MediaPlayer tests.
+ * 
+ * Running all tests:
+ *
+ * adb shell am instrument \
+ *   -w com.android.smstests.MediaPlayerInstrumentationTestRunner
+ */
+
+public class MediaFrameworkTestRunner extends InstrumentationTestRunner {
+
+
+    @Override
+    public TestSuite getAllTests() {
+        TestSuite suite = new InstrumentationTestSuite(this);
+        suite.addTestSuite(MediaPlayerApiTest.class);
+        suite.addTestSuite(SimTonesTest.class);
+        suite.addTestSuite(MediaMetadataTest.class);
+        suite.addTestSuite(CameraTest.class);
+        suite.addTestSuite(MediaRecorderTest.class);
+        //suite.addTestSuite(MediaAudioTrackTest.class);
+        return suite;
+    }
+
+    @Override
+    public ClassLoader getLoader() {
+        return MediaFrameworkTestRunner.class.getClassLoader();
+    }
+}
+
+
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkUnitTestRunner.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkUnitTestRunner.java
new file mode 100755
index 0000000..81d59da
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkUnitTestRunner.java
@@ -0,0 +1,91 @@
+/*
+ * 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.
+ */
+
+package com.android.mediaframeworktest;
+
+import android.test.InstrumentationTestRunner;
+import android.test.InstrumentationTestSuite;
+import com.android.mediaframeworktest.unit.*;
+
+import junit.framework.TestSuite;
+
+/**
+ * Instrumentation Test Runner for all media framework unit tests.
+ * 
+ * Make sure that MediaFrameworkUnitTestRunner has been added to
+ * AndroidManifest.xml file, and then "make -j4 mediaframeworktest; adb sync"
+ * to build and upload mediaframeworktest to the phone or emulator.
+ * 
+ * Example on running all unit tests for a single class:
+ * adb shell am instrument -e class \
+ * com.android.mediaframeworktest.unit.MediaMetadataRetrieverUnitTest \ 
+ * -w com.android.mediaframeworktest/.MediaFrameworkUnitTestRunner
+ * 
+ * Example on running all unit tests for the media framework:
+ * adb shell am instrument \
+ * -w com.android.mediaframeworktest/.MediaFrameworkUnitTestRunner
+ */
+
+public class MediaFrameworkUnitTestRunner extends InstrumentationTestRunner {
+
+    @Override
+    public TestSuite getAllTests() {
+        TestSuite suite = new InstrumentationTestSuite(this);
+        addMediaMetadataRetrieverStateUnitTests(suite);
+        addMediaRecorderStateUnitTests(suite);
+        addMediaPlayerStateUnitTests(suite);
+        return suite;
+    }
+
+    @Override
+    public ClassLoader getLoader() {
+        return MediaFrameworkUnitTestRunner.class.getClassLoader();
+    }
+    
+    // Running all unit tests checking the state machine may be time-consuming.
+    private void addMediaMetadataRetrieverStateUnitTests(TestSuite suite) {
+        suite.addTestSuite(MediaMetadataRetrieverTest.class);
+    }
+    
+    // Running all unit tests checking the state machine may be time-consuming.
+    private void addMediaRecorderStateUnitTests(TestSuite suite) {
+        suite.addTestSuite(MediaRecorderPrepareStateUnitTest.class);
+        suite.addTestSuite(MediaRecorderResetStateUnitTest.class);
+        suite.addTestSuite(MediaRecorderSetAudioEncoderStateUnitTest.class);
+        suite.addTestSuite(MediaRecorderSetAudioSourceStateUnitTest.class);
+        suite.addTestSuite(MediaRecorderSetOutputFileStateUnitTest.class);
+        suite.addTestSuite(MediaRecorderSetOutputFormatStateUnitTest.class);
+        suite.addTestSuite(MediaRecorderStartStateUnitTest.class);
+        suite.addTestSuite(MediaRecorderStopStateUnitTest.class);
+    }
+
+    // Running all unit tests checking the state machine may be time-consuming.
+    private void addMediaPlayerStateUnitTests(TestSuite suite) {
+        suite.addTestSuite(MediaPlayerGetDurationStateUnitTest.class);
+        suite.addTestSuite(MediaPlayerSeekToStateUnitTest.class);
+        suite.addTestSuite(MediaPlayerGetCurrentPositionStateUnitTest.class);
+        suite.addTestSuite(MediaPlayerGetVideoWidthStateUnitTest.class);
+        suite.addTestSuite(MediaPlayerGetVideoHeightStateUnitTest.class);
+        suite.addTestSuite(MediaPlayerIsPlayingStateUnitTest.class);
+        suite.addTestSuite(MediaPlayerResetStateUnitTest.class);
+        suite.addTestSuite(MediaPlayerPauseStateUnitTest.class);
+        suite.addTestSuite(MediaPlayerStartStateUnitTest.class);
+        suite.addTestSuite(MediaPlayerStopStateUnitTest.class);
+        suite.addTestSuite(MediaPlayerSetLoopingStateUnitTest.class);
+        suite.addTestSuite(MediaPlayerSetAudioStreamTypeStateUnitTest.class);
+        suite.addTestSuite(MediaPlayerSetVolumeStateUnitTest.class);
+    }
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaNames.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaNames.java
new file mode 100755
index 0000000..5e9c488
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaNames.java
@@ -0,0 +1,497 @@
+/*
+ * 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.
+ */
+
+package com.android.mediaframeworktest;
+
+/**
+ * 
+ * This class has the names of the all the activity name and variables 
+ * in the instrumentation test.
+ *
+ */
+public class MediaNames {
+  
+    //Audio files
+    public static final String MP3CBR = "/sdcard/media_api/music/MP3CBR.mp3";  
+    public static final String MP3VBR = "/sdcard/media_api/music/MP3VBR.mp3";
+    public static final String SHORTMP3 = "/sdcard/media_api/music/SHORTMP3.mp3";
+    public static final String MIDI = "/sdcard/media_api/music/MIDI.mid";
+    public static final String WMA9 = "/sdcard/media_api/music/WMA9.wma";
+    public static final String WMA10 = "/sdcard/media_api/music/WMA10.wma";
+    public static final String WAV = "/sdcard/media_api/music/complicated_wav.wav";
+    public static final String AMR = "/sdcard/media_api/music/AMRNB.amr";
+    public static final String OGG = "/sdcard/media_api/music/Mists_of_Time-4T.ogg";
+    public static final String OGGSHORT = "/sdcard/media_api/music/Skippy.ogg";
+  
+    public static final int MP3CBR_LENGTH = 231116;  
+    public static final int MP3VBR_LENGTH = 126407;
+    public static final int SHORTMP3_LENGTH = 286;
+    public static final int MIDI_LENGTH = 210528;
+    public static final int WMA9_LENGTH = 126559;
+    public static final int WMA10_LENGTH = 126559;
+    public static final int AMR_LENGTH = 126540;
+    public static final int OGG_LENGTH = 40000;
+    public static final int SEEK_TIME = 10000;
+  
+    public static final long PAUSE_WAIT_TIME = 3000;
+    public static final long WAIT_TIME = 2000;
+    public static final long WAIT_LONG = 4000;
+  
+    //Streaming Video
+    public static final String VIDEO_HTTP3GP = "http://pvs.pv.com/jj/lipsync0.3gp";  
+    public static final String VIDEO_RTSP3GP = "rtsp://63.241.31.203/public/jj/md.3gp";
+    public static final String VIDEO_RTSP3GP2 = "rtsp://pvs.pv.com/public/live_dvd1.3gp";
+    public static final String VIDEO_RTSP3GP3 = 
+      "rtsp://ehug.rtsp-youtube.l.google.com/" +
+      "Ci4LENy73wIaJQmeRVCJq4HuQBMYDSANFEIJbXYtZ29vZ2xlSARSB2RldGFpbHMM/0/0/0/video.3gp";
+    //public static final String VIDEO_RTSP3GP = "rtsp://193.159.241.21/sp/alizee05.3gp";
+  
+    //local video
+    public static final String VIDEO_MP4 = "/sdcard/media_api/video/gingerkids.MP4";
+    public static final String VIDEO_LONG_3GP = "/sdcard/media_api/video/radiohead.3gp";
+    public static final String VIDEO_SHORT_3GP = "/sdcard/media_api/video/short.3gp";
+    public static final String VIDEO_LARGE_SIZE_3GP = "/sdcard/media_api/video/border_large.3gp";
+    public static final String VIDEO_H263_AAC = "/sdcard/media_api/video/H263_AAC.3gp";
+    public static final String VIDEO_H263_AMR = "/sdcard/media_api/video/H263_AMR.3gp";
+    public static final String VIDEO_H264_AAC = "/sdcard/media_api/video/H264_AAC.3gp";
+    public static final String VIDEO_H264_AMR = "/sdcard/media_api/video/H264_AMR.3gp";   
+    public static final String VIDEO_WMV = "/sdcard/media_api/video/bugs.wmv";
+    public static final String VIDEO_HIGHRES_H263 = "/sdcard/media_api/video/h263_qcif_30fps.3gp";
+    public static final String VIDEO_HIGHRES_MP4 = "/sdcard/media_api/video/mpeg4_qvga_24fps.3gp";
+    
+    //ringtone
+    public static final String ringtone = "/sdcard/media_api/ringtones/F1_NewVoicemail.mp3";
+  
+    //streaming mp3
+    public static final String STREAM_LARGE_MP3 = 
+      "http://wms.pv.com:7070/MediaDownloadContent/mp3/BuenaVista_04_Pueblo_Nuevo.mp3";
+    public static final String STREAM_SMALL_MP3 = 
+      "http://wms.pv.com:7070/MediaDownloadContent/mp3/ID3V2_TestFile.mp3"; 
+    public static final String STREAM_REGULAR_MP3 = 
+      "http://wms.pv.com:7070/MediaDownloadContent/mp3/ElectricCosmo.mp3";
+  
+    //streaming mp3
+    public static final String STREAM_MP3_1 = 
+      "http://wms.pv.com:7070/MediaDownloadContent/mp3/chadthi_jawani_128kbps.mp3";
+    public static final String STREAM_MP3_2 = 
+      "http://wms.pv.com:7070/MediaDownloadContent/mp3/dualStereo.mp3";
+    public static final String STREAM_MP3_3 = 
+      "http://wms.pv.com:7070/mediadownloadcontent/UserUploads/15%20Keep%20Holding%20On.mp3";
+    public static final String STREAM_MP3_4 = 
+      "http://wms.pv.com:7070/mediadownloadcontent/UserUploads/1%20-%20Apologize.mp3";
+    public static final String STREAM_MP3_5 = 
+      "http://wms.pv.com:7070/mediadownloadcontent/UserUploads/" +
+      "03%20You're%20Gonna%20Miss%20This.mp3";
+    public static final String STREAM_MP3_6 = 
+      "http://wms.pv.com:7070/mediadownloadcontent/UserUploads" +
+      "/02%20Looney%20Tunes%20%C3%82%C2%B7%20Light%20Cavalry%20Overture%20(LP%20Version).mp3";
+    public static final String STREAM_MP3_7 = 
+      "http://wms.pv.com:7070/mediadownloadcontent/UserUploads" +
+      "/01%20Love%20Song%20(Album%20Version).mp3";
+    public static final String STREAM_MP3_8 = 
+      "http://wms.pv.com:7070/MediaDownloadContent/UserUploads/1%20-%20Apologize.mp3";
+    public static final String STREAM_MP3_9 = 
+      "http://wms.pv.com:7070/MediaDownloadContent/UserUploads" +
+      "/1%20-%20Smile%20(Explicit%20Version).mp3";
+    public static final String STREAM_MP3_10 = 
+      "http://wms.pv.com:7070/MediaDownloadContent/UserUploads/beefcake.mp3";
+
+    //Sonivox
+    public static String MIDIFILES[] = { 
+        "/sdcard/media_api/music/Leadsol.mxmf",
+        "/sdcard/media_api/music/abba.imy", "/sdcard/media_api/music/ants.mid",
+        "/sdcard/media_api/music/greensleeves.rtttl", "/sdcard/media_api/music/test.ota"};
+  
+    //Performance measurement
+    public static String[] WAVFILES = { 
+        "/sdcard/media_api/music_perf/WAV/M1F1-AlawWE-AFsp.wav",
+        "/sdcard/media_api/music_perf/WAV/M1F1-float64-AFsp.wav",
+        "/sdcard/media_api/music_perf/WAV/song.wav",
+        "/sdcard/media_api/music_perf/WAV/WAVEtest.wav",
+        "/sdcard/media_api/music_perf/WAV/WAVEtest_out.wav",
+        "/sdcard/media_api/music_perf/WAV/test_out.wav"};
+        
+    public static String[] AMRNBFILES = { 
+        "/sdcard/media_api/music_perf/AMR/AI_AMR-NB_5.9kbps_6.24kbps_8khz_mono_NMC.amr",
+        "/sdcard/media_api/music_perf/AMR/AI_AMR-NB_5.15kbps_5.46kbps_8khz_mono_NMC.amr",
+        "/sdcard/media_api/music_perf/AMR/AI_AMR-NB_7.4kbps_7.80kbps_8khz_mono_NMC.amr",
+        "/sdcard/media_api/music_perf/AMR/AI_AMR-NB_7.95kbps_9.6kbps_8khz_mono_NMC.amr",
+        "/sdcard/media_api/music_perf/AMR/AI_AMR-NB_10.2kbps_10.48kbps_8khz_mono_NMC.amr"};
+  
+    public static String[] AMRWBFILES = { 
+        "/sdcard/media_api/music_perf/AMRWB/NIN_AMR-WB_15.85kbps_16kbps.amr",
+        "/sdcard/media_api/music_perf/AMRWB/NIN_AMR-WB_18.25kbps_18kbps.amr",
+        "/sdcard/media_api/music_perf/AMRWB/NIN_AMR-WB_19.85kbps_20kbps.amr",
+        "/sdcard/media_api/music_perf/AMRWB/NIN_AMR-WB_23.05kbps_23kbps.amr",
+        "/sdcard/media_api/music_perf/AMRWB/NIN_AMR-WB_23.85kbps_24kbps.amr",
+        "/sdcard/media_api/music_perf/AMRWB/PD_AMR-WB_19.85kbps_20kbps.amr",
+        "/sdcard/media_api/music_perf/AMRWB/PD_AMR-WB_23.05kbps_23kbps.amr",
+        "/sdcard/media_api/music_perf/AMRWB/PD_AMR-WB_23.85kbps_24kbps.amr",
+        "/sdcard/media_api/music_perf/AMRWB/WC_AMR-WB_23.05kbps_23kbps.amr",
+        "/sdcard/media_api/music_perf/AMRWB/WC_AMR-WB_23.85kbps_24kbps.amr", };
+ 
+    public static String[] MP3FILES = { 
+        "/sdcard/media_api/music_perf/MP3/NIN_56kbps_32khz_stereo_VBR_MCA.MP3",
+        "/sdcard/media_api/music_perf/MP3/NIN_80kbps_32khz_stereo_VBR_MCA.mp3",
+        "/sdcard/media_api/music_perf/MP3/NIN_80kbps_44.1khz_stereo_VBR_MCA.mp3", 
+        "/sdcard/media_api/music_perf/MP3/NIN_80kbps_48khz_stereo_VBR_MCA.mp3",
+        "/sdcard/media_api/music_perf/MP3/NIN_112kbps_32khz_stereo_VBR_MCA.mp3",
+        "/sdcard/media_api/music_perf/MP3/NIN_112kbps_44.1khz_stereo_VBR_MCA.mp3",
+        "/sdcard/media_api/music_perf/MP3/NIN_112kbps_48khz_stereo_VBR_MCA.mp3",
+        "/sdcard/media_api/music_perf/MP3/NIN_192kbps_32khz_mono_CBR_MCA.mp3",
+        "/sdcard/media_api/music_perf/MP3/NIN_192kbps_44.1khz_mono_CBR_MCA.mp3",
+        "/sdcard/media_api/music_perf/MP3/NIN_192kbps_48khz_mono_CBR_MCA.mp3",
+        "/sdcard/media_api/music_perf/MP3/NIN_256kbps_44.1khz_mono_CBR_MCA.mp3",
+        "/sdcard/media_api/music_perf/MP3/NIN_256kbps_48khz_mono_CBR_MCA.mp3",
+        "/sdcard/media_api/music_perf/MP3/PD_112kbps_32khz_stereo_VBR_MCA.mp3",
+        "/sdcard/media_api/music_perf/MP3/PD_112kbps_44.1khz_stereo_VBR_MCA.mp3",
+        "/sdcard/media_api/music_perf/MP3/PD_112kbps_48khz_stereo_VBR_MCA.mp3",
+        "/sdcard/media_api/music_perf/MP3/PD_192kbps_32khz_mono_CBR_DPA.mp3",
+        "/sdcard/media_api/music_perf/MP3/PD_256kbps_44.1khz_mono_CBR_DPA.mp3",
+        "/sdcard/media_api/music_perf/MP3/PD_256kbps_48khz_mono_CBR_MCA.mp3",
+        "/sdcard/media_api/music_perf/MP3/WC_256kbps_44.1khz_mono_CBR_DPA.mp3",
+        "/sdcard/media_api/music_perf/MP3/WC_256kbps_48khz_mono_CBR_DPA.mp3",
+        "/sdcard/media_api/music_perf/regular_album_photo/Apologize.mp3",
+        "/sdcard/media_api/music_perf/regular_album_photo/Because_Of_You.mp3",
+        "/sdcard/media_api/music_perf/regular_album_photo/Complicated.mp3",
+        "/sdcard/media_api/music_perf/regular_album_photo/Glamorous.mp3",
+        "/sdcard/media_api/music_perf/regular_album_photo/Im_With_You.mp3",
+        "/sdcard/media_api/music_perf/regular_album_photo/Smile.mp3",
+        "/sdcard/media_api/music_perf/regular_album_photo/Suddenly_I_See.mp3",
+        "/sdcard/media_api/music_perf/regular_album_photo/When You Say Nothing At All.mp3",
+        "/sdcard/media_api/music_perf/regular_album_photo/my_happy_ending.mp3"};
+  
+    public static String[] AACFILES = { 
+        "/sdcard/media_api/music_perf/AAC/AI_AAC_24kbps_12khz_Mono_1pCBR_SSE.mp4",
+        "/sdcard/media_api/music_perf/AAC/AI_AAC_56kbps_22.05khz_Stereo_1pCBR_SSE.mp4",
+        "/sdcard/media_api/music_perf/AAC/AI_AAC_56kbps_32khz_Stereo_CBR_SSE.mp4",
+        "/sdcard/media_api/music_perf/AAC/AI_AAC_56kbps_44.1khz_Stereo_1pCBR_SSE.mp4",
+        "/sdcard/media_api/music_perf/AAC/AI_AAC_80kbps_32khz_Stereo_1pCBR_SSE.mp4",
+        "/sdcard/media_api/music_perf/AAC/AI_AAC_80kbps_32khz_Stereo_CBR_SSE.mp4",
+        "/sdcard/media_api/music_perf/AAC/NIN_AAC_56kbps_22.05khz_Stereo_1pCBR_SSE.mp4",
+        "/sdcard/media_api/music_perf/AAC/NIN_AAC_56kbps_32khz_Stereo_CBR_SSE.mp4",
+        "/sdcard/media_api/music_perf/AAC/NIN_AAC_56kbps_44.1khz_Stereo_1pCBR_SSE.mp4",
+        "/sdcard/media_api/music_perf/AAC/NIN_AAC_80kbps_32khz_Stereo_1pCBR_SSE.mp4",
+        "/sdcard/media_api/music_perf/AAC/NIN_AAC_80kbps_32khz_Stereo_CBR_SSE.mp4",
+        "/sdcard/media_api/music_perf/AAC/PD_AAC_56kbps_22.05khz_Stereo_1pCBR_SSE.mp4",
+        "/sdcard/media_api/music_perf/AAC/PD_AAC_56kbps_32khz_Stereo_CBR_SSE.mp4",
+        "/sdcard/media_api/music_perf/AAC/PD_AAC_56kbps_44.1khz_Stereo_1pCBR_SSE.mp4",
+        "/sdcard/media_api/music_perf/AAC/PD_AAC_80kbps_32khz_Stereo_1pCBR_SSE.mp4",
+        "/sdcard/media_api/music_perf/AAC/PD_AAC_80kbps_32khz_Stereo_CBR_SSE.mp4",
+        "/sdcard/media_api/music_perf/AAC/PV_AAC_56kbps_22.05khz_Stereo_1pCBR_SSE.mp4",
+        "/sdcard/media_api/music_perf/AAC/PV_AAC_56kbps_32khz_Stereo_CBR_SSE.mp4",
+        "/sdcard/media_api/music_perf/AAC/PV_AAC_56kbps_44.1khz_Stereo_1pCBR_SSE.mp4",
+        "/sdcard/media_api/music_perf/AAC/PV_AAC_80kbps_32khz_Stereo_1pCBR_SSE.mp4",
+        "/sdcard/media_api/music_perf/AAC/PV_AAC_80kbps_32khz_Stereo_CBR_SSE.mp4",
+        "/sdcard/media_api/music_perf/AAC/WC_AAC_56kbps_22.05khz_Stereo_1pCBR_SSE.mp4",
+        "/sdcard/media_api/music_perf/AAC/WC_AAC_56kbps_32khz_Stereo_CBR_SSE.mp4",
+        "/sdcard/media_api/music_perf/AAC/WC_AAC_56kbps_44.1khz_Stereo_1pCBR_SSE.mp4",
+        "/sdcard/media_api/music_perf/AAC/WC_AAC_80kbps_32khz_Stereo_1pCBR_SSE.mp4",
+        "/sdcard/media_api/music_perf/AAC/WC_AAC_80kbps_32khz_Stereo_CBR_SSE.mp4",      
+    };
+    
+    public static String[] VIDEOFILES = { "/sdcard/media_api/video_perf/AI_CTO_Mpeg4_32kbps_10fps_SQCIF_128x96+AAC_8kbps_8khz_mono_QTE.mp4",
+      "/sdcard/media_api/video_perf/AI_CTO_Mpeg4_32kbps_12fps_SQCIF_128x96+AAC_8kbps_8khz_mono_QTE.mp4",
+      "/sdcard/media_api/video_perf/AI_CTO_Mpeg4_32kbps_15fps_SQCIF_128x96+AAC_8kbps_8khz_mono_QTE.mp4",
+      "/sdcard/media_api/video_perf/AI_CTO_Mpeg4_32kbps_5fps_SQCIF_128x96+AAC_8kbps_8khz_mono_QTE.mp4",
+      "/sdcard/media_api/video_perf/AI_CTO_Mpeg4_32kbps_5fps_SQCIF_128x96+AAC_8kbps_8khz_mono_SSE.mp4",
+      "/sdcard/media_api/video_perf/AI_CTO_Mpeg4_32kbps_7.5fps_SQCIF_128x96+AAC_8kbps_8khz_mono_QTE.mp4",
+      "/sdcard/media_api/video_perf/AI_WMV_1024kbps_20fps_QCIF_176x144_noaudio_SSE.wmv",
+      "/sdcard/media_api/video_perf/AI_WMV_1024kbps_25fps_QCIF_176x144_noaudio_SSE.wmv",
+      "/sdcard/media_api/video_perf/Chicken.wmv",
+      "/sdcard/media_api/video_perf/MP_qcif_15fps_100kbps_48kHz_192kbps_30secs.wmv",
+      "/sdcard/media_api/video_perf/NIN_CTO_H264_123kbps_5fps_QCIF_176x144+AMR_12.2kbps_8khz_mono_QTE.3gp",
+      "/sdcard/media_api/video_perf/NIN_CTO_H264_96kbps_10.2fps_QCIF_176x144+AMR_12.2kbps_8khz_mono_QTE.3gp",
+      "/sdcard/media_api/video_perf/NIN_CTO_H264_96kbps_12fps_QCIF_176x144+AMR_12.2kbps_8khz_mono_QTE.3gp",
+      "/sdcard/media_api/video_perf/NIN_CTO_H264_96kbps_15fps_QCIF_176x144+AMR_12.2kbps_8khz_mono_QTE.3gp",
+      "/sdcard/media_api/video_perf/NIN_CTO_Mpeg4_123kbps_15fps_QCIF_176x144+AAC_32kbps_22khz_mono_SSE.3gp",
+      "/sdcard/media_api/video_perf/NIN_CTO_Mpeg4_123kbps_7.5fps_QCIF_176x144+AAC_32kbps_22khz_stereo_SSE.3gp",
+      "/sdcard/media_api/video_perf/NIN_CTO_Mpeg4_128kbps_10fps_QCIF_176x144+AAC+_32kbps_48khz_stereo_SSE.3gp",
+      "/sdcard/media_api/video_perf/NIN_CTO_Mpeg4_128kbps_12fps_QCIF_176x144+AAC+_32kbps_48khz_stereo_SSE.3gp",
+      "/sdcard/media_api/video_perf/NIN_CTO_Mpeg4_128kbps_15fps_QCIF_176x144+AAC+_32kbps_48khz_stereo_SSE.3gp",
+      "/sdcard/media_api/video_perf/NIN_CTO_Mpeg4_128kbps_5fps_QCIF_176x144+AAC+_32kbps_48khz_stereo_SSE.3gp",
+      "/sdcard/media_api/video_perf/NIN_CTO_Mpeg4_128kbps_7.5fps_QCIF_176x144+AAC+_32kbps_48khz_stereo_SSE.3gp",
+      "/sdcard/media_api/video_perf/NIN_H263_128kbps_10fps_QCIF_174x144_noaudio_SSE.mp4",
+      "/sdcard/media_api/video_perf/NIN_H263_128kbps_15fps_QCIF_174x144_noaudio_SSE.mp4",
+      "/sdcard/media_api/video_perf/NIN_H263_48kbps_10fps_QCIF_174x144_noaudio_SSE.3gp",
+      "/sdcard/media_api/video_perf/NIN_H263_48kbps_12fps_QCIF_174x144_noaudio_SSE.3gp",
+      "/sdcard/media_api/video_perf/NIN_H264_123kbps_15fps_QCIF_176x144+AAC_32kbps_22khz_stereo_SSE.3gp",
+      "/sdcard/media_api/video_perf/NIN_H264_123kbps_7.5fps_QCIF_176x144+AAC_32kbps_22khz_stereo_SSE.3gp",
+      "/sdcard/media_api/video_perf/PV_H264_2000kbps_20fps_CIF_352x288+AAC_96kbps_48khz_stereo_SSE.mp4",
+      "/sdcard/media_api/video_perf/PV_H264_2000kbps_25fps_CIF_352x288+AAC_96kbps_48khz_stereo_SSE.mp4",
+      "/sdcard/media_api/video_perf/PV_H264_2000kbps_30fps_CIF_352x288+AAC_128kbps_48khz_stereo_SSE.mp4",
+      "/sdcard/media_api/video_perf/Stevie-1.wmv",
+      "/sdcard/media_api/video_perf/WC_H264_1600kbps_20fps_QCIF_176x144+AAC_96kbps_48khz_mono_SSE.mp4",
+      "/sdcard/media_api/video_perf/WC_H264_1600kbps_25fps_QCIF_176x144+AAC_96kbps_48khz_mono_SSE.mp4",
+      "/sdcard/media_api/video_perf/WC_H264_1600kbps_30fps_QCIF_176x144+AAC_96kbps_48khz_mono_SSE.mp4",
+      "/sdcard/media_api/video_perf/bugs.wmv",
+      "/sdcard/media_api/video_perf/niceday.wmv",
+      "/sdcard/media_api/video_perf/eaglesatopnflpe.wmv",
+     
+    };
+    
+    //wma - only support up to wma 9
+    public static String[] WMASUPPORTED = {
+      "/sdcard/media_api/music_perf/WMASUPPORTED/AI_WMA9.2_32kbps_44.1khz_mono_CBR_DPA.wma",
+      "/sdcard/media_api/music_perf/WMASUPPORTED/AI_WMA9.2_48kbps_44.1khz_mono_CBR_DPA.wma",
+      "/sdcard/media_api/music_perf/WMASUPPORTED/NIN_WMA9.2_32kbps_44.1khz_mono_CBR_DPA.wma",
+      "/sdcard/media_api/music_perf/WMASUPPORTED/NIN_WMA9.2_48kbps_44.1khz_mono_CBR_DPA.wma",
+      "/sdcard/media_api/music_perf/WMASUPPORTED/PD_WMA9.2_32kbps_44.1khz_mono_CBR_DPA.wma",
+      "/sdcard/media_api/music_perf/WMASUPPORTED/PD_WMA9.2_48kbps_44.1khz_mono_CBR_DPA.wma",
+      "/sdcard/media_api/music_perf/WMASUPPORTED/PV_WMA9.2_32kbps_44.1khz_mono_CBR_DPA.wma",
+      "/sdcard/media_api/music_perf/WMASUPPORTED/PV_WMA9.2_48kbps_44.1khz_mono_CBR_DPA.wma",
+      "/sdcard/media_api/music_perf/WMASUPPORTED/WC_WMA9.2_32kbps_44.1khz_mono_CBR_DPA.wma",
+      "/sdcard/media_api/music_perf/WMASUPPORTED/WC_WMA9.2_48kbps_44.1khz_mono_CBR_DPA.wma"
+      
+    };
+    
+    public static String[] WMAUNSUPPORTED = { 
+      "/sdcard/media_api/music_perf/WMAUNSUPPORTED/AI_WMA10_127kbps_48khz_stereo_CBR_DPA.wma",
+      "/sdcard/media_api/music_perf/WMAUNSUPPORTED/AI_WMA10_128kbps_44.1khz_stereo_2pVBR_DPA.wma",
+      "/sdcard/media_api/music_perf/WMAUNSUPPORTED/AI_WMA10_128kbps_48khz_stereo_2pVBR_DPA.wma",
+      "/sdcard/media_api/music_perf/WMAUNSUPPORTED/AI_WMA10_128kbps_88khz_stereo_CBR_DPA.wma",
+      "/sdcard/media_api/music_perf/WMAUNSUPPORTED/AI_WMA10_128kbps_96khz_stereo_CBR_DPA.wma",
+      "/sdcard/media_api/music_perf/WMAUNSUPPORTED/AI_WMA10_192kbps_44.1khz_stereo_2pVBR_DPA.wma",
+      "/sdcard/media_api/music_perf/WMAUNSUPPORTED/AI_WMA10_192kbps_88khz_stereo_CBR_DPA.wma",
+      "/sdcard/media_api/music_perf/WMAUNSUPPORTED/AI_WMA10_192kbps_96khz_stereo_CBR_DPA.wma",
+      "/sdcard/media_api/music_perf/WMAUNSUPPORTED/AI_WMA10_256kbps_44khz_stereo_CBR_DPA.wma",
+      "/sdcard/media_api/music_perf/WMAUNSUPPORTED/AI_WMA10_256kbps_48khz_stereo_CBR_DPA.wma",
+      "/sdcard/media_api/music_perf/WMAUNSUPPORTED/AI_WMA10_256kbps_88khz_stereo_CBR_DPA.wma",
+      "/sdcard/media_api/music_perf/WMAUNSUPPORTED/AI_WMA10_256kbps_96khz_stereo_CBR_DPA.wma",
+      "/sdcard/media_api/music_perf/WMAUNSUPPORTED/AI_WMA10_384kbps_44khz_stereo_CBR_DPA.wma",
+      "/sdcard/media_api/music_perf/WMAUNSUPPORTED/AI_WMA10_384kbps_48khz_stereo_CBR_DPA.wma",
+      "/sdcard/media_api/music_perf/WMAUNSUPPORTED/AI_WMA10_384kbps_88khz_stereo_CBR_DPA.wma"
+    };
+    
+    //Media Recorder
+    public static final String RECORDER_OUTPUT = "/sdcard/media_api/recorderOutput.amr";
+    
+    //video thumbnail
+    public static final String THUMBNAIL_OUTPUT = "/sdcard/media_api/videoThumbnail.png";
+    public static final String GOLDEN_THUMBNAIL_OUTPUT = "/sdcard/media_api/goldenThumbnail.png";
+    
+    //Metadata Utility
+    public static final String[] THUMBNAIL_CAPTURE_TEST_FILES = {
+      "/sdcard/media_api/metadata/test.mp4",
+      "/sdcard/media_api/metadata/test1.3gp",
+      "/sdcard/media_api/metadata/test2.3gp",
+      "/sdcard/media_api/metadata/test3.3gp",
+      "/sdcard/media_api/metadata/test4.3gp",
+      "/sdcard/media_api/metadata/test5.3gp",
+      "/sdcard/media_api/metadata/test6.3gp",
+      "/sdcard/media_api/metadata/test7.3gp",
+      "/sdcard/media_api/metadata/test8.3gp",
+      "/sdcard/media_api/metadata/test9.3gp",
+      "/sdcard/media_api/metadata/test10.3gp",
+      "/sdcard/media_api/metadata/test11.3gp",
+      "/sdcard/media_api/metadata/test12.3gp",
+      "/sdcard/media_api/metadata/test13.3gp",
+      "/sdcard/media_api/metadata/test14.3gp",
+      "/sdcard/media_api/metadata/test15.3gp",
+      "/sdcard/media_api/metadata/test16.3gp",
+      "/sdcard/media_api/metadata/test17.3gp",
+      "/sdcard/media_api/metadata/test18.3gp",
+      "/sdcard/media_api/metadata/test19.3gp",
+      "/sdcard/media_api/metadata/test20.3gp",
+      "/sdcard/media_api/metadata/test21.3gp",
+      "/sdcard/media_api/metadata/test22.3gp",
+      "/sdcard/media_api/metadata/test23.3gp",
+      "/sdcard/media_api/metadata/test24.3gp",
+      "/sdcard/media_api/metadata/test25.3gp",
+      "/sdcard/media_api/metadata/test26.3gp",
+      "/sdcard/media_api/metadata/test27.3gp",
+      "/sdcard/media_api/metadata/test28.3gp",
+      "/sdcard/media_api/metadata/test29.3gp",
+      "/sdcard/media_api/metadata/test30.3gp",
+      "/sdcard/media_api/metadata/test31.3gp",
+      "/sdcard/media_api/metadata/test32.3gp",
+      "/sdcard/media_api/metadata/test33.3gp",
+      "/sdcard/media_api/metadata/test35.mp4",
+      "/sdcard/media_api/metadata/test36.m4v",
+      "/sdcard/media_api/metadata/test34.wmv",
+      "/sdcard/media_api/metadata/test_metadata.mp4",
+  };
+  
+  public static final String[] METADATA_RETRIEVAL_TEST_FILES = {
+      // Raw AAC is not supported
+      // "/sdcard/media_api/test_raw.aac",
+      // "/sdcard/media_api/test_adts.aac",
+      // "/sdcard/media_api/test_adif.aac",
+      "/sdcard/media_api/metadata/test_metadata.mp4",
+      "/sdcard/media_api/metadata/WMA10.wma",
+      "/sdcard/media_api/metadata/Leadsol_out.wav",
+      "/sdcard/media_api/metadata/test_aac.mp4",
+      "/sdcard/media_api/metadata/test_amr.mp4",
+      "/sdcard/media_api/metadata/test_avc_amr.mp4",
+      "/sdcard/media_api/metadata/test_metadata.mp4",
+      "/sdcard/media_api/metadata/test_vbr.mp3",
+      "/sdcard/media_api/metadata/test_cbr.mp3",
+      "/sdcard/media_api/metadata/metadata_test1.mp3",
+      "/sdcard/media_api/metadata/test33.3gp",
+      "/sdcard/media_api/metadata/test35.mp4",
+      "/sdcard/media_api/metadata/test36.m4v",
+      "/sdcard/media_api/metadata/test_m4v_amr.mp4",
+      "/sdcard/media_api/metadata/test_h263_amr.mp4",
+      "/sdcard/media_api/metadata/test34.wmv",
+  };
+  
+  public static final String[] ALBUMART_TEST_FILES = {
+      "/sdcard/media_api/album_photo/test_22_16_mp3.mp3",
+      "/sdcard/media_api/album_photo/PD_256kbps_48khz_mono_CBR_MCA.mp3",
+      "/sdcard/media_api/album_photo/PD_256kbps_44.1khz_mono_CBR_DPA.mp3",
+      "/sdcard/media_api/album_photo/PD_192kbps_32khz_mono_CBR_DPA.mp3",
+      "/sdcard/media_api/album_photo/NIN_256kbps_48khz_mono_CBR_MCA.mp3",
+      "/sdcard/media_api/album_photo/NIN_256kbps_44.1khz_mono_CBR_MCA.mp3",
+      "/sdcard/media_api/album_photo/NIN_112kbps(96kbps)_48khz_stereo_VBR_MCA.mp3",
+      "/sdcard/media_api/album_photo/NIN_112kbps(96kbps)_44.1khz_stereo_VBR_MCA.mp3",
+      "/sdcard/media_api/album_photo/lightGreen1.mp3",
+      "/sdcard/media_api/album_photo/babyBlue2 1.mp3",
+      "/sdcard/media_api/album_photo/2-01 01 NIN_56kbps(64kbps)_32khz_stereo_VBR_MCA.mp3",
+      "/sdcard/media_api/album_photo/02_NIN_112kbps(80kbps)_32khz_stereo_VBR_MCA.mp3",
+      "/sdcard/media_api/album_photo/No_Woman_No_Cry_128K.wma",
+      "/sdcard/media_api/album_photo/Beethoven_2.wma",
+  };
+
+  //TEST_PATH_1: is a video and contains metadata for key "num-tracks"
+  // TEST_PATH_2: any valid media file.
+  // TEST_PATH_3: invalid media file
+  public static final String TEST_PATH_1 = "/sdcard/media_api/metadata/test.mp4";
+  public static final String TEST_PATH_3 = "/sdcard/media_api/data.txt";
+  public static final String TEST_PATH_4 = "somenonexistingpathname";
+  public static final String TEST_PATH_5 = "mem://012345";
+  
+  //Meta data expected result
+  //The expected tag result in the following order
+  //cd_track_number, album, artist, author, composer, date, genre
+  //title, years, duration
+  public static final String META_DATA_MP3 [][] = {
+      {"/sdcard/media_api/metaDataTestMedias/MP3/ID3V1_ID3V2.mp3", "1/10", "ID3V2.3 Album", "ID3V2.3 Artist",
+          "ID3V2.3 Lyricist", "ID3V2.3 Composer", null, "Blues",
+          "ID3V2.3 Title", "1234", "321", "1"},
+      {"/sdcard/media_api/metaDataTestMedias/MP3/ID3V2.mp3", "1/10", "ID3V2.3 Album", "ID3V2.3 Artist",
+          "ID3V2.3 Lyricist", "ID3V2.3 Composer", null, "Blues", 
+          "ID3V2.3 Title", "1234", "313", "1"},
+      {"/sdcard/media_api/metaDataTestMedias/MP3/ID3V1.mp3", null, "test ID3V1 Album", "test ID3V1 Artist",
+          null, null, null, null, "test ID3V1 Title", "1234", "231332", "1"},
+      {"/sdcard/media_api/metaDataTestMedias/MP3/Corrupted_ID3V1.mp3" , null, null, null,
+              null, null, null, null, null, null, "231330", "1"},
+      //The corrupted TALB field in id3v2 would not switch to id3v1 tag automatically
+      {"/sdcard/media_api/metaDataTestMedias/MP3/Corrupted_ID3V2_TALB.mp3", "01", null, "ID3V2.3 Artist",
+          "ID3V2.3 Lyricist", "ID3V2.3 Composer", null, 
+          "Blues", "ID3V2.3 Title", "1234", "321", "1"},
+      {"/sdcard/media_api/metaDataTestMedias/MP3/Corrupted_ID3V2_TCOM.mp3", "01", "ID3V2.3 Album", 
+           "ID3V2.3 Artist", "ID3V2.3 Lyricist", null, null, 
+           "Blues", "ID3V2.3 Title", "1234", "321", "1"},
+      {"/sdcard/media_api/metaDataTestMedias/MP3/Corrupted_ID3V2_TCOM_2.mp3", "01", "ID3V2.3 Album", 
+           "ID3V2.3 Artist", null, null, null, "Blues", "ID3V2.3 Title", "1234", "321", "1"},
+      {"/sdcard/media_api/metaDataTestMedias/MP3/Corrupted_ID3V2_TRCK.mp3", "dd", "ID3V2.3 Album", 
+           "ID3V2.3 Artist", "ID3V2.3 Lyricist", "ID3V2.3 Composer", null,
+           "Blues", "ID3V2.3 Title", "1234", "321", "1"},
+      {"/sdcard/media_api/metaDataTestMedias/MP3/Corrupted_ID3V2_TRCK_2.mp3", "01", "ID3V2.3 Album", 
+           "ID3V2.3 Artist", null, null, null, null, "ID3V2.3 Title", null, "321", "1"},
+      {"/sdcard/media_api/metaDataTestMedias/MP3/Corrupted_ID3V2_TYER.mp3", "01", "ID3V2.3 Album",
+           "ID3V2.3 Artist", null, null, null, null, "ID3V2.3 Title", "9999", "321", "1"},
+      {"/sdcard/media_api/metaDataTestMedias/MP3/Corrupted_ID3V2_TYER_2.mp3", "01", "ID3V2.3 Album",
+           "ID3V2.3 Artist", "ID3V2.3 Lyricist", "ID3V2.3 Composer", null, 
+           "Blues", "ID3V2.3 Title", null, "321", "1"},
+      {"/sdcard/media_api/metaDataTestMedias/MP3/Corrupted_ID3V2_TIT.mp3", null, null, null,
+          null, null, null, null, null, null, "577", "1"}
+  };
+
+  public static final String META_DATA_OTHERS [][] = {
+      {"/sdcard/media_api/metaDataTestMedias/3GP/cat.3gp", null, null, null,
+          null, null, "20080309T002415.000Z", null,
+          null, null, "1404928", "2"},
+      {"/sdcard/media_api/metaDataTestMedias/AMR/AMR_NB.amr", null, null, null,
+          null, null, null, null,
+          null, null, "126540", "1"},
+      {"/sdcard/media_api/metaDataTestMedias/AMRWB/AMR_WB.amr", null, null, null,
+          null, null, null, null,
+          null, null, "231180", "1"},     
+      {"/sdcard/media_api/metaDataTestMedias/M4A/Jaws Of Life_ver1.m4a", null, "Suspended Animation", 
+          "John Petrucci", null, null, "20070510T125223.000Z", 
+          null, null, "2005", "231180", "1"},     
+      {"/sdcard/media_api/metaDataTestMedias/M4V/sample_iPod.m4v", null, null, 
+          null, null, null, "20051220T202015.000Z", 
+          null, null, null, "3771392", "2"}, 
+      {"/sdcard/media_api/metaDataTestMedias/MIDI/MIDI.mid", null, "Suspended Animation", 
+          "John Petrucci", null, null, "20070510T125223.000Z", 
+          null, null, "2005", "231180", "1"}, 
+      {"/sdcard/media_api/metaDataTestMedias/MP4/kung_fu_panda_h264.mp4", null, "mp4 album Kung Fu Panda", 
+          "mp4 artist Kung Fu Panda", null, null, "20080517T091451.000Z", 
+          "Kung Fu Panda", "Kung Fu Panda", "2008", "5667840", "2"},
+      {"/sdcard/media_api/metaDataTestMedias/OGG/Ring_Classic_02.ogg", null, "Suspended Animation", 
+          "John Petrucci", null, null, "20070510T125223.000Z", 
+          null, null, "2005", "231180", "1"},
+      {"/sdcard/media_api/metaDataTestMedias/OGG/When You Say Nothing At All.ogg", 
+          null, "Suspended Animation", "John Petrucci", 
+          null, null, "20070510T125223.000Z", null, null, "2005", "231180", "1"},
+      {"/sdcard/media_api/metaDataTestMedias/WAV/Im With You.wav", null, null, 
+          null, null, null, null, 
+          null, null, null, "224000", "1"},
+      {"/sdcard/media_api/metaDataTestMedias/WMA/WMA9.wma", "6", "Ten Songs in the Key of Betrayal", 
+          "Alien Crime Syndicate", "Alien Crime Syndicate", 
+          "wma 9 Composer", "20040521T175729.483Z", 
+          "Rock", "Run for the Money", "2004", "134479", "1"},
+      {"/sdcard/media_api/metaDataTestMedias/WMA/WMA10.wma", "09", "wma 10 Album", 
+          "wma 10 Album Artist", "wma 10 Artist", "wma 10 Composer", "20070705T063625.097Z", 
+          "Acid Jazz", "wma 10 Title", "2010", "126574", "1"},
+      {"/sdcard/media_api/metaDataTestMedias/WMV/bugs.wmv", "8", "wmv 9 Album", 
+          null, "wmv 9 Artist ", null, "20051122T155247.540Z", 
+          null, "Looney Tunes - Hare-Breadth Hurry", "2005", "193482", "2"},
+      {"/sdcard/media_api/metaDataTestMedias/WMV/clips_ver7.wmv", "50", "wmv 7 Album", 
+          null, "Hallau Shoots & Company", null, "20020226T170045.891Z", 
+          null, "CODEC Shootout", "1986", "43709", "2"}
+  };
+  
+  //output recorded video
+  
+  public static final String RECORDED_HVGA_H263 = "/sdcard/HVGA_H263.3gp";
+  public static final String RECORDED_QVGA_H263 = "/sdcard/QVGA_H263.3gp";
+  public static final String RECORDED_SQVGA_H263 = "/sdcard/SQVGA_H263.3gp";
+  public static final String RECORDED_CIF_H263 = "/sdcard/CIF_H263.3gp";
+  public static final String RECORDED_QCIF_H263 = "/sdcard/QCIF_H263.3gp";
+  
+  public static final String RECORDED_HVGA_MP4 = "/sdcard/HVGA_mp4.mp4";
+  public static final String RECORDED_QVGA_MP4 = "/sdcard/QVGA_mp4.mp4";
+  public static final String RECORDED_SQVGA_MP4 = "/sdcard/SQVGA_mp4.mp4";
+  public static final String RECORDED_CIF_MP4 = "/sdcard/CIF_mp4.mp4";
+  public static final String RECORDED_QCIF_MP4 = "/sdcard/QCIF_mp4.mp4";
+  
+  public static final String RECORDED_VIDEO_3GP = "/sdcard/temp.3gp";
+  
+  public static final String INVALD_VIDEO_PATH = "/sdcard/media_api/filepathdoesnotexist" +
+      "/filepathdoesnotexist/temp.3gp";
+  
+ 
+  public static final long RECORDED_TIME = 5000;
+  public static final long VALID_VIDEO_DURATION = 2000;
+  
+  //Videos for the mediaplayer stress test
+  public static String[] H263_STRESS = { 
+      "/sdcard/media_api/video_stress/h263/H263_CIF.3gp",
+      "/sdcard/media_api/video_stress/h263/H263_QCIF.3gp",
+      "/sdcard/media_api/video_stress/h263/H263_QVGA.3gp",
+      "/sdcard/media_api/video_stress/h263/H263_SQVGA.3gp"
+  };
+  
+  public static String[] MPEG4_STRESS = { 
+    "/sdcard/media_api/video_stress/h263/mpeg4_CIF.mp4",
+    "/sdcard/media_api/video_stress/h263/mpeg4_QCIF.3gp",
+    "/sdcard/media_api/video_stress/h263/mpeg4_QVGA.3gp",
+    "/sdcard/media_api/video_stress/h263/mpeg4_SQVGA.mp4"
+  };
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaRecorderStressTestRunner.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaRecorderStressTestRunner.java
new file mode 100755
index 0000000..12eacd3
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaRecorderStressTestRunner.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+package com.android.mediaframeworktest;
+
+import android.test.InstrumentationTestRunner;
+import android.test.InstrumentationTestSuite;
+import com.android.mediaframeworktest.stress.MediaRecorderStressTest;
+
+import junit.framework.TestSuite;
+
+public class MediaRecorderStressTestRunner extends InstrumentationTestRunner {
+
+    @Override
+    public TestSuite getAllTests() {
+        TestSuite suite = new InstrumentationTestSuite(this);
+        suite.addTestSuite(MediaRecorderStressTest.class);
+        return suite;
+    }
+
+    @Override
+    public ClassLoader getLoader() {
+        return MediaRecorderStressTestRunner.class.getClassLoader();
+    }
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/CameraTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/CameraTest.java
new file mode 100644
index 0000000..59803f7d
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/CameraTest.java
@@ -0,0 +1,262 @@
+/*
+ * 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.
+ */
+
+package com.android.mediaframeworktest.functional;
+
+import com.android.mediaframeworktest.MediaFrameworkTest;
+import com.android.mediaframeworktest.MediaNames;
+
+import java.io.*;
+
+import android.content.Context;
+import android.hardware.Camera;
+import android.hardware.Camera.PictureCallback;
+import android.hardware.Camera.PreviewCallback;
+import android.hardware.Camera.ShutterCallback;
+import android.test.ActivityInstrumentationTestCase;
+import android.util.Log;
+import android.view.SurfaceHolder;
+
+import android.os.Looper;
+
+import android.test.suitebuilder.annotation.LargeTest;
+
+/**
+ * Junit / Instrumentation test case for the camera api
+ 
+ */  
+public class CameraTest extends ActivityInstrumentationTestCase<MediaFrameworkTest> {    
+    private String TAG = "CameraTest";
+    
+    private boolean rawPreviewCallbackResult = false;
+    private boolean shutterCallbackResult = false;
+    private boolean rawPictureCallbackResult = false;
+    private boolean jpegPictureCallbackResult = false;
+    
+    private static int WAIT_FOR_COMMAND_TO_COMPLETE = 10000;  // Milliseconds.
+    
+    private RawPreviewCallback mRawPreviewCallback = new RawPreviewCallback();
+    private TestShutterCallback mShutterCallback = new TestShutterCallback();
+    private RawPictureCallback mRawPictureCallback = new RawPictureCallback();
+    private JpegPictureCallback mJpegPictureCallback = new JpegPictureCallback();
+    
+    private boolean mInitialized = false;
+    private Looper mLooper = null;
+    private final Object lock = new Object();
+    private final Object previewDone = new Object();
+    
+    Camera mCamera;
+    Context mContext;
+  
+    public CameraTest() {
+        super("com.android.mediaframeworktest", MediaFrameworkTest.class);
+    }
+
+    protected void setUp() throws Exception {
+        super.setUp(); 
+    }
+   
+    /*
+     * Initializes the message looper so that the Camera object can 
+     * receive the callback messages.
+     */
+    private void initializeMessageLooper() {
+        Log.v(TAG, "start looper");
+        new Thread() {
+            @Override
+            public void run() {
+                // Set up a looper to be used by camera.
+                Looper.prepare();
+                Log.v(TAG, "start loopRun");
+                // Save the looper so that we can terminate this thread 
+                // after we are done with it.
+                mLooper = Looper.myLooper();                
+                mCamera = Camera.open();                                
+                synchronized (lock) {
+                    mInitialized = true;
+                    lock.notify();
+                }
+                Looper.loop();  // Blocks forever until Looper.quit() is called.
+                Log.v(TAG, "initializeMessageLooper: quit.");
+            }
+        }.start();
+    }
+    
+    /*
+     * Terminates the message looper thread.
+     */
+    private void terminateMessageLooper() {
+        mLooper.quit();
+        mCamera.release();
+    }
+    
+    //Implement the previewCallback
+    private final class RawPreviewCallback implements PreviewCallback { 
+        public void onPreviewFrame(byte [] rawData, Camera camera) {         
+            Log.v(TAG, "Preview callback start");            
+            int rawDataLength = 0;
+            if (rawData != null) {
+                rawDataLength = rawData.length;
+            }
+            if (rawDataLength > 0) {
+                rawPreviewCallbackResult = true;
+            } else {
+                rawPreviewCallbackResult = false;
+            }
+            synchronized (previewDone) {
+                Log.v(TAG, "notify the preview callback");
+                previewDone.notify();
+            }
+            
+            Log.v(TAG, "Preview callback stop");
+        }
+    };
+    
+    //Implement the shutterCallback
+    private final class TestShutterCallback implements ShutterCallback {
+        public void onShutter() {
+            shutterCallbackResult = true;
+            Log.v(TAG, "onShutter called");
+        }
+    };
+    
+    //Implement the RawPictureCallback
+    private final class RawPictureCallback implements PictureCallback { 
+        public void onPictureTaken(byte [] rawData, Camera camera) {
+           // no support for raw data - success if we get the callback
+           rawPictureCallbackResult = true;
+           //if (rawData != null) {
+           //    rawPictureCallbackResult = true;
+           //} else {
+           //    rawPictureCallbackResult = false;
+           //}
+            Log.v(TAG, "RawPictureCallback callback");
+        }
+    };
+    
+    //Implement the JpegPictureCallback
+    private final class JpegPictureCallback implements PictureCallback {   
+        public void onPictureTaken(byte [] rawData, Camera camera) {           
+            try {         
+                if (rawData != null) {
+                    int rawDataLength = rawData.length;
+                    File rawoutput = new File("/sdcard/test.bmp");
+                    FileOutputStream outstream = new FileOutputStream(rawoutput);
+                    outstream.write(rawData);                   
+                    Log.v(TAG, "JpegPictureCallback rawDataLength = " + rawDataLength);
+                    jpegPictureCallbackResult = true;
+                } else {
+                    jpegPictureCallbackResult = false;
+                }
+                Log.v(TAG, "Jpeg Picture callback");
+            } catch (Exception e) {
+                Log.v(TAG, e.toString());
+            }
+        }
+    };
+   
+    
+    private void checkTakePicture() { 
+        SurfaceHolder mSurfaceHolder;
+        try {
+            mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
+            mCamera.setPreviewDisplay(mSurfaceHolder);
+            Log.v(TAG, "Start preview");
+            mCamera.startPreview();
+            synchronized (previewDone) {
+                try {
+                    previewDone.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
+                    Log.v(TAG, "Preview Done");
+                } catch (Exception e) {
+                    Log.v(TAG, "wait was interrupted.");
+                }
+            }
+            mCamera.setPreviewCallback(null);
+            mCamera.takePicture(mShutterCallback, mRawPictureCallback, mJpegPictureCallback);
+            Thread.sleep(MediaNames.WAIT_LONG);
+        } catch (Exception e) {
+            Log.v(TAG, e.toString());
+        }      
+    }
+    
+    private void checkPreviewCallback() { 
+        SurfaceHolder mSurfaceHolder;
+        try {
+            mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
+            mCamera.setPreviewDisplay(mSurfaceHolder);
+            Log.v(TAG, "start preview");
+            mCamera.startPreview();                      
+            synchronized (previewDone) {
+                try {
+                    previewDone.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
+                    Log.v(TAG, "setPreview done");
+                } catch (Exception e) {
+                    Log.v(TAG, "wait was interrupted.");
+                }
+            }
+            mCamera.setPreviewCallback(null);
+        } catch (Exception e) {
+            Log.v(TAG, e.toString());
+        }      
+    }
+    
+    /*
+     * TODO(yslau): Need to setup the golden rawData and compare the 
+     * the new captured rawData with the golden one.       
+     * 
+     * Test case 1: Take a picture and verify all the callback
+     * functions are called properly.
+     */
+    @LargeTest
+    public void testTakePicture() throws Exception {  
+        initializeMessageLooper();
+        synchronized (lock) {
+            try {
+                lock.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
+            } catch(Exception e) {
+                Log.v(TAG, "runTestOnMethod: wait was interrupted.");
+            }
+        }
+        mCamera.setPreviewCallback(mRawPreviewCallback);
+        checkTakePicture();
+        terminateMessageLooper();
+        assertTrue("shutterCallbackResult", shutterCallbackResult);
+        assertTrue("rawPictureCallbackResult", rawPictureCallbackResult);
+        assertTrue("jpegPictureCallbackResult", jpegPictureCallbackResult);
+    }
+    
+    /*
+     * Test case 2: Set the preview and 
+     * verify the RawPreviewCallback is called
+     */
+    @LargeTest
+    public void testCheckPreview() throws Exception {  
+        initializeMessageLooper();
+        synchronized (lock) {
+            try {
+                lock.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
+            } catch(Exception e) {
+                Log.v(TAG, "wait was interrupted.");
+            }
+        }
+        mCamera.setPreviewCallback(mRawPreviewCallback);
+        checkPreviewCallback();     
+        terminateMessageLooper();
+        assertTrue("RawPreviewCallbackResult", rawPreviewCallbackResult);
+    }
+
+}
+
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/CodecTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/CodecTest.java
new file mode 100644
index 0000000..0e88719
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/CodecTest.java
@@ -0,0 +1,577 @@
+/*
+ * 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.
+ */
+
+package com.android.mediaframeworktest.functional;
+
+
+
+//import android.content.Resources;
+import com.android.mediaframeworktest.MediaFrameworkTest;
+import com.android.mediaframeworktest.MediaNames;
+
+import android.content.res.AssetFileDescriptor;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.media.MediaMetadataRetriever;
+import android.media.MediaPlayer;
+import android.media.MediaRecorder;
+import android.os.SystemClock;
+import android.util.Log;
+
+import java.io.IOException;
+import java.io.InputStream;
+/**
+ * Junit / Instrumentation test case for the media player api
+ 
+ */  
+public class CodecTest {    
+    private static String TAG = "MediaPlayerApiTest";
+
+    public static String printCpuInfo(){      
+        String cm = "dumpsys cpuinfo";
+        String cpuinfo =null;
+        int ch;
+        try{
+            Process  p = Runtime.getRuntime().exec(cm);
+            InputStream in = p.getInputStream();        
+            StringBuffer sb = new StringBuffer(512);
+            while ( ( ch = in.read() ) != -1 ){  
+                sb.append((char) ch); 
+            }
+            cpuinfo = sb.toString();      
+        }catch (IOException e){
+            Log.v(TAG, e.toString());
+        }
+        return cpuinfo;
+    }
+
+
+    public static int getDuration(String filePath) {
+        Log.v(TAG, "getDuration - " + filePath);
+        MediaPlayer mp = new MediaPlayer();
+        try{
+            mp.setDataSource(filePath);
+            mp.prepare(); 
+        }catch (Exception e){}
+        int duration = mp.getDuration();
+        Log.v(TAG, "Duration " + duration);
+        mp.release();
+        Log.v(TAG, "release");      
+        return duration;
+    }
+
+    public static boolean getCurrentPosition(String filePath){
+        Log.v(TAG, "GetCurrentPosition - " + filePath);
+        int currentPosition = 0;
+        long t1=0;
+        long t2 =0;
+        MediaPlayer mp = new MediaPlayer();
+        try{
+            mp.setDataSource(filePath);
+            Log.v(TAG, "start playback");
+            mp.prepare();
+            mp.start();
+            t1=SystemClock.uptimeMillis();
+            Thread.sleep(10000);
+            mp.pause();
+            Thread.sleep(MediaNames.PAUSE_WAIT_TIME);
+            t2=SystemClock.uptimeMillis();
+        }catch (Exception e){
+            Log.v(TAG, e.toString());
+        }
+        currentPosition = mp.getCurrentPosition();
+        mp.stop();
+        mp.release();   
+        Log.v(TAG, "mp currentPositon = " + currentPosition + " play duration = " + (t2-t1));
+        //The currentposition should be within 10% of the sleep time
+        //For the very short mp3, it should return the length instead of 10 seconds
+        if (filePath.equals(MediaNames.SHORTMP3)){
+            if (currentPosition < 1000 )
+                return true;
+        }
+        if ((currentPosition < ((t2-t1) *1.2)) && (currentPosition > 0)) 
+            return true;
+        else
+            return false;
+    }  
+
+    public static boolean seekTo(String filePath){
+        Log.v(TAG, "seekTo " + filePath);
+        int currentPosition = 0;
+        MediaPlayer mp = new MediaPlayer();
+        try{
+            mp.setDataSource(filePath);
+            mp.prepare();
+            mp.start();
+            mp.seekTo(MediaNames.SEEK_TIME);
+            Thread.sleep(MediaNames.WAIT_TIME);
+            currentPosition = mp.getCurrentPosition();
+        }catch (Exception e){
+            Log.v(TAG, e.getMessage());
+        }      
+        mp.stop();
+        mp.release();
+        Log.v(TAG, "CurrentPosition = " + currentPosition);
+        //The currentposition should be at least greater than the 80% of seek time
+        if ((currentPosition > MediaNames.SEEK_TIME *0.8)) 
+            return true;
+        else
+            return false;
+    }
+
+    public static boolean setLooping(String filePath){
+        int currentPosition = 0;
+        int duration = 0;
+        long t1 =0;
+        long t2 =0;
+        Log.v (TAG, "SetLooping - " + filePath);
+        MediaPlayer mp = new MediaPlayer();
+        try{
+            mp.setDataSource(filePath);
+            mp.prepare();
+            duration = mp.getDuration(); 
+            Log.v(TAG, "setLooping duration " + duration);
+            mp.setLooping(true);
+            mp.start();
+            Thread.sleep(5000);
+            mp.seekTo(duration - 5000);
+            t1=SystemClock.uptimeMillis();
+            Thread.sleep(20000);
+            t2=SystemClock.uptimeMillis();
+            Log.v(TAG, "pause");
+            //Bug# 1106852 - IllegalStateException will be thrown if pause is called 
+            //in here
+            //mp.pause();
+            currentPosition = mp.getCurrentPosition();
+            Log.v(TAG, "looping position " + currentPosition + "duration = " + (t2-t1));
+        }catch (Exception e){
+            Log.v(TAG, "Exception : " + e.toString());
+        }      
+        mp.stop();
+        mp.release();
+        //The current position should be within 20% of the sleep time
+        //and should be greater than zero.
+        if ((currentPosition < ((t2-t1-5000)*1.2)) && currentPosition > 0)
+            return true;
+        else
+            return false;
+    }  
+
+    public static boolean pause(String filePath) throws Exception {
+        Log.v(TAG, "pause - " + filePath);
+        boolean misPlaying = true;
+        boolean pauseResult = false;
+        long t1=0;
+        long t2=0;
+        MediaPlayer mp = new MediaPlayer();
+        mp.setDataSource(filePath);
+        mp.prepare();    
+        int duration = mp.getDuration();
+        mp.start();
+        t1=SystemClock.uptimeMillis();
+        Thread.sleep(5000);
+        mp.pause();
+        Thread.sleep(MediaNames.PAUSE_WAIT_TIME);
+        t2=SystemClock.uptimeMillis();
+        misPlaying = mp.isPlaying();
+        int curPosition = mp.getCurrentPosition();
+        Log.v(TAG, filePath + " pause currentPositon " + curPosition);
+        Log.v(TAG, "isPlaying "+ misPlaying + " wait time " + (t2 - t1) );
+        String cpuinfo = printCpuInfo();
+        Log.v(TAG, cpuinfo);
+        if ((curPosition>0) && (curPosition < ((t2-t1) * 1.3)) && (misPlaying == false))
+            pauseResult = true;
+        mp.stop();
+        mp.release();
+        return pauseResult;
+    }
+
+    public static void prepareStopRelease(String filePath) throws Exception {
+        Log.v(TAG, "prepareStopRelease" + filePath);
+        MediaPlayer mp = new MediaPlayer();
+        mp.setDataSource(filePath);
+        mp.prepare();
+        mp.stop();
+        mp.release();
+    }
+
+    public static void preparePauseRelease(String filePath) throws Exception {
+        Log.v(TAG, "preparePauseRelease" + filePath);
+        MediaPlayer mp = new MediaPlayer();
+        mp.setDataSource(filePath);
+        mp.prepare();
+        mp.pause();
+        mp.release();
+    }
+
+    public static int videoHeight(String filePath) throws Exception {
+        Log.v(TAG, "videoHeight - " + filePath);
+        int videoHeight = 0;
+        MediaPlayer mp = new MediaPlayer();
+        mp.setDataSource(filePath);
+        mp.setDisplay(MediaFrameworkTest.mSurfaceView.getHolder());
+        mp.prepare();
+        videoHeight = mp.getVideoHeight();
+        mp.release();
+        return videoHeight;
+    }
+
+    public static int videoWidth(String filePath) throws Exception {
+        Log.v(TAG, "videoWidth - " + filePath);
+        int videoWidth = 0;
+        MediaPlayer mp = new MediaPlayer();
+        mp.setDataSource(filePath);
+        mp.setDisplay(MediaFrameworkTest.mSurfaceView.getHolder());
+        mp.prepare();
+        videoWidth = mp.getVideoWidth();
+        mp.release();
+        return videoWidth;
+    }
+
+    //This also test the streaming video which may take a long
+    //time to start the playback. 
+    public static boolean videoSeekTo(String filePath) throws Exception {
+        Log.v(TAG, "videoSeekTo - " + filePath);
+        int currentPosition = 0;
+        int duration = 0;
+        boolean videoResult = false;
+        MediaPlayer mp = new MediaPlayer();
+        mp.setDataSource(filePath);
+        mp.setDisplay(MediaFrameworkTest.mSurfaceView.getHolder());
+        mp.prepare();
+        mp.start();
+        if (filePath.equals(MediaNames.VIDEO_SHORT_3GP)){
+            mp.pause();
+            Thread.sleep(MediaNames.PAUSE_WAIT_TIME);
+            mp.seekTo(0);
+            mp.start();
+            Thread.sleep(1000);
+            currentPosition = mp.getCurrentPosition();
+            Log.v(TAG,"short position " + currentPosition);
+            if (currentPosition > 100 )
+                return true;
+            else
+                return false;
+        }
+        Thread.sleep(5000);
+        duration = mp.getDuration();
+        Log.v(TAG, "video duration " + duration);
+        mp.pause();
+        Thread.sleep(MediaNames.PAUSE_WAIT_TIME);
+        mp.seekTo(duration - 20000 );
+        mp.start();
+        Thread.sleep(1000);
+        mp.pause();
+        Thread.sleep(MediaNames.PAUSE_WAIT_TIME);
+        mp.seekTo(duration/2);
+        mp.start();
+        Thread.sleep(10000);
+        currentPosition = mp.getCurrentPosition();
+        Log.v(TAG, "video currentPosition " + currentPosition);
+        mp.release();
+        if (currentPosition > (duration /2 )*0.9)
+            return true;
+        else
+            return false;
+
+    }
+
+    public static boolean seekToEnd(String filePath){
+        Log.v(TAG, "seekToEnd - " + filePath);
+        int duration = 0;
+        int currentPosition = 0;
+        boolean isPlaying = false;
+        MediaPlayer mp = new MediaPlayer();
+        try{
+            mp.setDataSource(filePath);
+            Log.v(TAG, "start playback");
+            mp.prepare();
+            duration = mp.getDuration();
+            mp.seekTo(duration - 3000);
+            mp.start();
+            Thread.sleep(6000);
+        }catch (Exception e){}
+        isPlaying = mp.isPlaying();
+        currentPosition = mp.getCurrentPosition();
+        Log.v(TAG, "seekToEnd currentPosition= " + currentPosition + " isPlaying = " + isPlaying);
+        mp.stop();
+        mp.release();   
+        Log.v(TAG, "duration = " + duration);
+        if (currentPosition < 0.9 * duration || isPlaying)
+            return false;
+        else
+            return true;        
+    }
+
+    public static boolean shortMediaStop(String filePath){
+        Log.v(TAG, "shortMediaStop - " + filePath);
+        //This test is only for the short media file
+        int duration = 0;
+        int currentPosition = 0;
+        boolean isPlaying = false;
+        MediaPlayer mp = new MediaPlayer();
+        try{
+            mp.setDataSource(filePath);
+            Log.v(TAG, "start playback");
+            mp.prepare();
+            duration = mp.getDuration();
+            mp.start();
+            Thread.sleep(10000);
+        }catch (Exception e){}
+        isPlaying = mp.isPlaying();
+        currentPosition = mp.getCurrentPosition();
+        Log.v(TAG, "seekToEnd currentPosition= " + currentPosition + " isPlaying = " + isPlaying);
+        mp.stop();
+        mp.release();   
+        Log.v(TAG, "duration = " + duration);
+        if (currentPosition > duration || isPlaying)
+            return false;
+        else
+            return true;        
+    }
+
+    public static boolean playToEnd(String filePath){
+        Log.v(TAG, "shortMediaStop - " + filePath);
+        //This test is only for the short media file
+        int duration = 200000;
+        int updateDuration = 0;
+        int currentPosition = 0;
+        boolean isPlaying = false;
+        MediaPlayer mp = new MediaPlayer();
+        try{
+            Thread.sleep(5000);
+            mp.setDataSource(filePath);
+            Log.v(TAG, "start playback");
+            mp.prepare();
+            //duration = mp.getDuration();
+            mp.start();
+            Thread.sleep(50000);
+        }catch (Exception e){}
+        isPlaying = mp.isPlaying();
+        currentPosition = mp.getCurrentPosition();
+        //updateDuration = mp.getDuration();
+        Log.v(TAG, "seekToEnd currentPosition= " + currentPosition + " isPlaying = " + isPlaying);
+        mp.stop();
+        mp.release();   
+        //Log.v(TAG, "duration = " + duration);
+        //Log.v(TAG, "Update duration = " + updateDuration);
+        if (currentPosition > duration || isPlaying)
+            return false;
+        else
+            return true;        
+    }
+
+    public static boolean seektoBeforeStart(String filePath){
+        Log.v(TAG, "seektoBeforeStart - " + filePath);
+        //This test is only for the short media file
+        int duration = 0;
+        int currentPosition = 0;
+
+        MediaPlayer mp = new MediaPlayer();
+        try{
+            mp.setDataSource(filePath);
+            mp.prepare();
+            duration = mp.getDuration();
+            mp.seekTo(duration - 10000);
+            mp.start();
+            currentPosition=mp.getCurrentPosition();
+            mp.stop();
+            mp.release();
+        }catch (Exception e){}
+        if (currentPosition < duration/2)
+            return false;
+        else
+            return true;        
+    }
+
+    public static boolean mediaRecorderRecord(String filePath){
+        Log.v(TAG, "SoundRecording - " + filePath);
+        //This test is only for the short media file
+        int duration = 0;
+        try{
+            MediaRecorder mRecorder = new MediaRecorder();
+            mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
+            mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
+            mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
+            mRecorder.setOutputFile(filePath);
+            mRecorder.prepare();
+            mRecorder.start();
+            Thread.sleep(500);
+            mRecorder.stop();
+            Log.v(TAG, "sound recorded");
+            mRecorder.release();
+        }catch (Exception e){
+            Log.v(TAG, e.toString());
+        }  
+
+        //Verify the recorded file
+        MediaPlayer mp = new MediaPlayer();
+        try{
+            mp.setDataSource(filePath);
+            mp.prepare();
+            duration = mp.getDuration();
+            Log.v(TAG,"Duration " + duration);
+            mp.release();
+        }catch (Exception e){}
+        //Check the record media file length is greate than zero
+        if (duration > 0)
+            return true;
+        else
+            return false;
+
+    }
+
+    //Test for mediaMeta Data Thumbnail
+    public static boolean getThumbnail(String filePath, String goldenPath){
+        Log.v(TAG, "getThumbnail - " + filePath);
+
+        int goldenHeight = 0;
+        int goldenWidth = 0;
+        int outputWidth = 0;
+        int outputHeight = 0;
+
+        //This test is only for the short media file
+        try{
+            BitmapFactory mBitmapFactory = new BitmapFactory();
+
+            MediaMetadataRetriever mMediaMetadataRetriever = new MediaMetadataRetriever();
+            try {
+                mMediaMetadataRetriever.setDataSource(filePath);
+            } catch(Exception e) {
+                e.printStackTrace();
+                return false;
+            }
+            Bitmap outThumbnail = mMediaMetadataRetriever.captureFrame();
+
+            //Verify the thumbnail 
+            Bitmap goldenBitmap = mBitmapFactory.decodeFile(goldenPath);
+
+            outputWidth = outThumbnail.getWidth();
+            outputHeight = outThumbnail.getHeight();
+            goldenHeight = goldenBitmap.getHeight();
+            goldenWidth = goldenBitmap.getWidth();
+
+            //check the image dimension
+            if ((outputWidth != goldenWidth) || (outputHeight != goldenHeight))
+                return false;
+
+            //Check one line of pixel
+            int x = goldenHeight/2;
+            for (int j=0; j<goldenWidth; j++){
+                if (goldenBitmap.getPixel(x, j) != outThumbnail.getPixel(x, j)){
+                    Log.v(TAG, "pixel = " + goldenBitmap.getPixel(x, j));
+                    return false;    
+                }
+            }
+        }catch (Exception e){}
+        return true;
+    }
+
+    //Load midi file from resources
+    public static boolean resourcesPlayback(AssetFileDescriptor afd, int expectedDuration){
+        int duration = 0;
+        try{
+            MediaPlayer mp = new MediaPlayer();
+            mp.setDataSource(afd.getFileDescriptor(),afd.getStartOffset(), afd.getLength());
+            mp.prepare();
+            mp.start();
+            duration = mp.getDuration();
+            Thread.sleep(5000);
+            mp.release();
+        }catch (Exception e){
+            Log.v(TAG,e.getMessage());
+        }
+        if (duration > expectedDuration)
+            return true;
+        else
+            return false;
+    }
+
+    public static boolean prepareAsyncReset(String filePath){    
+        //preparesAsync 
+        try{
+            MediaPlayer mp = new MediaPlayer();
+            mp.setDataSource(filePath);
+            mp.prepareAsync();
+            mp.reset();
+            mp.release();
+        }catch (Exception e){
+            Log.v(TAG,e.getMessage());
+            return false;
+        }
+        return true;
+    }
+
+
+    public static boolean isLooping(String filePath) {        
+        MediaPlayer mp = null;
+        
+        try {
+            mp = new MediaPlayer();
+            if (mp.isLooping()) {
+                Log.v(TAG, "MediaPlayer.isLooping() returned true after ctor");
+                return false;
+            }
+            mp.setDataSource(filePath);
+            mp.prepare();
+
+            mp.setLooping(true);
+            if (!mp.isLooping()) {
+                Log.v(TAG, "MediaPlayer.isLooping() returned false after setLooping(true)");
+                return false;
+            }
+            
+            mp.setLooping(false);
+            if (mp.isLooping()) {
+                Log.v(TAG, "MediaPlayer.isLooping() returned true after setLooping(false)");
+                return false;
+            }
+        }catch (Exception e){
+            Log.v(TAG, "Exception : " + e.toString());
+            return false;
+        } finally {
+            if (mp != null)
+                mp.release();
+        }
+
+        return true;
+    }
+
+    public static boolean isLoopingAfterReset(String filePath) {
+        MediaPlayer mp = null;
+        try {
+            mp = new MediaPlayer();
+            mp.setDataSource(filePath);
+            mp.prepare();
+
+            mp.setLooping(true);
+            mp.reset();
+            if (mp.isLooping()) {
+                Log.v(TAG, "MediaPlayer.isLooping() returned true after reset()");
+                return false;
+            }
+        }catch (Exception e){
+            Log.v(TAG, "Exception : " + e.toString());
+            return false;
+        } finally {
+            if (mp != null)
+                mp.release();
+        }
+
+        return true;
+    }
+}
+
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaAudioTrackTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaAudioTrackTest.java
new file mode 100644
index 0000000..24edb65
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaAudioTrackTest.java
@@ -0,0 +1,897 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+package com.android.mediaframeworktest.functional;
+
+import com.android.mediaframeworktest.MediaFrameworkTest;
+import com.android.mediaframeworktest.MediaNames;
+
+import android.media.AudioFormat;
+import android.media.AudioManager;
+import android.media.AudioTrack;
+import android.content.Context;
+import android.test.ActivityInstrumentationTestCase2;
+import android.util.Log;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.suitebuilder.annotation.Suppress;
+
+/**
+ * Junit / Instrumentation test case for the media AudioTrack api
+ 
+ */  
+public class MediaAudioTrackTest extends ActivityInstrumentationTestCase2<MediaFrameworkTest> {    
+    private String TAG = "MediaAudioTrackTest";
+   
+    public MediaAudioTrackTest() {
+        super("com.android.mediaframeworktest", MediaFrameworkTest.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+      super.setUp();
+    }
+    
+    @Override 
+    protected void tearDown() throws Exception {     
+        super.tearDown();              
+    }
+    
+    private static void assumeTrue(String message, boolean cond) {
+        assertTrue("(assume)"+message, cond);
+    }
+    
+    private void log(String testName, String message) {
+        Log.v(TAG, "["+testName+"] "+message);
+    }
+    
+    private void loge(String testName, String message) {
+        Log.e(TAG, "["+testName+"] "+message);
+    }
+    
+    //-----------------------------------------------------------------
+    // private class to hold test reslts
+    public class TestResults {
+        public boolean mResult = false;
+        public String  mResultLog = "";
+        public TestResults(boolean b, String s) { mResult = b; mResultLog = s; }
+    }
+    
+    //-----------------------------------------------------------------
+    // generic test methods
+    public TestResults constructorTestMultiSampleRate(
+                        // parameters tested by this method
+                        int _inTest_streamType, int _inTest_mode, 
+                        int _inTest_config, int _inTest_format,
+                        // parameter-dependent expected results
+                        int _expected_stateForMode) {
+        
+        int[] testSampleRates = {8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000};
+        String failedRates = "Failure for rate(s): ";
+        boolean localRes, finalRes = true;
+        
+        for (int i = 0 ; i < testSampleRates.length ; i++) {
+            //Log.v("MediaAudioTrackTest", "[ constructorTestMultiSampleRate ] testing "+ testSampleRates[i]);
+            AudioTrack track = null;
+            try {
+                track = new AudioTrack(
+                        _inTest_streamType, 
+                        testSampleRates[i], 
+                        _inTest_config, 
+                        _inTest_format,
+                        AudioTrack.getMinBufferSize(testSampleRates[i], 
+                                _inTest_config, _inTest_format), 
+                        _inTest_mode);
+            } catch(IllegalArgumentException iae) {
+                Log.e("MediaAudioTrackTest", "[ constructorTestMultiSampleRate ] exception at SR "
+                        + testSampleRates[i]+": \n" + iae);
+                localRes = false;
+            }
+            if (track != null) {
+                localRes = (track.getState() == _expected_stateForMode);
+                track.release();
+            }
+            else {
+                localRes = false;
+            }
+            
+            if (!localRes) {
+                //log the error for the test runner
+                failedRates += Integer.toString(testSampleRates[i]) + "Hz ";
+                //log the error for logcat
+                log("constructorTestMultiSampleRate", "failed to construct "
+                        +"AudioTrack(streamType="+_inTest_streamType 
+                        +", sampleRateInHz=" + testSampleRates[i]
+                        +", channelConfig=" + _inTest_config
+                        +", audioFormat=" + _inTest_format  
+                        +", bufferSizeInBytes=" + AudioTrack.getMinBufferSize(testSampleRates[i], 
+                                _inTest_config, AudioFormat.ENCODING_PCM_16BIT)
+                        +", mode="+ _inTest_mode );
+                //mark test as failed
+                finalRes = false;
+            }
+        }
+        return new TestResults(finalRes, failedRates);
+    }
+    
+    //-----------------------------------------------------------------
+    // AUDIOTRACK TESTS:
+    //----------------------------------
+    
+    //-----------------------------------------------------------------
+    //      AudioTrack constructor and AudioTrack.getMinBufferSize(...) for 16bit PCM
+    //----------------------------------
+       
+    //Test case 1: constructor for streaming AudioTrack, mono, 16bit at misc valid sample rates
+    @LargeTest
+    public void testConstructorMono16MusicStream() throws Exception {
+        
+        TestResults res = constructorTestMultiSampleRate(
+                AudioManager.STREAM_MUSIC, AudioTrack.MODE_STREAM, 
+                    AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT,
+                AudioTrack.STATE_INITIALIZED);
+
+        assertTrue("testConstructorMono16MusicStream: " + res.mResultLog, res.mResult);
+    }
+    
+    
+    //Test case 2: constructor for streaming AudioTrack, stereo, 16bit at misc valid sample rates
+    @LargeTest
+    public void testConstructorStereo16MusicStream() throws Exception {
+        
+        TestResults res = constructorTestMultiSampleRate(
+                AudioManager.STREAM_MUSIC, AudioTrack.MODE_STREAM, 
+                    AudioFormat.CHANNEL_CONFIGURATION_STEREO, AudioFormat.ENCODING_PCM_16BIT,
+                AudioTrack.STATE_INITIALIZED);
+
+        assertTrue("testConstructorStereo16MusicStream: " + res.mResultLog, res.mResult);
+    }
+    
+    
+    //Test case 3: constructor for static AudioTrack, mono, 16bit at misc valid sample rates
+    @LargeTest
+    public void testConstructorMono16MusicStatic() throws Exception {
+        
+        TestResults res = constructorTestMultiSampleRate(
+                AudioManager.STREAM_MUSIC, AudioTrack.MODE_STATIC, 
+                    AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT,
+                AudioTrack.STATE_NO_STATIC_DATA);
+
+        assertTrue("testConstructorMono16MusicStatic: " + res.mResultLog, res.mResult);
+    }
+    
+    
+    //Test case 4: constructor for static AudioTrack, stereo, 16bit at misc valid sample rates
+    @LargeTest
+    public void testConstructorStereo16MusicStatic() throws Exception {
+        
+        TestResults res = constructorTestMultiSampleRate(
+                AudioManager.STREAM_MUSIC, AudioTrack.MODE_STATIC, 
+                    AudioFormat.CHANNEL_CONFIGURATION_STEREO, AudioFormat.ENCODING_PCM_16BIT,
+                AudioTrack.STATE_NO_STATIC_DATA);
+
+        assertTrue("testConstructorStereo16MusicStatic: " + res.mResultLog, res.mResult);
+    }
+    
+    
+    //-----------------------------------------------------------------
+    //      AudioTrack constructor and AudioTrack.getMinBufferSize(...) for 8bit PCM
+    //----------------------------------
+       
+    //Test case 1: constructor for streaming AudioTrack, mono, 8bit at misc valid sample rates
+    @LargeTest
+    public void testConstructorMono8MusicStream() throws Exception {
+        
+        TestResults res = constructorTestMultiSampleRate(
+                AudioManager.STREAM_MUSIC, AudioTrack.MODE_STREAM, 
+                    AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_8BIT,
+                AudioTrack.STATE_INITIALIZED);
+
+        assertTrue("testConstructorMono8MusicStream: " + res.mResultLog, res.mResult);
+    }
+    
+    //Test case 2: constructor for streaming AudioTrack, stereo, 8bit at misc valid sample rates
+    @LargeTest
+    public void testConstructorStereo8MusicStream() throws Exception {
+        
+        TestResults res = constructorTestMultiSampleRate(
+                AudioManager.STREAM_MUSIC, AudioTrack.MODE_STREAM, 
+                    AudioFormat.CHANNEL_CONFIGURATION_STEREO, AudioFormat.ENCODING_PCM_8BIT,
+                AudioTrack.STATE_INITIALIZED);
+
+        assertTrue("testConstructorStereo8MusicStream: " + res.mResultLog, res.mResult);
+    }
+    
+    //Test case 3: constructor for static AudioTrack, mono, 8bit at misc valid sample rates
+    @LargeTest
+    public void testConstructorMono8MusicStatic() throws Exception {
+        
+        TestResults res = constructorTestMultiSampleRate(
+                AudioManager.STREAM_MUSIC, AudioTrack.MODE_STATIC, 
+                    AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_8BIT,
+                AudioTrack.STATE_NO_STATIC_DATA);
+
+        assertTrue("testConstructorMono8MusicStatic: " + res.mResultLog, res.mResult);
+    }
+    
+    //Test case 4: constructor for static AudioTrack, stereo, 8bit at misc valid sample rates
+    @LargeTest
+    public void testConstructorStereo8MusicStatic() throws Exception {
+        
+        TestResults res = constructorTestMultiSampleRate(
+                AudioManager.STREAM_MUSIC, AudioTrack.MODE_STATIC, 
+                    AudioFormat.CHANNEL_CONFIGURATION_STEREO, AudioFormat.ENCODING_PCM_8BIT,
+                AudioTrack.STATE_NO_STATIC_DATA);
+
+        assertTrue("testConstructorStereo8MusicStatic: " + res.mResultLog, res.mResult);
+    }
+    
+    
+    //-----------------------------------------------------------------
+    //      AudioTrack constructor for all stream types
+    //----------------------------------
+        
+    //Test case 1: constructor for all stream types
+    @LargeTest
+    public void testConstructorStreamType() throws Exception {
+        // constants for test
+        final int TYPE_TEST_SR = 22050;
+        final int TYPE_TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_STEREO;
+        final int TYPE_TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
+        final int TYPE_TEST_MODE = AudioTrack.MODE_STREAM;
+        final int[] STREAM_TYPES = { AudioManager.STREAM_ALARM, AudioManager.STREAM_BLUETOOTH_SCO, 
+                AudioManager.STREAM_MUSIC, AudioManager.STREAM_NOTIFICATION,
+                AudioManager.STREAM_RING, AudioManager.STREAM_SYSTEM, 
+                AudioManager.STREAM_VOICE_CALL };
+        final String[] STREAM_NAMES = { "STREAM_ALARM", "STREAM_BLUETOOTH_SCO", "STREAM_MUSIC",
+                "STREAM_NOTIFICATION", "STREAM_RING", "STREAM_SYSTEM", "STREAM_VOICE_CALL" };
+        
+        boolean localTestRes = true;
+        AudioTrack track = null;
+        // test: loop constructor on all stream types
+        for (int i = 0 ; i < STREAM_TYPES.length ; i++)
+        {
+            try {
+            //-------- initialization --------------
+                track = new AudioTrack(STREAM_TYPES[i], 
+                        TYPE_TEST_SR, TYPE_TEST_CONF, TYPE_TEST_FORMAT,
+                        AudioTrack.getMinBufferSize(TYPE_TEST_SR, TYPE_TEST_CONF, TYPE_TEST_FORMAT), 
+                        TYPE_TEST_MODE);
+            } catch (IllegalArgumentException iae) {
+                loge("testConstructorStreamType", "exception for stream type "
+                        + STREAM_NAMES[i] + ": "+ iae);
+                localTestRes = false;
+            }
+            //--------  test   --------------
+            if (track != null) {
+                if (track.getState() != AudioTrack.STATE_INITIALIZED) {
+                    localTestRes = false;
+                    Log.e("MediaAudioTrackTest", 
+                            "[ testConstructorStreamType ] failed for stream type "+STREAM_NAMES[i]);
+                }
+            //--------  tear down  --------------
+                track.release();
+            }
+            else {
+                localTestRes = false;
+            }
+        }
+
+        assertTrue("testConstructorStreamType", localTestRes);
+    }
+    
+    
+    //-----------------------------------------------------------------
+    //      Playback head position
+    //----------------------------------
+  
+    //Test case 1: getPlaybackHeadPosition() at 0 after initialization
+    @LargeTest
+    public void testPlaybackHeadPositionAfterInit() throws Exception {
+        // constants for test
+        final String TEST_NAME = "testPlaybackHeadPositionAfterInit";
+        final int TEST_SR = 22050;
+        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_STEREO;
+        final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
+        final int TEST_MODE = AudioTrack.MODE_STREAM;
+        final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
+        
+        //-------- initialization --------------
+        AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 
+                AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT), TEST_MODE);
+        //--------    test        --------------
+        assumeTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED);
+        assertTrue(TEST_NAME, track.getPlaybackHeadPosition() == 0);
+        //-------- tear down      --------------
+        track.release();
+    }
+    
+    //Test case 2: getPlaybackHeadPosition() increases after play()
+    @LargeTest
+    public void testPlaybackHeadPositionIncrease() throws Exception {
+        // constants for test
+        final String TEST_NAME = "testPlaybackHeadPositionIncrease";
+        final int TEST_SR = 22050;
+        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_STEREO;
+        final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
+        final int TEST_MODE = AudioTrack.MODE_STREAM;
+        final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
+        
+        //-------- initialization --------------
+        int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT);
+        AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 
+                minBuffSize, TEST_MODE);
+        byte data[] = new byte[minBuffSize/2];
+        //--------    test        --------------
+        assumeTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED);
+        track.write(data, 0, data.length);
+        track.write(data, 0, data.length);
+        track.play();
+        Thread.sleep(100);
+        log(TEST_NAME, "position ="+ track.getPlaybackHeadPosition());
+        assertTrue(TEST_NAME, track.getPlaybackHeadPosition() > 0);
+        //-------- tear down      --------------
+        track.release();
+    }
+    
+    //Test case 3: getPlaybackHeadPosition() is 0 after flush();
+    @LargeTest
+    public void testPlaybackHeadPositionAfterFlush() throws Exception {
+        // constants for test
+        final String TEST_NAME = "testPlaybackHeadPositionAfterFlush";
+        final int TEST_SR = 22050;
+        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_STEREO;
+        final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
+        final int TEST_MODE = AudioTrack.MODE_STREAM;
+        final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
+        
+        //-------- initialization --------------
+        int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT);
+        AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 
+                minBuffSize, TEST_MODE);
+        byte data[] = new byte[minBuffSize/2];
+        //--------    test        --------------
+        assumeTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED);
+        track.write(data, 0, data.length);
+        track.write(data, 0, data.length);
+        track.play();
+        Thread.sleep(100);
+        track.stop();
+        track.flush();
+        log(TEST_NAME, "position ="+ track.getPlaybackHeadPosition());
+        assertTrue(TEST_NAME, track.getPlaybackHeadPosition() == 0);
+        //-------- tear down      --------------
+        track.release();
+    }
+    
+    //Test case 3: getPlaybackHeadPosition() is 0 after stop();
+    @LargeTest
+    public void testPlaybackHeadPositionAfterStop() throws Exception {
+        // constants for test
+        final String TEST_NAME = "testPlaybackHeadPositionAfterStop";
+        final int TEST_SR = 22050;
+        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_STEREO;
+        final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
+        final int TEST_MODE = AudioTrack.MODE_STREAM;
+        final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
+        
+        //-------- initialization --------------
+        int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT);
+        AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 
+                minBuffSize, TEST_MODE);
+        byte data[] = new byte[minBuffSize/2];
+        //--------    test        --------------
+        assumeTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED);
+        track.write(data, 0, data.length);
+        track.write(data, 0, data.length);
+        track.play();
+        Thread.sleep(100);
+        track.stop();
+        Thread.sleep(100); // TODO: what is a sensible value?
+        int pos = track.getPlaybackHeadPosition();
+        log(TEST_NAME, "position ="+ pos);
+        assertTrue(TEST_NAME, pos == 0);
+        //-------- tear down      --------------
+        track.release();
+    }
+    
+    //Test case 4: getPlaybackHeadPosition() is > 0 after play(); pause();
+    @LargeTest
+    public void testPlaybackHeadPositionAfterPause() throws Exception {
+        // constants for test
+        final String TEST_NAME = "testPlaybackHeadPositionAfterPause";
+        final int TEST_SR = 22050;
+        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_STEREO;
+        final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
+        final int TEST_MODE = AudioTrack.MODE_STREAM;
+        final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
+        
+        //-------- initialization --------------
+        int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT);
+        AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 
+                minBuffSize, TEST_MODE);
+        byte data[] = new byte[minBuffSize/2];
+        //--------    test        --------------
+        assumeTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED);
+        track.write(data, 0, data.length);
+        track.write(data, 0, data.length);
+        track.play();
+        Thread.sleep(100);
+        track.pause();
+        int pos = track.getPlaybackHeadPosition();
+        log(TEST_NAME, "position ="+ pos);
+        assertTrue(TEST_NAME, pos > 0);
+        //-------- tear down      --------------
+        track.release();
+    }
+    
+    
+    //-----------------------------------------------------------------
+    //      Playback properties
+    //----------------------------------
+    
+    //Test case 1: setStereoVolume() with max volume returns SUCCESS
+    @LargeTest
+    public void testSetStereoVolumeMax() throws Exception {
+        // constants for test
+        final String TEST_NAME = "testSetStereoVolumeMax";
+        final int TEST_SR = 22050;
+        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_STEREO;
+        final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
+        final int TEST_MODE = AudioTrack.MODE_STREAM;
+        final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
+        
+        //-------- initialization --------------
+        int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT);
+        AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 
+                minBuffSize, TEST_MODE);
+        byte data[] = new byte[minBuffSize/2];
+        //--------    test        --------------
+        track.write(data, 0, data.length);
+        track.write(data, 0, data.length);
+        track.play();
+        float maxVol = AudioTrack.getMaxVolume();
+        assertTrue(TEST_NAME, track.setStereoVolume(maxVol, maxVol) == AudioTrack.SUCCESS);
+        //-------- tear down      --------------
+        track.release();
+    }
+    
+    //Test case 2: setStereoVolume() with min volume returns SUCCESS
+    @LargeTest
+    public void testSetStereoVolumeMin() throws Exception {
+        // constants for test
+        final String TEST_NAME = "testSetStereoVolumeMin";
+        final int TEST_SR = 22050;
+        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_STEREO;
+        final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
+        final int TEST_MODE = AudioTrack.MODE_STREAM;
+        final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
+        
+        //-------- initialization --------------
+        int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT);
+        AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 
+                minBuffSize, TEST_MODE);
+        byte data[] = new byte[minBuffSize/2];
+        //--------    test        --------------
+        track.write(data, 0, data.length);
+        track.write(data, 0, data.length);
+        track.play();
+        float minVol = AudioTrack.getMinVolume();
+        assertTrue(TEST_NAME, track.setStereoVolume(minVol, minVol) == AudioTrack.SUCCESS);
+        //-------- tear down      --------------
+        track.release();
+    }
+    
+    //Test case 3: setStereoVolume() with mid volume returns SUCCESS
+    @LargeTest
+    public void testSetStereoVolumeMid() throws Exception {
+        // constants for test
+        final String TEST_NAME = "testSetStereoVolumeMid";
+        final int TEST_SR = 22050;
+        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_STEREO;
+        final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
+        final int TEST_MODE = AudioTrack.MODE_STREAM;
+        final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
+        
+        //-------- initialization --------------
+        int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT);
+        AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 
+                minBuffSize, TEST_MODE);
+        byte data[] = new byte[minBuffSize/2];
+        //--------    test        --------------
+        track.write(data, 0, data.length);
+        track.write(data, 0, data.length);
+        track.play();
+        float midVol = (AudioTrack.getMaxVolume() - AudioTrack.getMinVolume()) / 2;
+        assertTrue(TEST_NAME, track.setStereoVolume(midVol, midVol) == AudioTrack.SUCCESS);
+        //-------- tear down      --------------
+        track.release();
+    }
+    
+    //Test case 4: setPlaybackRate() with half the content rate returns SUCCESS
+    @LargeTest
+    public void testSetPlaybackRate() throws Exception {
+        // constants for test
+        final String TEST_NAME = "testSetPlaybackRate";
+        final int TEST_SR = 22050;
+        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_STEREO;
+        final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
+        final int TEST_MODE = AudioTrack.MODE_STREAM;
+        final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
+        
+        //-------- initialization --------------
+        int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT);
+        AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 
+                minBuffSize, TEST_MODE);
+        byte data[] = new byte[minBuffSize/2];
+        //--------    test        --------------
+        track.write(data, 0, data.length);
+        track.write(data, 0, data.length);
+        assumeTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED);
+        track.play();
+        assertTrue(TEST_NAME, track.setPlaybackRate((int)(TEST_SR/2)) == AudioTrack.SUCCESS);
+        //-------- tear down      --------------
+        track.release();
+    }
+    
+    //Test case 5: setPlaybackRate(0) returns bad value error
+    @LargeTest
+    public void testSetPlaybackRateZero() throws Exception {
+        // constants for test
+        final String TEST_NAME = "testSetPlaybackRateZero";
+        final int TEST_SR = 22050;
+        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_STEREO;
+        final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
+        final int TEST_MODE = AudioTrack.MODE_STREAM;
+        final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
+        
+        //-------- initialization --------------
+        int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT);
+        AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 
+                minBuffSize, TEST_MODE);
+        //--------    test        --------------
+        assumeTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED);
+        assertTrue(TEST_NAME, track.setPlaybackRate(0) == AudioTrack.ERROR_BAD_VALUE);
+        //-------- tear down      --------------
+        track.release();
+    }
+    
+    //Test case 6: setPlaybackRate() accepts values twice the output sample rate
+    @LargeTest
+    public void testSetPlaybackRateTwiceOutputSR() throws Exception {
+        // constants for test
+        final String TEST_NAME = "testSetPlaybackRateTwiceOutputSR";
+        final int TEST_SR = 22050;
+        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_STEREO;
+        final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
+        final int TEST_MODE = AudioTrack.MODE_STREAM;
+        final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
+        
+        //-------- initialization --------------
+        int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT);
+        AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 
+                minBuffSize, TEST_MODE);
+        byte data[] = new byte[minBuffSize/2];
+        int outputSR = AudioTrack.getNativeOutputSampleRate(TEST_STREAM_TYPE);
+        //--------    test        --------------
+        track.write(data, 0, data.length);
+        track.write(data, 0, data.length);
+        assumeTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED);
+        track.play();
+        assertTrue(TEST_NAME, track.setPlaybackRate(2*outputSR) == AudioTrack.SUCCESS);
+        //-------- tear down      --------------
+        track.release();
+    }
+/*    
+    //Test case 7: setPlaybackRate() clips values over twice the output sample rate
+    @LargeTest
+    public void testSetPlaybackRateClip() throws Exception {
+        // constants for test
+        final String TEST_NAME = "testSetPlaybackRateClip";
+        final int TEST_SR = 22050;
+        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_STEREO;
+        final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
+        final int TEST_MODE = AudioTrack.MODE_STREAM;
+        final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
+        
+        //-------- initialization --------------
+        int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT);
+        AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 
+                minBuffSize, TEST_MODE);
+        byte data[] = new byte[minBuffSize/2];
+        int outputSR = AudioTrack.getNativeOutputSampleRate(TEST_STREAM_TYPE);
+        //--------    test        --------------
+        track.write(data, 0, data.length);
+        track.write(data, 0, data.length);
+        assumeTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED);
+        track.play();
+        track.setPlaybackRate(3*outputSR);
+        assertTrue(TEST_NAME, track.getSampleRate() == 2*outputSR);
+        //-------- tear down      --------------
+        track.release();
+    }
+*/    
+    //Test case 8: setPlaybackRate() invalid operation if track not initialized
+    @LargeTest
+    public void testSetPlaybackRateUninit() throws Exception {
+        // constants for test
+        final String TEST_NAME = "testSetPlaybackRateUninit";
+        final int TEST_SR = 22050;
+        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO;
+        final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
+        final int TEST_MODE = AudioTrack.MODE_STATIC;
+        final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
+        
+        //-------- initialization --------------
+        int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT);
+        AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 
+                minBuffSize, TEST_MODE);
+        //--------    test        --------------
+        assumeTrue(TEST_NAME, track.getState() == AudioTrack.STATE_NO_STATIC_DATA);
+        assertTrue(TEST_NAME, track.setPlaybackRate(TEST_SR/2) == AudioTrack.ERROR_INVALID_OPERATION);
+        //-------- tear down      --------------
+        track.release();
+    }
+    
+    //-----------------------------------------------------------------
+    //      Playback progress
+    //----------------------------------
+    
+    //Test case 1: setPlaybackHeadPosition() on playing track
+    @LargeTest
+    public void testSetPlaybackHeadPositionPlaying() throws Exception {
+        // constants for test
+        final String TEST_NAME = "testSetPlaybackHeadPositionPlaying";
+        final int TEST_SR = 22050;
+        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO;
+        final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
+        final int TEST_MODE = AudioTrack.MODE_STREAM;
+        final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
+        
+        //-------- initialization --------------
+        int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT);
+        AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 
+                2*minBuffSize, TEST_MODE);
+        byte data[] = new byte[minBuffSize];
+        //--------    test        --------------
+        assumeTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED);
+        track.write(data, 0, data.length);
+        track.write(data, 0, data.length);
+        track.play();
+        assertTrue(TEST_NAME,
+                track.setPlaybackHeadPosition(10) == AudioTrack.ERROR_INVALID_OPERATION);
+        //-------- tear down      --------------
+        track.release();
+    }
+    
+    //Test case 2: setPlaybackHeadPosition() on stopped track
+    @LargeTest
+    public void testSetPlaybackHeadPositionStopped() throws Exception {
+        // constants for test
+        final String TEST_NAME = "testSetPlaybackHeadPositionStopped";
+        final int TEST_SR = 22050;
+        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO;
+        final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
+        final int TEST_MODE = AudioTrack.MODE_STREAM;
+        final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
+        
+        //-------- initialization --------------
+        int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT);
+        AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 
+                2*minBuffSize, TEST_MODE);
+        byte data[] = new byte[minBuffSize];
+        //--------    test        --------------
+        assumeTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED);
+        track.write(data, 0, data.length);
+        track.write(data, 0, data.length);
+        track.play();
+        track.stop();
+        assumeTrue(TEST_NAME, track.getPlayState() == AudioTrack.PLAYSTATE_STOPPED);
+        assertTrue(TEST_NAME, track.setPlaybackHeadPosition(10) == AudioTrack.SUCCESS);
+        //-------- tear down      --------------
+        track.release();
+    }
+    
+    //Test case 3: setPlaybackHeadPosition() on paused track
+    @LargeTest
+    public void testSetPlaybackHeadPositionPaused() throws Exception {
+        // constants for test
+        final String TEST_NAME = "testSetPlaybackHeadPositionPaused";
+        final int TEST_SR = 22050;
+        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO;
+        final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
+        final int TEST_MODE = AudioTrack.MODE_STREAM;
+        final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
+        
+        //-------- initialization --------------
+        int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT);
+        AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 
+                2*minBuffSize, TEST_MODE);
+        byte data[] = new byte[minBuffSize];
+        //--------    test        --------------
+        assumeTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED);
+        track.write(data, 0, data.length);
+        track.write(data, 0, data.length);
+        track.play();
+        track.pause();
+        assumeTrue(TEST_NAME, track.getPlayState() == AudioTrack.PLAYSTATE_PAUSED);
+        assertTrue(TEST_NAME, track.setPlaybackHeadPosition(10) == AudioTrack.SUCCESS);
+        //-------- tear down      --------------
+        track.release();
+    }
+    
+    //Test case 4: setPlaybackHeadPosition() beyond what has been written
+    @LargeTest
+    public void testSetPlaybackHeadPositionTooFar() throws Exception {
+        // constants for test
+        final String TEST_NAME = "testSetPlaybackHeadPositionTooFar";
+        final int TEST_SR = 22050;
+        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO;
+        final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
+        final int TEST_MODE = AudioTrack.MODE_STREAM;
+        final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
+        
+        //-------- initialization --------------
+        int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT);
+        AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 
+                2*minBuffSize, TEST_MODE);
+        byte data[] = new byte[minBuffSize];
+        // make up a frame index that's beyond what has been written: go from buffer size to frame
+        //   count (given the audio track properties), and add 77.
+        int frameIndexTooFar = (2*minBuffSize/2) + 77;
+        //--------    test        --------------
+        assumeTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED);
+        track.write(data, 0, data.length);
+        track.write(data, 0, data.length);
+        track.play();
+        track.stop();
+        assumeTrue(TEST_NAME, track.getPlayState() == AudioTrack.PLAYSTATE_STOPPED);
+        assertTrue(TEST_NAME, track.setPlaybackHeadPosition(frameIndexTooFar) == AudioTrack.ERROR_BAD_VALUE);
+        //-------- tear down      --------------
+        track.release();
+    }
+    
+    
+    //Test case 5: setLoopPoints() fails for MODE_STREAM
+    @LargeTest
+    public void testSetLoopPointsStream() throws Exception {
+        // constants for test
+        final String TEST_NAME = "testSetLoopPointsStream";
+        final int TEST_SR = 22050;
+        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO;
+        final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
+        final int TEST_MODE = AudioTrack.MODE_STREAM;
+        final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
+        
+        //-------- initialization --------------
+        int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT);
+        AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 
+                2*minBuffSize, TEST_MODE);
+        byte data[] = new byte[minBuffSize];
+        //--------    test        --------------
+        track.write(data, 0, data.length);
+        assumeTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED);
+        assertTrue(TEST_NAME, track.setLoopPoints(2, 50, 2) == AudioTrack.ERROR_INVALID_OPERATION);
+        //-------- tear down      --------------
+        track.release();
+    }
+    
+    //Test case 6: setLoopPoints() fails start > end
+    @LargeTest
+    public void testSetLoopPointsStartAfterEnd() throws Exception {
+        // constants for test
+        final String TEST_NAME = "testSetLoopPointsStartAfterEnd";
+        final int TEST_SR = 22050;
+        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO;
+        final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
+        final int TEST_MODE = AudioTrack.MODE_STATIC;
+        final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
+        
+        //-------- initialization --------------
+        int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT);
+        AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 
+                minBuffSize, TEST_MODE);
+        byte data[] = new byte[minBuffSize];
+        //--------    test        --------------
+        track.write(data, 0, data.length);
+        assumeTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED);
+        assertTrue(TEST_NAME, track.setLoopPoints(50, 0, 2) == AudioTrack.ERROR_BAD_VALUE);
+        //-------- tear down      --------------
+        track.release();
+    }
+    
+    //Test case 6: setLoopPoints() success
+    @LargeTest
+    public void testSetLoopPointsSuccess() throws Exception {
+        // constants for test
+        final String TEST_NAME = "testSetLoopPointsSuccess";
+        final int TEST_SR = 22050;
+        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO;
+        final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
+        final int TEST_MODE = AudioTrack.MODE_STATIC;
+        final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
+        
+        //-------- initialization --------------
+        int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT);
+        AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 
+                minBuffSize, TEST_MODE);
+        byte data[] = new byte[minBuffSize];
+        //--------    test        --------------
+        track.write(data, 0, data.length);
+        assumeTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED);
+        assertTrue(TEST_NAME, track.setLoopPoints(0, 50, 2) == AudioTrack.SUCCESS);
+        //-------- tear down      --------------
+        track.release();
+    }
+    
+    //Test case 7: setLoopPoints() fails with loop length bigger than content
+    @LargeTest
+    public void testSetLoopPointsLoopTooLong() throws Exception {
+        // constants for test
+        final String TEST_NAME = "testSetLoopPointsLoopTooLong";
+        final int TEST_SR = 22050;
+        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO;
+        final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
+        final int TEST_MODE = AudioTrack.MODE_STATIC;
+        final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
+        
+        //-------- initialization --------------
+        int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT);
+        AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 
+                minBuffSize, TEST_MODE);
+        byte data[] = new byte[minBuffSize];
+        int dataSizeInFrames = minBuffSize/2;
+        //--------    test        --------------
+        assumeTrue(TEST_NAME, track.getState() == AudioTrack.STATE_NO_STATIC_DATA);
+        track.write(data, 0, data.length);
+        assumeTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED);
+        assertTrue(TEST_NAME, 
+                track.setLoopPoints(10, dataSizeInFrames+20, 2) == AudioTrack.ERROR_BAD_VALUE);
+        //-------- tear down      --------------
+        track.release();
+    }
+/*    
+    //Test case 7: setLoopPoints() fails with start beyond what can be written for the track
+    @LargeTest
+    public void testSetLoopPointsStartTooFar() throws Exception {
+        // constants for test
+        final String TEST_NAME = "testSetLoopPointsStartTooFar";
+        final int TEST_SR = 22050;
+        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO;
+        final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
+        final int TEST_MODE = AudioTrack.MODE_STATIC;
+        final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
+        
+        //-------- initialization --------------
+        int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT);
+        AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 
+                minBuffSize, TEST_MODE);
+        byte data[] = new byte[minBuffSize];
+        int dataSizeInFrames = minBuffSize/2;//16bit data
+        //--------    test        --------------
+        assumeTrue(TEST_NAME, track.getState() == AudioTrack.STATE_NO_STATIC_DATA);
+        track.write(data, 0, data.length);
+        assumeTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED);
+        assertTrue(TEST_NAME, 
+                track.setLoopPoints(dataSizeInFrames+20, dataSizeInFrames+50, 2) 
+                    == AudioTrack.ERROR_BAD_VALUE);
+        //-------- tear down      --------------
+        track.release();
+    }
+*/    
+    
+}
+
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaMetadataTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaMetadataTest.java
new file mode 100644
index 0000000..364e1af
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaMetadataTest.java
@@ -0,0 +1,255 @@
+/*
+ * 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.
+ */
+
+package com.android.mediaframeworktest.functional;
+
+import android.media.MediaMetadataRetriever;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.suitebuilder.annotation.Suppress;
+import android.util.Log;
+
+import com.android.mediaframeworktest.MediaNames;
+/**
+ * This metadata test suite test the basic functionality of the 
+ * MediaMetadataRetriever
+ * 
+ */
+public class MediaMetadataTest extends AndroidTestCase {
+    
+    private static final String TAG = "MediaMetadataTest";
+    
+    public static enum METADATA_EXPECTEDRESULT{
+        FILE_PATH,CD_TRACK, ALBUM,
+        ARTIST, AUTHOR, COMPOSER,
+        DATE, GENRE, TITLE,
+        YEAR, DURATION, NUM_TRACKS
+    }
+    
+    public static enum MP3_TEST_FILE{
+        ID3V1V2, ID3V2, ID3V1,
+        CORRUPTED_ID3V1, CORRUPTED_ID3V2_TALB, CORRUPTED_ID3V2_TCOM,
+        CORRUPTED_ID3V2_TCOM_2, CORRUPTED_ID3V2_TRCK, CORRUPTED_D3V2_TRCK_2,
+        CORRUPTED_ID3V2_TYER, CORRUPTED_ID3V2_TYER_2, CORRUPTED_ID3V2_TIT
+    }
+    
+    public static enum NON_MP3_TEST_FILE{
+         THREE3GP, AMRNB, AMRWB, M4A1, M4V, MIDI,
+         H264, OGG1, OGG2, WAV, WMA9, WMA10, WMV9, WMV7
+    }
+    
+    public static METADATA_EXPECTEDRESULT meta;
+    public static MP3_TEST_FILE mp3_test_file;
+    public static NON_MP3_TEST_FILE non_mp3_test_file;
+   
+    @MediumTest
+    public static void testID3V1V2Metadata() throws Exception {
+        validateMetatData(mp3_test_file.ID3V1V2.ordinal(), MediaNames.META_DATA_MP3);
+    }
+    
+    @MediumTest
+    public static void testID3V2Metadata() throws Exception {
+        validateMetatData(mp3_test_file.ID3V2.ordinal(), MediaNames.META_DATA_MP3);
+    }
+    
+    @MediumTest
+    public static void testID3V1Metadata() throws Exception {
+        validateMetatData(mp3_test_file.ID3V1.ordinal(), MediaNames.META_DATA_MP3);
+    }
+    
+    @MediumTest
+    public static void testCorruptedID3V1Metadata() throws Exception {
+        validateMetatData(mp3_test_file.CORRUPTED_ID3V1.ordinal(), MediaNames.META_DATA_MP3);
+    }
+
+    @MediumTest
+    public static void testCorrupted_ID3V2_TALBMetadata() throws Exception {
+        validateMetatData(mp3_test_file.CORRUPTED_ID3V2_TALB.ordinal(), MediaNames.META_DATA_MP3);
+    }
+    
+    @MediumTest
+    public static void testCorrupted_ID3V2_TCOMMetadata() throws Exception {
+        validateMetatData(mp3_test_file.CORRUPTED_ID3V2_TCOM.ordinal(), MediaNames.META_DATA_MP3);
+    }
+    
+    @MediumTest
+    public static void testCorrupted_ID3V2_TCOMM2etadata() throws Exception {
+        validateMetatData(mp3_test_file.CORRUPTED_ID3V2_TCOM_2.ordinal(), MediaNames.META_DATA_MP3);
+    }
+    
+    @MediumTest
+    public static void testCorrupted_ID3V2_TRCKMetadata() throws Exception {
+        validateMetatData(mp3_test_file.CORRUPTED_ID3V2_TRCK.ordinal(), MediaNames.META_DATA_MP3);
+    }
+    
+    @MediumTest
+    public static void testCorrupted_ID3V2_TRCK2Metadata() throws Exception {
+        validateMetatData(mp3_test_file.CORRUPTED_D3V2_TRCK_2.ordinal(), MediaNames.META_DATA_MP3);
+    }
+   
+    @MediumTest
+    public static void testCorrupted_ID3V2_TYERMetadata() throws Exception {
+        validateMetatData(mp3_test_file.CORRUPTED_ID3V2_TYER.ordinal(), MediaNames.META_DATA_MP3);
+    }
+    
+    @MediumTest
+    public static void testCorrupted_ID3V2_TYER2Metadata() throws Exception {
+        validateMetatData(mp3_test_file.CORRUPTED_ID3V2_TYER_2.ordinal(), MediaNames.META_DATA_MP3);
+    }
+    
+    @MediumTest
+    public static void testCorrupted_ID3V2_TITMetadata() throws Exception {
+        validateMetatData(mp3_test_file.CORRUPTED_ID3V2_TIT.ordinal(), MediaNames.META_DATA_MP3);
+    }
+   
+    @MediumTest
+    public static void test3gp_Metadata() throws Exception {
+        validateMetatData(non_mp3_test_file.THREE3GP.ordinal(), MediaNames.META_DATA_OTHERS);
+    }
+    
+    @MediumTest
+    public static void testAmr_Metadata() throws Exception {
+        validateMetatData(non_mp3_test_file.AMRNB.ordinal(), MediaNames.META_DATA_OTHERS);
+    }
+    
+    @MediumTest
+    public static void testAmrWb_Metadata() throws Exception {
+        validateMetatData(non_mp3_test_file.AMRWB.ordinal(), MediaNames.META_DATA_OTHERS);
+    }
+    
+    //Bug# 1440173 - skip this test case now
+    @Suppress
+    @MediumTest
+    public static void testM4A1_Metadata() throws Exception {
+        validateMetatData(non_mp3_test_file.M4A1.ordinal(), MediaNames.META_DATA_OTHERS);
+    }
+    
+    @MediumTest
+    public static void testM4v_Metadata() throws Exception {
+        validateMetatData(non_mp3_test_file.M4V.ordinal(), MediaNames.META_DATA_OTHERS);
+    }
+    
+    @MediumTest
+    public static void testH264_Metadata() throws Exception {
+        validateMetatData(non_mp3_test_file.H264.ordinal(), MediaNames.META_DATA_OTHERS);
+    }
+    //bug# 1440489
+    @Suppress
+    @MediumTest
+    public static void testOgg1_Metadata() throws Exception {
+        validateMetatData(non_mp3_test_file.OGG1.ordinal(), MediaNames.META_DATA_OTHERS);
+    }
+    
+    @Suppress
+    @MediumTest
+    public static void testOgg2_Metadata() throws Exception {
+        validateMetatData(non_mp3_test_file.OGG2.ordinal(), MediaNames.META_DATA_OTHERS);
+    }
+    
+    @Suppress
+    @MediumTest
+    public static void testMidi_Metadata() throws Exception {
+        validateMetatData(non_mp3_test_file.MIDI.ordinal(), MediaNames.META_DATA_OTHERS);
+    }
+    
+    @MediumTest
+    public static void testWav_Metadata() throws Exception {
+        validateMetatData(non_mp3_test_file.WAV.ordinal(), MediaNames.META_DATA_OTHERS);
+    }
+    
+    @MediumTest
+    public static void testWma9_Metadata() throws Exception {
+        validateMetatData(non_mp3_test_file.WMA9.ordinal(), MediaNames.META_DATA_OTHERS);
+    }
+    
+    @MediumTest
+    public static void testWma10_Metadata() throws Exception {
+        validateMetatData(non_mp3_test_file.WMA10.ordinal(), MediaNames.META_DATA_OTHERS);
+    }
+    
+    @MediumTest
+    public static void testWmv9_Metadata() throws Exception {
+        validateMetatData(non_mp3_test_file.WMV9.ordinal(), MediaNames.META_DATA_OTHERS);
+    }
+    
+    @MediumTest
+    public static void testWmv10_Metadata() throws Exception {
+        validateMetatData(non_mp3_test_file.WMV7.ordinal(), MediaNames.META_DATA_OTHERS);
+    }
+     
+    private static void validateMetatData(int fileIndex, String meta_data_file[][]) {
+        String value = null;
+        MediaMetadataRetriever retriever = new MediaMetadataRetriever();
+        retriever.setMode(MediaMetadataRetriever.MODE_GET_METADATA_ONLY);
+        try {
+            retriever.setDataSource(meta_data_file[fileIndex][0]);
+            Log.v(TAG, "filePath = "+ meta_data_file[fileIndex][0]);
+        } catch(Exception e) {
+            Log.v(TAG, "Failed: "+meta_data_file[fileIndex][0] + " " + e.toString());
+            //Set the test case failure whenever it failed to setDataSource
+            assertTrue("Failed to setDataSource ", false);
+        }
+        
+        //METADATA_KEY_CD_TRACK_NUMBER should return the TCRK value
+        value = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_CD_TRACK_NUMBER);
+        Log.v(TAG, "CD_TRACK_NUMBER : " + value);
+        assertEquals(TAG, meta_data_file[fileIndex][meta.CD_TRACK.ordinal()], value);
+       
+        value = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ALBUM);
+        Log.v(TAG, "Album : "+ value);
+        assertEquals(TAG, meta_data_file[fileIndex][meta.ALBUM.ordinal()], value); 
+        
+        value = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST);
+        Log.v(TAG, "Artist : "+ value);
+        assertEquals(TAG, meta_data_file[fileIndex][meta.ARTIST.ordinal()], value);
+        
+        value = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_AUTHOR);
+        Log.v(TAG, "Author : "+ value);
+        assertEquals(TAG, meta_data_file[fileIndex][meta.AUTHOR.ordinal()], value);
+        
+        value = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_COMPOSER);
+        Log.v(TAG, "Composer : "+ value);
+        assertEquals(TAG, meta_data_file[fileIndex][meta.COMPOSER.ordinal()], value);
+        
+        value = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DATE);
+        Log.v(TAG, "Date : "+ value);
+        assertEquals(TAG, meta_data_file[fileIndex][meta.DATE.ordinal()], value);
+        
+        value = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_GENRE);
+        Log.v(TAG, "Genre : "+ value);
+        assertEquals(TAG, meta_data_file[fileIndex][meta.GENRE.ordinal()], value);
+        
+        value = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE);
+        Log.v(TAG, "Title : "+ value);
+        assertEquals(TAG, meta_data_file[fileIndex][meta.TITLE.ordinal()], value);
+        
+        value = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_YEAR);
+        Log.v(TAG, "Year : "+ value);
+        assertEquals(TAG, meta_data_file[fileIndex][meta.YEAR.ordinal()], value);
+        
+        value = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
+        Log.v(TAG, "Expected = " + meta_data_file[fileIndex][meta.DURATION.ordinal()] + "reult = " + value);
+        assertEquals(TAG, meta_data_file[fileIndex][meta.DURATION.ordinal()], value);
+        
+        //METADATA_KEY_NUM_TRACKS should return the total number of tracks in the media
+        //include the video and audio
+        value = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_NUM_TRACKS);
+        Log.v(TAG, "Track : "+ value);
+        assertEquals(TAG,meta_data_file[fileIndex][meta.NUM_TRACKS.ordinal()], value);
+     
+        retriever.release();        
+    }
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPlayerApiTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPlayerApiTest.java
new file mode 100644
index 0000000..dd94164
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPlayerApiTest.java
@@ -0,0 +1,433 @@
+/*
+ * 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.
+ */
+
+package com.android.mediaframeworktest.functional;
+
+import com.android.mediaframeworktest.MediaFrameworkTest;
+import com.android.mediaframeworktest.MediaNames;
+
+import android.content.Context;
+import android.test.ActivityInstrumentationTestCase;
+import android.util.Log;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.suitebuilder.annotation.Suppress;
+
+/**
+ * Junit / Instrumentation test case for the media player api
+ 
+ */  
+public class MediaPlayerApiTest extends ActivityInstrumentationTestCase<MediaFrameworkTest> {    
+   private boolean duratoinWithinTolerence = false;
+   private String TAG = "MediaPlayerApiTest";
+   
+   Context mContext;
+  
+   public MediaPlayerApiTest() {
+     super("com.android.mediaframeworktest", MediaFrameworkTest.class);
+   }
+
+    protected void setUp() throws Exception {
+      super.setUp();
+   
+  }
+    
+    public boolean verifyDuration(int duration, int expectedDuration){
+      if ((duration > expectedDuration * 1.1) || (duration < expectedDuration * 0.9))
+         return false;
+      else
+        return true;
+    }   
+    
+   
+    //Audio    
+    //Wait for PV bugs for MP3 duration
+    @MediumTest
+    public void testMP3CBRGetDuration() throws Exception {
+      int duration = CodecTest.getDuration(MediaNames.MP3CBR);
+      duratoinWithinTolerence = verifyDuration(duration, MediaNames.MP3CBR_LENGTH);
+      assertTrue("MP3CBR getDuration", duratoinWithinTolerence);  
+    }
+    
+    @MediumTest
+    public void testMP3VBRGetDuration() throws Exception {
+      int duration = CodecTest.getDuration(MediaNames.MP3VBR);
+      Log.v(TAG, "getDuration");
+      duratoinWithinTolerence = verifyDuration(duration, MediaNames.MP3VBR_LENGTH);
+      assertTrue("MP3VBR getDuration", duratoinWithinTolerence);  
+    }
+
+    @MediumTest
+    public void testMIDIGetDuration() throws Exception {
+      int duration = CodecTest.getDuration(MediaNames.MIDI);  
+      duratoinWithinTolerence = verifyDuration(duration, MediaNames.MIDI_LENGTH);
+      assertTrue("MIDI getDuration", duratoinWithinTolerence);  
+    }
+    
+    @MediumTest
+    public void testWMA9GetDuration() throws Exception {
+      int duration = CodecTest.getDuration(MediaNames.WMA9); 
+      duratoinWithinTolerence = verifyDuration(duration, MediaNames.WMA9_LENGTH);
+      assertTrue("WMA9 getDuration", duratoinWithinTolerence);  
+    }
+
+    @MediumTest
+    public void testAMRGetDuration() throws Exception {
+      int duration = CodecTest.getDuration(MediaNames.AMR);  
+      duratoinWithinTolerence = verifyDuration(duration, MediaNames.AMR_LENGTH);
+      assertTrue("AMR getDuration", duratoinWithinTolerence);  
+    }
+    
+    /*
+    public void testOGGGetDuration() throws Exception {
+      int duration = CodecTest.getDuration(MediaNames.OGG);  
+      duratoinWithinTolerence = verifyDuration(duration, MediaNames.OGG_LENGTH);
+      assertTrue("OGG getDuration", duratoinWithinTolerence);  
+    }*/
+    
+    
+    //Test cases for GetCurrentPosition
+    @LargeTest
+    public void testMP3CBRGetCurrentPosition() throws Exception {
+      boolean currentPosition = CodecTest.getCurrentPosition(MediaNames.MP3CBR);       
+      assertTrue("MP3CBR GetCurrentPosition", currentPosition);  
+    }
+  
+    @LargeTest
+    public void testMP3VBRGetCurrentPosition() throws Exception {
+      boolean currentPosition = CodecTest.getCurrentPosition(MediaNames.MP3VBR);  
+      assertTrue("MP3VBR GetCurrentPosition", currentPosition);  
+    }
+  
+    @LargeTest
+    public void testMIDIGetCurrentPosition() throws Exception {
+      boolean currentPosition = CodecTest.getCurrentPosition(MediaNames.MIDI);  
+      assertTrue("MIDI GetCurrentPosition", currentPosition);  
+    }
+   
+    @LargeTest
+    public void testWMA9GetCurrentPosition() throws Exception {
+      boolean currentPosition = CodecTest.getCurrentPosition(MediaNames.WMA9);  
+      assertTrue("WMA9 GetCurrentPosition", currentPosition);  
+    }
+    
+    @LargeTest
+    public void testAMRGetCurrentPosition() throws Exception {
+      boolean currentPosition = CodecTest.getCurrentPosition(MediaNames.AMR);  
+      assertTrue("AMR GetCurrentPosition", currentPosition);  
+    }  
+    
+    /*
+    public void testOGGGetCurrentPosition() throws Exception {
+      boolean currentPosition = CodecTest.getCurrentPosition(MediaNames.OGG);  
+      assertTrue("OGG GetCurrentPosition", currentPosition);  
+     */    
+    
+    //Test cases for pause
+    @LargeTest
+    public void testMP3CBRPause() throws Exception {
+      boolean isPaused = CodecTest.pause(MediaNames.MP3CBR);       
+      assertTrue("MP3CBR Pause", isPaused);  
+    }
+  
+    @LargeTest
+    public void testMP3VBRPause() throws Exception {
+      boolean isPaused = CodecTest.pause(MediaNames.MP3VBR);  
+      assertTrue("MP3VBR Pause", isPaused);  
+    }
+    
+    @LargeTest
+    public void testMIDIPause() throws Exception {
+      boolean isPaused = CodecTest.pause(MediaNames.MIDI);  
+      assertTrue("MIDI Pause", isPaused);  
+    }
+   
+    @LargeTest
+    public void testWMA9Pause() throws Exception {
+      boolean isPaused = CodecTest.pause(MediaNames.WMA9);  
+      assertTrue("WMA9 Pause", isPaused);  
+    }
+  
+    @LargeTest
+    public void testAMRPause() throws Exception {
+      boolean isPaused = CodecTest.pause(MediaNames.AMR);  
+      assertTrue("AMR Pause", isPaused);  
+    }
+    
+    /*
+    public void testOGGPause() throws Exception {
+      boolean isPaused = CodecTest.pause(MediaNames.OGG);  
+      assertTrue("OGG Pause", isPaused);  
+    }*/
+    
+    @MediumTest
+    public void testMP3CBRPrepareStopRelease() throws Exception {
+      CodecTest.prepareStopRelease(MediaNames.MP3CBR);       
+      assertTrue("MP3CBR prepareStopRelease", true);  
+    }
+    
+    @MediumTest
+    public void testMIDIPrepareStopRelease() throws Exception {
+      CodecTest.prepareStopRelease(MediaNames.MIDI);  
+      assertTrue("MIDI prepareStopRelease", true);  
+    }
+    
+    //One test case for seek before start 
+    @MediumTest
+    public void testMP3CBRSeekBeforeStart() throws Exception {
+      boolean seekBeforePlay = CodecTest.seektoBeforeStart(MediaNames.MP3CBR);       
+      assertTrue("MP3CBR SeekBeforePlay", seekBeforePlay);  
+    }
+    
+    //Skip test - Bug# 1120249
+    /*
+    public void testMP3CBRpreparePauseRelease() throws Exception {
+      CodecTest.preparePauseRelease(MediaNames.MP3CBR);       
+      assertTrue("MP3CBR preparePauseRelease", true);  
+    }
+  
+    public void testMIDIpreparePauseRelease() throws Exception {
+      CodecTest.preparePauseRelease(MediaNames.MIDI);  
+      assertTrue("MIDI preparePauseRelease", true);  
+    }
+    */
+    
+    
+    //Test cases for setLooping 
+    @LargeTest
+    public void testMP3CBRSetLooping() throws Exception {
+      boolean isLoop = CodecTest.setLooping(MediaNames.MP3CBR);     
+      assertTrue("MP3CBR setLooping", isLoop);  
+    }
+    
+    @LargeTest
+    public void testMP3VBRSetLooping() throws Exception {
+      boolean isLoop = CodecTest.setLooping(MediaNames.MP3VBR);
+      Log.v(TAG, "setLooping");
+      assertTrue("MP3VBR setLooping", isLoop);  
+    }
+    
+    @LargeTest
+    public void testMIDISetLooping() throws Exception {
+      boolean isLoop = CodecTest.setLooping(MediaNames.MIDI);  
+      assertTrue("MIDI setLooping", isLoop);  
+    }
+    
+    @LargeTest
+    public void testWMA9SetLooping() throws Exception {
+      boolean isLoop = CodecTest.setLooping(MediaNames.WMA9);  
+      assertTrue("WMA9 setLooping", isLoop);  
+    }
+    
+    @LargeTest
+    public void testAMRSetLooping() throws Exception {
+      boolean isLoop = CodecTest.setLooping(MediaNames.AMR);  
+      assertTrue("AMR setLooping", isLoop);  
+    }
+    
+    /*
+    public void testOGGSetLooping() throws Exception {
+      boolean isLoop = CodecTest.setLooping(MediaNames.OGG);  
+      assertTrue("OGG setLooping", isLoop);  
+    } */ 
+    
+    //Test cases for seekTo
+    @LargeTest
+    public void testMP3CBRSeekTo() throws Exception {
+      boolean isLoop = CodecTest.seekTo(MediaNames.MP3CBR);     
+      assertTrue("MP3CBR seekTo", isLoop);  
+    }
+    
+    @LargeTest
+    public void testMP3VBRSeekTo() throws Exception {
+      boolean isLoop = CodecTest.seekTo(MediaNames.MP3VBR);
+      Log.v(TAG, "seekTo");
+      assertTrue("MP3VBR seekTo", isLoop);  
+    }
+    
+    @LargeTest
+    public void testMIDISeekTo() throws Exception {
+      boolean isLoop = CodecTest.seekTo(MediaNames.MIDI);  
+      assertTrue("MIDI seekTo", isLoop);  
+    }
+    
+    @LargeTest
+    public void testWMA9SeekTo() throws Exception {
+      boolean isLoop = CodecTest.seekTo(MediaNames.WMA9);  
+      assertTrue("WMA9 seekTo", isLoop);  
+    }
+    
+    @LargeTest
+    public void testAMRSeekTo() throws Exception {
+      boolean isLoop = CodecTest.seekTo(MediaNames.AMR);  
+      assertTrue("AMR seekTo", isLoop);  
+    }
+    
+    /*
+    public void testOGGSeekTo() throws Exception {
+      boolean isLoop = CodecTest.seekTo(MediaNames.OGG);  
+      assertTrue("OGG seekTo", isLoop);  
+    }*/
+    
+    
+    //Jump to the end of the files
+    @LargeTest
+    public void testMP3CBRSeekToEnd() throws Exception {
+      boolean isEnd = CodecTest.seekToEnd(MediaNames.MP3CBR);     
+      assertTrue("MP3CBR seekToEnd", isEnd);  
+    }
+    
+    @LargeTest
+    public void testMP3VBRSeekToEnd() throws Exception {
+      boolean isEnd = CodecTest.seekToEnd(MediaNames.MP3VBR);
+      Log.v(TAG, "seekTo");
+      assertTrue("MP3VBR seekToEnd", isEnd);  
+    }
+    
+    @LargeTest
+    public void testMIDISeekToEnd() throws Exception {
+      boolean isEnd = CodecTest.seekToEnd(MediaNames.MIDI);  
+      assertTrue("MIDI seekToEnd", isEnd);  
+    }
+    
+    @LargeTest
+    public void testWMA9SeekToEnd() throws Exception {
+      boolean isEnd = CodecTest.seekToEnd(MediaNames.WMA9);  
+      assertTrue("WMA9 seekToEnd", isEnd);  
+    }
+    
+    @LargeTest
+    public void testAMRSeekToEnd() throws Exception {
+      boolean isEnd = CodecTest.seekToEnd(MediaNames.AMR);  
+      assertTrue("AMR seekToEnd", isEnd);  
+    }
+    
+    /*
+    public void testOGGSeekToEnd() throws Exception {
+      boolean isEnd = CodecTest.seekToEnd(MediaNames.OGG);  
+      assertTrue("OGG seekToEnd", isEnd);  
+    }*/
+    
+    @LargeTest
+    public void testWAVSeekToEnd() throws Exception {
+      boolean isEnd = CodecTest.seekToEnd(MediaNames.WAV);  
+      assertTrue("WAV seekToEnd", isEnd);  
+    }  
+    
+    @MediumTest
+    public void testLargeVideoHeigth() throws Exception {
+      int height = 0;
+      height = CodecTest.videoHeight(MediaNames.VIDEO_LARGE_SIZE_3GP);
+      Log.v(TAG, "Video height = " +  height);
+      assertEquals("streaming video height", 240, height);           
+    }
+    
+    @MediumTest
+    public void testLargeVideoWidth() throws Exception {
+      int width = 0;
+      width = CodecTest.videoWidth(MediaNames.VIDEO_LARGE_SIZE_3GP);
+      Log.v(TAG, "Video width = " +  width);
+      assertEquals("streaming video width", 320, width);           
+    }
+    
+    @LargeTest
+    public void testVideoMP4SeekTo() throws Exception {
+      boolean isSeek = CodecTest.videoSeekTo(MediaNames.VIDEO_MP4);
+      assertTrue("Local MP4 SeekTo", isSeek);          
+    }
+    
+    @LargeTest
+    public void testVideoLong3gpSeekTo() throws Exception {
+      boolean isSeek = CodecTest.videoSeekTo(MediaNames.VIDEO_LONG_3GP);
+      assertTrue("Local 3gp SeekTo", isSeek);         
+    }
+   
+    @LargeTest
+    public void testVideoH263AACSeekTo() throws Exception {
+      boolean isSeek = CodecTest.videoSeekTo(MediaNames.VIDEO_H263_AAC);
+      assertTrue("H263AAC SeekTo", isSeek);         
+    }
+    
+    @LargeTest
+    public void testVideoH263AMRSeekTo() throws Exception {
+      boolean isSeek = CodecTest.videoSeekTo(MediaNames.VIDEO_H263_AMR);
+      assertTrue("H263AMR SeekTo", isSeek);         
+    }
+    
+    @LargeTest
+    public void testVideoH264AACSeekTo() throws Exception {
+      boolean isSeek = CodecTest.videoSeekTo(MediaNames.VIDEO_H264_AAC);
+      assertTrue("H264AAC SeekTo", isSeek);         
+    }
+    
+    @LargeTest
+    public void testVideoH264AMRSeekTo() throws Exception {
+      boolean isSeek = CodecTest.videoSeekTo(MediaNames.VIDEO_H264_AMR);
+      assertTrue("H264AMR SeekTo", isSeek);         
+    }
+    
+    @LargeTest
+    public void testVideoWMVSeekTo() throws Exception {
+      boolean isSeek = CodecTest.videoSeekTo(MediaNames.VIDEO_WMV);
+      assertTrue("WMV SeekTo", isSeek);         
+    }
+    
+    @LargeTest
+    public void testSoundRecord() throws Exception {
+      boolean isRecordered = CodecTest.mediaRecorderRecord(MediaNames.RECORDER_OUTPUT);
+      assertTrue("Recorder", isRecordered);         
+    }
+  
+    @LargeTest
+    public void testGetThumbnail() throws Exception {
+      boolean getThumbnail = CodecTest.getThumbnail(MediaNames.VIDEO_H264_AAC, MediaNames.GOLDEN_THUMBNAIL_OUTPUT);
+      assertTrue("Get Thumbnail", getThumbnail);         
+    }
+    
+    //Play a mid file which the duration is around 210 seconds
+    @LargeTest
+    public void testMidiResources() throws Exception {
+      boolean midiResources = CodecTest.resourcesPlayback(MediaFrameworkTest.midiafd,180000);
+      assertTrue("Play midi from resources", midiResources);         
+    }
+    
+    @LargeTest
+    public void testMp3Resources() throws Exception {
+      boolean mp3Resources = CodecTest.resourcesPlayback(MediaFrameworkTest.mp3afd,25000);
+      assertTrue("Play mp3 from resources", mp3Resources);         
+    }
+    
+    //Bug# 1422662
+    @Suppress
+    @MediumTest
+    public void testPrepareAsyncReset() throws Exception {
+      boolean isReset = CodecTest.prepareAsyncReset(MediaNames.STREAM_LARGE_MP3);
+      assertTrue("PrepareAsync Reset", isReset);         
+    }
+    
+    @MediumTest
+    public void testIsLooping() throws Exception {
+        boolean isLooping = CodecTest.isLooping(MediaNames.AMR);
+        assertTrue("isLooping", isLooping);
+    }
+
+    @MediumTest
+    public void testIsLoopingAfterReset() throws Exception {
+        boolean isLooping = CodecTest.isLoopingAfterReset(MediaNames.AMR);
+        assertTrue("isLooping after reset", isLooping);
+    }
+}
+
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaRecorderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaRecorderTest.java
new file mode 100644
index 0000000..65451c5
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaRecorderTest.java
@@ -0,0 +1,339 @@
+/*
+ * 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.
+ */
+
+package com.android.mediaframeworktest.functional;
+
+import com.android.mediaframeworktest.MediaFrameworkTest;
+import com.android.mediaframeworktest.MediaNames;
+
+import java.io.*;
+
+import android.content.Context;
+import android.media.MediaPlayer;
+import android.media.MediaRecorder;
+import android.test.ActivityInstrumentationTestCase;
+import android.util.Log;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+
+
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.Suppress;
+
+
+/**
+ * Junit / Instrumentation test case for the media recorder api 
+ */  
+public class MediaRecorderTest extends ActivityInstrumentationTestCase<MediaFrameworkTest> {    
+    private String TAG = "MediaRecorderTest";
+    private int mOutputDuration =0;
+    private int mOutputVideoWidth = 0;
+    private int mOutputVideoHeight= 0 ;
+    
+    private SurfaceHolder mSurfaceHolder = null;
+    private MediaRecorder mRecorder;
+    Context mContext;
+  
+    public MediaRecorderTest() {
+        super("com.android.mediaframeworktest", MediaFrameworkTest.class);
+       
+    }
+
+    protected void setUp() throws Exception {
+        super.setUp(); 
+        Log.v(TAG,"create the media recorder");
+        mRecorder = new MediaRecorder();
+    }
+ 
+    private void recordVideo(int frameRate, int width, int height, 
+            int videoFormat, int outFormat, String outFile, boolean videoOnly) {
+        Log.v(TAG,"startPreviewAndPrepareRecording");
+        try {
+            if (!videoOnly) {
+                Log.v(TAG, "setAudioSource");
+                mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
+            }
+            mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
+            mRecorder.setOutputFormat(outFormat);
+            Log.v(TAG, "output format " + outFormat);          
+            mRecorder.setOutputFile(outFile);
+            mRecorder.setVideoFrameRate(frameRate);
+            mRecorder.setVideoSize(width, height);
+            Log.v(TAG, "setEncoder");
+            mRecorder.setVideoEncoder(videoFormat);
+            if (!videoOnly) {
+                mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
+            }
+            mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
+            Log.v(TAG, "setPreview");
+            mRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
+            Log.v(TAG, "prepare");
+            mRecorder.prepare();
+            Log.v(TAG, "start");
+            mRecorder.start();
+            Thread.sleep(MediaNames.RECORDED_TIME);
+            Log.v(TAG, "stop");
+            mRecorder.stop();
+            mRecorder.release();
+        } catch (Exception e) {
+            Log.v("record video failed ", e.toString());
+            mRecorder.release();
+        }
+    }
+    
+    
+    private boolean invalidRecordSetting(int frameRate, int width, int height, 
+            int videoFormat, int outFormat, String outFile, boolean videoOnly) {
+        try {
+            if (!videoOnly) {
+                Log.v(TAG, "setAudioSource");
+                mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
+            }
+            mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
+            mRecorder.setOutputFormat(outFormat);
+            Log.v(TAG, "output format " + outFormat);          
+            mRecorder.setOutputFile(outFile);
+            mRecorder.setVideoFrameRate(frameRate);
+            mRecorder.setVideoSize(width, height);
+            Log.v(TAG, "setEncoder");
+            mRecorder.setVideoEncoder(videoFormat);
+            if (!videoOnly) {
+                mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
+            }
+            mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
+            Log.v(TAG, "setPreview");
+            mRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
+            Log.v(TAG, "prepare");
+            mRecorder.prepare();
+            Log.v(TAG, "start");
+            mRecorder.start();
+            Thread.sleep(MediaNames.RECORDED_TIME);
+            Log.v(TAG, "stop");
+            mRecorder.stop();
+            mRecorder.release();
+        } catch (Exception e) {
+            Log.v("record video failed ", e.toString());
+            mRecorder.release();
+            Log.v(TAG, "reset and release");
+            return true;
+        }
+        return false;
+    }
+    
+    
+    
+    private void getOutputVideoProperty(String outputFilePath) {
+        MediaPlayer mediaPlayer = new MediaPlayer();
+        try {
+            mediaPlayer.setDataSource(outputFilePath);
+            Log.v(TAG, "file Path = " + outputFilePath);
+            mediaPlayer.setDisplay(MediaFrameworkTest.mSurfaceView.getHolder());
+            Log.v(TAG, "before player prepare");
+            mediaPlayer.prepare();
+            Log.v(TAG, "before getduration");
+            mOutputDuration = mediaPlayer.getDuration();
+            Log.v(TAG, "get video dimension");
+            mOutputVideoHeight = mediaPlayer.getVideoHeight();
+            mOutputVideoWidth = mediaPlayer.getVideoWidth();
+            mediaPlayer.release();    
+        } catch (Exception e) {
+            Log.v(TAG, e.toString());
+            mediaPlayer.release();
+        }       
+    }
+    
+    private void removeFile(String filePath) {
+        File fileRemove = new File(filePath);
+        fileRemove.delete();     
+    }
+    
+    private boolean validateVideo(String filePath, int width, int height) {
+        boolean validVideo = false;
+        getOutputVideoProperty(filePath);
+        if (mOutputVideoWidth == width && mOutputVideoHeight == height &&
+                mOutputDuration > MediaNames.VALID_VIDEO_DURATION ) {
+            validVideo = true;
+        }
+        Log.v(TAG, "width = " + mOutputVideoWidth + " height = " + mOutputVideoHeight + " Duration = " + mOutputDuration);
+        removeFile(filePath);
+        return validVideo;
+    }
+    
+  
+    //Format: HVGA h263
+    @Suppress
+    public void testHVGAH263() throws Exception {  
+        boolean videoRecordedResult = false;
+        recordVideo(15, 480, 320, MediaRecorder.VideoEncoder.H263, 
+               MediaRecorder.OutputFormat.THREE_GPP, MediaNames.RECORDED_HVGA_H263, false);      
+        videoRecordedResult = validateVideo(MediaNames.RECORDED_HVGA_H263, 480, 320);
+        assertTrue("HVGAH263", videoRecordedResult);
+    }
+    
+    //Format: QVGA h263
+    @LargeTest
+    public void testQVGAH263() throws Exception {  
+        boolean videoRecordedResult = false;
+        recordVideo(15, 320, 240, MediaRecorder.VideoEncoder.H263, 
+               MediaRecorder.OutputFormat.THREE_GPP, MediaNames.RECORDED_QVGA_H263, false);      
+        videoRecordedResult = validateVideo(MediaNames.RECORDED_QVGA_H263, 320, 240);
+        assertTrue("QVGAH263", videoRecordedResult);
+    }
+    
+    //Format: SQVGA h263
+    @LargeTest
+    public void testSQVGAH263() throws Exception {  
+        boolean videoRecordedResult = false;
+        recordVideo(15, 240, 160, MediaRecorder.VideoEncoder.H263, 
+               MediaRecorder.OutputFormat.THREE_GPP, MediaNames.RECORDED_SQVGA_H263, false);      
+        videoRecordedResult = validateVideo(MediaNames.RECORDED_SQVGA_H263, 240, 160);
+        assertTrue("SQVGAH263", videoRecordedResult);
+    }
+    
+    //Format: QCIF h263
+    @LargeTest
+    public void testQCIFH263() throws Exception {
+        boolean videoRecordedResult = false; 
+        recordVideo(15, 176, 144, MediaRecorder.VideoEncoder.H263, 
+               MediaRecorder.OutputFormat.THREE_GPP, MediaNames.RECORDED_QCIF_H263, false);      
+        videoRecordedResult = validateVideo(MediaNames.RECORDED_QCIF_H263, 176, 144);
+        assertTrue("QCIFH263", videoRecordedResult);
+    }    
+    
+    //Format: CIF h263
+    @LargeTest
+    public void testCIFH263() throws Exception {       
+        boolean videoRecordedResult = false;
+        recordVideo(15, 352, 288, MediaRecorder.VideoEncoder.H263, 
+               MediaRecorder.OutputFormat.THREE_GPP, MediaNames.RECORDED_CIF_H263, false);      
+        videoRecordedResult = validateVideo(MediaNames.RECORDED_CIF_H263, 352, 288);
+        assertTrue("CIFH263", videoRecordedResult);
+    }
+      
+    
+   
+    @LargeTest
+    public void testVideoOnly() throws Exception {       
+        boolean videoRecordedResult = false;
+        recordVideo(15, 176, 144, MediaRecorder.VideoEncoder.H263, 
+               MediaRecorder.OutputFormat.MPEG_4, MediaNames.RECORDED_VIDEO_3GP, true);      
+        videoRecordedResult = validateVideo(MediaNames.RECORDED_VIDEO_3GP, 176, 144);
+        assertTrue("QCIFH263 Video Only", videoRecordedResult);
+    }
+    
+    @Suppress
+    public void testPortraitH263() throws Exception {       
+        boolean videoRecordedResult = false;
+        recordVideo(15, 144, 176, MediaRecorder.VideoEncoder.H263, 
+               MediaRecorder.OutputFormat.MPEG_4, MediaNames.RECORDED_VIDEO_3GP, true);      
+        videoRecordedResult = validateVideo(MediaNames.RECORDED_VIDEO_3GP, 144, 176);
+        assertTrue("PortraitH263", videoRecordedResult);
+    }
+    
+    @Suppress
+    public void testHVGAMP4() throws Exception {  
+        boolean videoRecordedResult = false;
+        recordVideo(15, 480, 320, MediaRecorder.VideoEncoder.MPEG_4_SP, 
+               MediaRecorder.OutputFormat.MPEG_4, MediaNames.RECORDED_HVGA_MP4, false);      
+        videoRecordedResult = validateVideo(MediaNames.RECORDED_HVGA_MP4, 480, 320);
+        assertTrue("HVGAMP4", videoRecordedResult);
+    }
+     
+    @LargeTest
+    public void testQVGAMP4() throws Exception {  
+        boolean videoRecordedResult = false;
+        recordVideo(15, 320, 240, MediaRecorder.VideoEncoder.MPEG_4_SP, 
+               MediaRecorder.OutputFormat.MPEG_4, MediaNames.RECORDED_QVGA_MP4, false);      
+        videoRecordedResult = validateVideo(MediaNames.RECORDED_QVGA_MP4, 320, 240);
+        assertTrue("QVGAMP4", videoRecordedResult);
+    }
+    
+    @LargeTest
+    public void testSQVGAMP4() throws Exception {  
+        boolean videoRecordedResult = false;
+        recordVideo(15, 240, 160, MediaRecorder.VideoEncoder.MPEG_4_SP, 
+               MediaRecorder.OutputFormat.MPEG_4, MediaNames.RECORDED_SQVGA_MP4, false);      
+        videoRecordedResult = validateVideo(MediaNames.RECORDED_SQVGA_MP4, 240, 160);
+        assertTrue("SQVGAMP4", videoRecordedResult);
+    }
+    
+    //Format: QCIF MP4
+    @LargeTest
+    public void testQCIFMP4() throws Exception {       
+        boolean videoRecordedResult = false;
+        recordVideo(15, 176, 144, MediaRecorder.VideoEncoder.MPEG_4_SP, 
+               MediaRecorder.OutputFormat.MPEG_4, MediaNames.RECORDED_QCIF_MP4, false);      
+        videoRecordedResult = validateVideo(MediaNames.RECORDED_QCIF_MP4, 176, 144);
+        assertTrue("QCIFMP4", videoRecordedResult);
+    }    
+    
+    
+    //Format: CIF MP4
+    @LargeTest
+    public void testCIFMP4() throws Exception {       
+        boolean videoRecordedResult = false;
+        recordVideo(15, 352, 288, MediaRecorder.VideoEncoder.MPEG_4_SP, 
+               MediaRecorder.OutputFormat.MPEG_4, MediaNames.RECORDED_CIF_MP4, false);      
+        videoRecordedResult = validateVideo(MediaNames.RECORDED_CIF_MP4, 352, 288);
+        assertTrue("CIFMP4", videoRecordedResult);
+    }
+    
+    
+    //Format: CIF MP4 output format 3gpp
+    @LargeTest
+    public void testCIFMP43GPP() throws Exception {       
+        boolean videoRecordedResult = false;
+        recordVideo(15, 352, 288, MediaRecorder.VideoEncoder.MPEG_4_SP, 
+               MediaRecorder.OutputFormat.THREE_GPP, MediaNames.RECORDED_VIDEO_3GP, false);      
+        videoRecordedResult = validateVideo(MediaNames.RECORDED_VIDEO_3GP, 352, 288);
+        assertTrue("CIFMP4 3GPP", videoRecordedResult);
+    }
+    
+    @LargeTest
+    public void testQCIFH2633GPP() throws Exception {       
+        boolean videoRecordedResult = false;
+        recordVideo(15, 176, 144, MediaRecorder.VideoEncoder.H263, 
+               MediaRecorder.OutputFormat.THREE_GPP, MediaNames.RECORDED_VIDEO_3GP, false);      
+        videoRecordedResult = validateVideo(MediaNames.RECORDED_VIDEO_3GP, 176, 144);
+        assertTrue("QCIFH263 3GPP", videoRecordedResult);
+    }
+    
+    @LargeTest
+    public void testInvalidVideoPath() throws Exception {       
+        boolean isTestInvalidVideoPathSuccessful = false;
+        isTestInvalidVideoPathSuccessful = invalidRecordSetting(15, 176, 144, MediaRecorder.VideoEncoder.H263, 
+               MediaRecorder.OutputFormat.THREE_GPP, MediaNames.INVALD_VIDEO_PATH, false);      
+        assertTrue("Invalid outputFile Path", isTestInvalidVideoPathSuccessful);
+    }
+    
+    @Suppress
+    public void testInvalidVideoSize() throws Exception {       
+        boolean isTestInvalidVideoSizeSuccessful = false;
+        isTestInvalidVideoSizeSuccessful = invalidRecordSetting(15, 800, 600, MediaRecorder.VideoEncoder.H263, 
+               MediaRecorder.OutputFormat.THREE_GPP, MediaNames.RECORDED_VIDEO_3GP, false);      
+        assertTrue("Invalid video Size", isTestInvalidVideoSizeSuccessful);
+    }
+    
+    @LargeTest
+    public void testInvalidFrameRate() throws Exception {       
+        boolean isTestInvalidFrameRateSuccessful = false;
+        isTestInvalidFrameRateSuccessful = invalidRecordSetting(50, 176, 144, MediaRecorder.VideoEncoder.H263, 
+               MediaRecorder.OutputFormat.THREE_GPP, MediaNames.RECORDED_VIDEO_3GP, false);      
+        assertTrue("Invalid FrameRate", isTestInvalidFrameRateSuccessful);
+    }
+    
+}
+
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/SimTonesTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/SimTonesTest.java
new file mode 100644
index 0000000..241f8d6
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/SimTonesTest.java
@@ -0,0 +1,73 @@
+/*
+ * 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.
+ */
+
+package com.android.mediaframeworktest.functional;
+
+// import android.content.Resources;
+import com.android.mediaframeworktest.MediaFrameworkTest;
+
+import android.content.Context;
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+
+/**
+ * Junit / Instrumentation test case for the SIM tone generator
+ * 
+ */  
+public class SimTonesTest extends ActivityInstrumentationTestCase<MediaFrameworkTest> {    
+    private String TAG = "SimTonesTest";
+    
+    Context mContext;
+
+    public SimTonesTest() {
+        super("com.android.mediaframeworktest", MediaFrameworkTest.class);
+      }
+
+       protected void setUp() throws Exception {
+         super.setUp();
+     }
+   
+   @LargeTest    
+   public void testDtmfTones() throws Exception {
+       boolean result = TonesAutoTest.tonesDtmfTest();
+     assertTrue("DTMF Tones", result);  
+   }
+
+   @LargeTest
+   public void testSupervisoryTones() throws Exception {
+       boolean result = TonesAutoTest.tonesSupervisoryTest();
+     assertTrue("Supervisory Tones", result);  
+   }
+
+   @LargeTest
+   public void testProprietaryTones() throws Exception {
+       boolean result = TonesAutoTest.tonesProprietaryTest();
+     assertTrue("Proprietary Tones", result);  
+   }
+
+   @LargeTest
+   public void testSimultaneousTones() throws Exception {
+       boolean result = TonesAutoTest.tonesSimultaneousTest();
+     assertTrue("Simultaneous Tones", result);  
+   }
+
+   @LargeTest
+   public void testStressTones() throws Exception {
+       boolean result = TonesAutoTest.tonesStressTest();
+     assertTrue("Stress Tones", result);  
+   }
+}
+
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/TonesAutoTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/TonesAutoTest.java
new file mode 100644
index 0000000..da18e74
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/TonesAutoTest.java
@@ -0,0 +1,180 @@
+/*
+ * 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.
+ */
+
+package com.android.mediaframeworktest.functional;
+
+
+//import android.content.Resources;
+import android.util.Log;
+
+import android.media.ToneGenerator;
+import android.media.AudioManager;
+
+/**
+ * Junit / Instrumentation test case for the Sim tones tests
+ 
+ */  
+    public class TonesAutoTest {
+        private static String TAG = "TonesAutoTest";
+
+    // Test all DTMF tones one by one
+    public static boolean tonesDtmfTest() throws Exception {
+        Log.v(TAG, "DTMF tones test");
+        ToneGenerator toneGen;
+        int type;
+        boolean result = true;
+
+        toneGen = new ToneGenerator(AudioManager.STREAM_MUSIC, 100);
+
+        for (type = ToneGenerator.TONE_DTMF_0; type <= ToneGenerator.TONE_DTMF_D; type++) {
+            if (toneGen.startTone(type)) {
+                Thread.sleep(200);
+                toneGen.stopTone();
+                Thread.sleep(100);
+            } else {
+                result = false;
+                break;
+            }
+        }
+
+        toneGen.release();
+        return result;
+    }
+
+    // Test all supervisory tones one by one
+    public static boolean tonesSupervisoryTest() throws Exception {
+      Log.v(TAG, "Supervisory tones test");
+      ToneGenerator toneGen;
+      int type;
+      boolean result = true;
+
+      toneGen = new ToneGenerator(AudioManager.STREAM_MUSIC, 100);
+      
+      for (type = ToneGenerator.TONE_SUP_DIAL;
+      type <= ToneGenerator.TONE_SUP_RINGTONE; type++) {
+          if (toneGen.startTone(type)) {
+              Thread.sleep(2000);
+              toneGen.stopTone();
+              Thread.sleep(200);
+          } else {
+              result = false;
+              break;
+          }
+      }
+      
+      toneGen.release();
+      return result;
+    }
+
+    // Test all proprietary tones one by one
+    public static boolean tonesProprietaryTest() throws Exception {
+        Log.v(TAG, "Proprietary tones test");
+        ToneGenerator toneGen;
+        int type;
+        boolean result = true;
+
+        toneGen = new ToneGenerator(AudioManager.STREAM_MUSIC, 100);
+
+        for (type = ToneGenerator.TONE_PROP_BEEP; type <= ToneGenerator.TONE_PROP_BEEP2; type++) {
+            if (toneGen.startTone(type)) {
+                Thread.sleep(1000);
+                toneGen.stopTone();
+                Thread.sleep(100);
+            } else {
+                result = false;
+                break;
+            }
+        }
+
+        toneGen.release();
+        return result;
+    }
+
+    // Test playback of 2 tones simultaneously
+    public static boolean tonesSimultaneousTest() throws Exception {
+        Log.v(TAG, "Simultaneous tones test");
+        ToneGenerator toneGen1;
+        ToneGenerator toneGen2;
+        int type;
+        boolean result = true;
+
+        toneGen1 = new ToneGenerator(AudioManager.STREAM_MUSIC, 100);
+        toneGen2 = new ToneGenerator(AudioManager.STREAM_MUSIC, 50);
+
+        if (toneGen1.startTone(ToneGenerator.TONE_DTMF_1)) {
+            Thread.sleep(100);
+            if (toneGen2.startTone(ToneGenerator.TONE_DTMF_2)) {
+                Thread.sleep(500);
+                toneGen1.stopTone();
+                Thread.sleep(100);
+                toneGen2.stopTone();
+            } else {
+                toneGen1.stopTone();
+                result = false;
+            }
+        } else {
+            result = false;
+        }
+
+        toneGen1.release();
+        toneGen2.release();
+        return result;
+    }
+
+    // Test start of new tone without stopping previous one 
+    public static boolean tonesStressTest() throws Exception {
+        Log.v(TAG, "Stress tones test");
+        ToneGenerator toneGen;
+        int type;
+        boolean result = true;
+
+        toneGen = new ToneGenerator(AudioManager.STREAM_MUSIC, 100);
+
+        for (type = ToneGenerator.TONE_DTMF_1; type <= ToneGenerator.TONE_DTMF_9; type++) {
+            if (toneGen.startTone(type)) {
+                Thread.sleep(200);
+            } else {
+                result = false;
+                break;
+            }
+        }
+
+        toneGen.release();
+        return result;
+    }
+   
+    // Perform all tones tests 
+    public static boolean tonesAllTest() throws Exception {
+        Log.v(TAG, "All tones tests");
+
+        if (!tonesDtmfTest()) {
+            return false;
+        }
+        if (!tonesSupervisoryTest()) {
+            return false;
+        }
+        if (!tonesProprietaryTest()) {
+            return false;
+        }
+        if (!tonesSimultaneousTest()) {
+            return false;
+        }
+        if (!tonesStressTest()) {
+            return false;
+        }
+        return true;
+    }
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java
new file mode 100644
index 0000000..2f0173d
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java
@@ -0,0 +1,376 @@
+/*
+ * 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.
+ */
+
+package com.android.mediaframeworktest.performance;
+
+import com.android.mediaframeworktest.MediaFrameworkTest;
+import com.android.mediaframeworktest.MediaNames;
+
+import android.database.sqlite.SQLiteDatabase;
+import android.media.MediaPlayer;
+import android.media.MediaRecorder;
+import android.os.SystemClock;
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.Suppress;
+import android.util.Log;
+import android.view.SurfaceHolder;
+
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Writer;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.BufferedWriter;
+
+import android.media.MediaMetadataRetriever;
+
+/**
+ * Junit / Instrumentation - performance measurement for media player and 
+ * recorder
+ */
+public class MediaPlayerPerformance extends ActivityInstrumentationTestCase<MediaFrameworkTest> {
+
+    private String TAG = "MediaFrameworkPerformance";
+
+    private SQLiteDatabase mDB;
+    private SurfaceHolder mSurfaceHolder = null;
+    private static final int NUM_STRESS_LOOP = 10;
+    private static final int NUM_PLAYBACk_IN_EACH_LOOP = 20;
+    private static final long MEDIA_STRESS_WAIT_TIME = 5000; //5 seconds
+    private static final String H263_VIDEO_PLAYBACK_MEMOUT =
+        "/sdcard/h263VideoPlaybackMemOut.txt";
+    private static final String H264_VIDEO_PLAYBACK_MEMOUT =
+        "/sdcard/h264VideoPlaybackMemOut.txt";
+    private static final String WMV_VIDEO_PLAYBACK_MEMOUT =
+        "/sdcard/WmvVideoPlaybackMemOut.txt";
+    private static final String H263_VIDEO_ONLY_RECORD_MEMOUT =
+        "/sdcard/recordH263VideoOnlyMemOut.txt";
+    private static final String MP4_VIDEO_ONLY_RECORD_MEMOUT =
+        "/sdcard/recordMPEG4VideoOnlyMemOut.txt";
+    private static final String H263_VIDEO_AUDIO_RECORD_MEMOUT =
+        "/sdcard/recordVideoH263AudioMemOut.txt";
+    private static final String AUDIO_ONLY_RECORD_MEMOUT =
+        "/sdcard/recordAudioOnlyMemOut.txt";
+
+
+    public MediaPlayerPerformance() {
+        super("com.android.mediaframeworktest", MediaFrameworkTest.class);
+    }
+
+    protected void setUp() throws Exception {
+        super.setUp();
+    }
+
+    public void createDB() {
+        mDB = SQLiteDatabase.openOrCreateDatabase("/sdcard/perf.db", null);
+        mDB.execSQL("CREATE TABLE perfdata (_id INTEGER PRIMARY KEY," + 
+                "file TEXT," + "setdatatime LONG," + "preparetime LONG," +
+                "playtime LONG" + ");");
+    }
+
+    public void audioPlaybackStartupTime(String[] testFile) {
+        long t1 = 0;
+        long t2 = 0;
+        long t3 = 0;
+        long t4 = 0;
+        long setDataSourceDuration = 0;
+        long prepareDuration = 0;
+        long startDuration = 0;
+        long totalSetDataTime = 0;
+        long totalPrepareTime = 0;
+        long totalStartDuration = 0;
+
+        int numberOfFiles = testFile.length;
+        Log.v(TAG, "File length " + numberOfFiles);
+        for (int k = 0; k < numberOfFiles; k++) {
+            MediaPlayer mp = new MediaPlayer();
+            try {
+                t1 = SystemClock.uptimeMillis();
+                FileInputStream fis = new FileInputStream(testFile[k]);
+                FileDescriptor fd = fis.getFD();
+                mp.setDataSource(fd);
+                fis.close();
+                t2 = SystemClock.uptimeMillis();
+                mp.prepare();
+                t3 = SystemClock.uptimeMillis();
+                mp.start();
+                t4 = SystemClock.uptimeMillis();
+            } catch (Exception e) {
+                Log.v(TAG, e.toString());
+            }
+            setDataSourceDuration = t2 - t1;
+            prepareDuration = t3 - t2;
+            startDuration = t4 - t3;
+            totalSetDataTime = totalSetDataTime + setDataSourceDuration;
+            totalPrepareTime = totalPrepareTime + prepareDuration;
+            totalStartDuration = totalStartDuration + startDuration;
+            mDB.execSQL("INSERT INTO perfdata (file, setdatatime, preparetime," +
+                    " playtime) VALUES (" + '"' + testFile[k] + '"' + ',' +
+                    setDataSourceDuration + ',' + prepareDuration +
+            		',' + startDuration + ");");
+            Log.v(TAG, "File name " + testFile[k]);
+            mp.stop();
+            mp.release();
+        }
+        Log.v(TAG, "setDataSource average " + totalSetDataTime / numberOfFiles);
+        Log.v(TAG, "prepare average " + totalPrepareTime / numberOfFiles);
+        Log.v(TAG, "start average " + totalStartDuration / numberOfFiles);
+
+    }
+
+    @Suppress
+    public void testStartUpTime() throws Exception {
+        createDB();
+        audioPlaybackStartupTime(MediaNames.MP3FILES);
+        audioPlaybackStartupTime(MediaNames.AACFILES);
+
+    }
+
+    public void wmametadatautility(String[] testFile) {
+        long t1 = 0;
+        long t2 = 0;
+        long sum = 0;
+        long duration = 0;
+        MediaMetadataRetriever retriever = new MediaMetadataRetriever();
+        String value;
+        for (int i = 0, n = testFile.length; i < n; ++i) {
+            try {
+                t1 = SystemClock.uptimeMillis();
+                retriever.setDataSource(testFile[i]);
+                value = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ALBUM);
+                value = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST);
+                value = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_COMPOSER);
+                value = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_GENRE);
+                value = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE);
+                value = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_YEAR);
+                value =
+                    retriever
+                    .extractMetadata(MediaMetadataRetriever.METADATA_KEY_CD_TRACK_NUMBER);
+                t2 = SystemClock.uptimeMillis();
+                duration = t2 - t1;
+                Log.v(TAG, "Time taken = " + duration);
+                sum = sum + duration;
+            } catch (Exception e) {
+                Log.v(TAG, e.getMessage());
+            }
+
+        }
+        Log.v(TAG, "Average duration = " + sum / testFile.length);
+    }
+
+
+    // Note: This test is to assume the mediaserver's pid is 34
+    public void mediaStressPlayback(String testFilePath) {
+        for (int i = 0; i < NUM_PLAYBACk_IN_EACH_LOOP; i++) {
+            MediaPlayer mp = new MediaPlayer();
+            try {
+                mp.setDataSource(testFilePath);
+                mp.setDisplay(MediaFrameworkTest.mSurfaceView.getHolder());
+                mp.prepare();
+                mp.start();
+                Thread.sleep(MEDIA_STRESS_WAIT_TIME);
+                mp.release();
+            } catch (Exception e) {
+                mp.release();
+                Log.v(TAG, e.toString());
+            }
+        }
+    }
+
+    // Note: This test is to assume the mediaserver's pid is 34
+    private void stressVideoRecord(int frameRate, int width, int height, int videoFormat,
+            int outFormat, String outFile, boolean videoOnly) {
+        // Video recording
+        for (int i = 0; i < NUM_PLAYBACk_IN_EACH_LOOP; i++) {
+            MediaRecorder mRecorder = new MediaRecorder();
+            try {
+                if (!videoOnly) {
+                    Log.v(TAG, "setAudioSource");
+                    mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
+                }
+                mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
+                mRecorder.setOutputFormat(outFormat);
+                Log.v(TAG, "output format " + outFormat);
+                mRecorder.setOutputFile(outFile);
+                mRecorder.setVideoFrameRate(frameRate);
+                mRecorder.setVideoSize(width, height);
+                Log.v(TAG, "setEncoder");
+                mRecorder.setVideoEncoder(videoFormat);
+                if (!videoOnly) {
+                    mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
+                }
+                mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
+                mRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
+                mRecorder.prepare();
+                mRecorder.start();
+                Thread.sleep(MEDIA_STRESS_WAIT_TIME);
+                mRecorder.stop();
+                mRecorder.release();
+            } catch (Exception e) {
+                Log.v("record video failed ", e.toString());
+                mRecorder.release();
+            }
+        }
+    }
+
+    public void stressAudioRecord(String filePath) {
+        // This test is only for the short media file
+        for (int i = 0; i < NUM_PLAYBACk_IN_EACH_LOOP; i++) {
+            MediaRecorder mRecorder = new MediaRecorder();
+            try {
+                mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
+                mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
+                mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
+                mRecorder.setOutputFile(filePath);
+                mRecorder.prepare();
+                mRecorder.start();
+                Thread.sleep(MEDIA_STRESS_WAIT_TIME);
+                mRecorder.stop();
+                mRecorder.release();
+            } catch (Exception e) {
+                Log.v(TAG, e.toString());
+                mRecorder.release();
+            }
+        }
+    }
+
+    //Write the ps output to the file
+    public void getMemoryWriteToLog(Writer output) {
+        String cm = "ps mediaserver";
+        String memoryUsage = null;
+        int ch;
+        try {
+            Process p = Runtime.getRuntime().exec(cm);
+            InputStream in = p.getInputStream();
+            StringBuffer sb = new StringBuffer(512);
+            while ((ch = in.read()) != -1) {
+                sb.append((char) ch);
+            }
+            memoryUsage = sb.toString();
+        } catch (IOException e) {
+            Log.v(TAG, e.toString());
+        }
+
+        String[] poList = memoryUsage.split("\r|\n|\r\n");
+        String memusage = poList[1].concat("\n");
+        Log.v(TAG, memusage);
+        try {
+            //Write to file output
+            output.write(memusage);
+        } catch (Exception e) {
+            e.toString();
+        }
+    }
+
+
+    @Suppress
+    public void testWmaParseTime() throws Exception {
+        // createDB();
+        wmametadatautility(MediaNames.WMASUPPORTED);
+    }
+
+
+    // Test case 1: Capture the memory usage after every 20 h263 playback
+    @LargeTest
+    public void testH263VideoPlaybackMemoryUsage() throws Exception {
+        File h263MemoryOut = new File(H263_VIDEO_PLAYBACK_MEMOUT);
+        Writer output = new BufferedWriter(new FileWriter(h263MemoryOut));
+        for (int i = 0; i < NUM_STRESS_LOOP; i++) {
+            mediaStressPlayback(MediaNames.VIDEO_HIGHRES_H263);
+            getMemoryWriteToLog(output);
+        }
+        output.close();
+    }
+
+    // Test case 2: Capture the memory usage after every 20 h264 playback
+    @LargeTest
+    public void testH264VideoPlaybackMemoryUsage() throws Exception {
+        File h264MemoryOut = new File(H264_VIDEO_PLAYBACK_MEMOUT);
+        Writer output = new BufferedWriter(new FileWriter(h264MemoryOut));
+        for (int i = 0; i < NUM_STRESS_LOOP; i++) {
+            mediaStressPlayback(MediaNames.VIDEO_H264_AMR);
+            getMemoryWriteToLog(output);
+        }
+        output.close();
+    }
+
+    // Test case 3: Capture the memory usage after each 20 WMV playback
+    @LargeTest
+    public void testWMVVideoPlaybackMemoryUsage() throws Exception {
+        File wmvMemoryOut = new File(WMV_VIDEO_PLAYBACK_MEMOUT);
+        Writer output = new BufferedWriter(new FileWriter(wmvMemoryOut));
+        for (int i = 0; i < NUM_STRESS_LOOP; i++) {
+            mediaStressPlayback(MediaNames.VIDEO_WMV);
+            getMemoryWriteToLog(output);
+        }
+        output.close();
+    }
+
+    // Test case 4: Capture the memory usage after every 20 video only recorded
+    @LargeTest
+    public void testH263RecordVideoOnlyMemoryUsage() throws Exception {
+        File videoH263RecordOnlyMemoryOut = new File(H263_VIDEO_ONLY_RECORD_MEMOUT);
+        Writer output = new BufferedWriter(new FileWriter(videoH263RecordOnlyMemoryOut));
+        for (int i = 0; i < NUM_STRESS_LOOP; i++) {
+            stressVideoRecord(20, 352, 288, MediaRecorder.VideoEncoder.H263,
+                    MediaRecorder.OutputFormat.MPEG_4, MediaNames.RECORDED_VIDEO_3GP, true);
+            getMemoryWriteToLog(output);
+        }
+        output.close();
+    }
+
+    // Test case 5: Capture the memory usage after every 20 video only recorded
+    @LargeTest
+    public void testMpeg4RecordVideoOnlyMemoryUsage() throws Exception {
+        File videoMp4RecordOnlyMemoryOut = new File(MP4_VIDEO_ONLY_RECORD_MEMOUT);
+        Writer output = new BufferedWriter(new FileWriter(videoMp4RecordOnlyMemoryOut));
+        for (int i = 0; i < NUM_STRESS_LOOP; i++) {
+            stressVideoRecord(20, 352, 288, MediaRecorder.VideoEncoder.MPEG_4_SP,
+                    MediaRecorder.OutputFormat.MPEG_4, MediaNames.RECORDED_VIDEO_3GP, true);
+            getMemoryWriteToLog(output);
+        }
+        output.close();
+    }
+
+    // Test case 6: Capture the memory usage after every 20 video and audio recorded
+    @LargeTest
+    public void testRecordVidedAudioMemoryUsage() throws Exception {
+        File videoRecordAudioMemoryOut = new File(H263_VIDEO_AUDIO_RECORD_MEMOUT);
+        Writer output = new BufferedWriter(new FileWriter(videoRecordAudioMemoryOut));
+        for (int i = 0; i < NUM_STRESS_LOOP; i++) {
+            stressVideoRecord(20, 352, 288, MediaRecorder.VideoEncoder.H263,
+                    MediaRecorder.OutputFormat.MPEG_4, MediaNames.RECORDED_VIDEO_3GP, false);
+            getMemoryWriteToLog(output);
+        }
+        output.close();
+    }
+
+    // Test case 7: Capture the memory usage after every 20 audio only recorded
+    @LargeTest
+    public void testRecordAudioOnlyMemoryUsage() throws Exception {
+        File audioOnlyMemoryOut = new File(AUDIO_ONLY_RECORD_MEMOUT);
+        Writer output = new BufferedWriter(new FileWriter(audioOnlyMemoryOut));
+        for (int i = 0; i < NUM_STRESS_LOOP; i++) {
+            stressAudioRecord(MediaNames.RECORDER_OUTPUT);
+            getMemoryWriteToLog(output);
+        }
+        output.close();
+    }
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaRecorderStressTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaRecorderStressTest.java
new file mode 100644
index 0000000..dbf937c
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaRecorderStressTest.java
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+package com.android.mediaframeworktest.stress;
+
+import com.android.mediaframeworktest.MediaFrameworkTest;
+
+import android.hardware.Camera;
+import android.media.MediaPlayer;
+import android.media.MediaRecorder;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.util.Log;
+import android.view.SurfaceHolder;
+
+/**
+ * Junit / Instrumentation test case for the media player api
+ 
+ */  
+public class MediaRecorderStressTest extends ActivityInstrumentationTestCase2<MediaFrameworkTest> {    
+    
+  
+    private String TAG = "MediaRecorderStressTest";
+    private MediaRecorder mRecorder;
+    private Camera mCamera;
+   
+    private static final int NUMBER_OF_CAMERA_STRESS_LOOPS = 100;
+    private static final int NUMBER_OF_RECORDER_STRESS_LOOPS = 100;
+    private static final int NUMBER_OF_RECORDERANDPLAY_STRESS_LOOPS = 50;
+    private static final int NUMBER_OF_SWTICHING_LOOPS_BW_CAMERA_AND_RECORDER = 200;
+    private static final long WAIT_TIME_CAMERA_TEST = 3000;  // 3 second
+    private static final long WAIT_TIME_RECORDER_TEST = 60000;  // 6 second
+    private static final long WAIT_TIME_RECORD = 100000;  // 10 seconds
+    private static final long WAIT_TIME_PLAYBACK = 60000;  // 6 second
+    private static final String OUTPUT_FILE = "/sdcard/temp";
+    private static final String OUTPUT_FILE_EXT = ".3gp";
+    
+    public MediaRecorderStressTest() {
+        super("com.android.mediaframeworktest", MediaFrameworkTest.class);
+    }
+
+    protected void setUp() throws Exception {
+        getActivity();
+        super.setUp();      
+    }
+       
+    //Test case for stressing the camera preview.
+    @LargeTest
+    public void testStressCamera() throws Exception {
+        SurfaceHolder mSurfaceHolder;             
+        mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
+        try {        
+            Log.v(TAG, "Start preview");
+            for (int i = 0; i< NUMBER_OF_CAMERA_STRESS_LOOPS; i++){
+                mCamera = Camera.open();
+                mCamera.setPreviewDisplay(mSurfaceHolder);
+                mCamera.startPreview();
+                Thread.sleep(WAIT_TIME_CAMERA_TEST);
+                mCamera.stopPreview();
+                mCamera.release();
+            }
+        } catch (Exception e) {
+                Log.v(TAG, e.toString());
+        }
+    }
+    
+    //Test case for stressing the camera preview.
+    @LargeTest
+    public void testStressRecorder() throws Exception {
+        String filename;
+        SurfaceHolder mSurfaceHolder;             
+        mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
+        try {    
+            Log.v(TAG, "Start preview");
+            for (int i = 0; i < NUMBER_OF_RECORDER_STRESS_LOOPS; i++){
+                Log.v(TAG, "counter = " + i);
+                filename = OUTPUT_FILE + i + OUTPUT_FILE_EXT;
+                Log.v(TAG, filename);
+                mRecorder = new MediaRecorder();
+                mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
+                mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);          
+                mRecorder.setOutputFile(filename);
+                mRecorder.setVideoFrameRate(20);
+                mRecorder.setVideoSize(176,144);
+                Log.v(TAG, "setEncoder");
+                mRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H263);
+                mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
+                Log.v(TAG, "setPreview");
+                mRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
+                Log.v(TAG, "prepare");
+                mRecorder.prepare();
+                Log.v(TAG, "before release");
+                Thread.sleep(WAIT_TIME_RECORDER_TEST);  
+                mRecorder.reset();
+                mRecorder.release();
+            }
+        } catch (Exception e) {
+                Log.v(TAG, e.toString());
+        }
+    }
+    
+    
+    //Stress test case for switching camera and video recorder preview.
+    @LargeTest
+    public void testStressCameraSwitchRecorder() throws Exception {
+        String filename;
+        SurfaceHolder mSurfaceHolder;             
+        mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
+        try {    
+            Log.v(TAG, "Start preview");
+            for (int i = 0; i < NUMBER_OF_SWTICHING_LOOPS_BW_CAMERA_AND_RECORDER; i++){
+                mCamera = Camera.open();
+                mCamera.setPreviewDisplay(mSurfaceHolder);
+                mCamera.startPreview();
+                Thread.sleep(WAIT_TIME_CAMERA_TEST);
+                mCamera.stopPreview();
+                mCamera.release();
+                mCamera = null;
+                Log.v(TAG, "release camera");
+                filename = OUTPUT_FILE + i + OUTPUT_FILE_EXT;
+                Log.v(TAG, filename);
+                mRecorder = new MediaRecorder();
+                mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
+                mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);          
+                mRecorder.setOutputFile(filename);
+                mRecorder.setVideoFrameRate(20);
+                mRecorder.setVideoSize(176,144);
+                Log.v(TAG, "Media recorder setEncoder");
+                mRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H263);
+                Log.v(TAG, "mediaRecorder setPreview");
+                mRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
+                Log.v(TAG, "prepare");
+                mRecorder.prepare();
+                Log.v(TAG, "before release");
+                Thread.sleep(WAIT_TIME_CAMERA_TEST);  
+                mRecorder.release();
+                Log.v(TAG, "release video recorder");                
+            }
+        } catch (Exception e) {
+                Log.v(TAG, e.toString());
+        }
+    }
+    
+    //Stress test case for record a video and play right away.
+    @LargeTest
+    public void testStressRecordVideoAndPlayback() throws Exception {
+        String filename;
+        SurfaceHolder mSurfaceHolder;             
+        mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
+        try {    
+            for (int i = 0; i < NUMBER_OF_RECORDERANDPLAY_STRESS_LOOPS; i++){
+                filename = OUTPUT_FILE + i + OUTPUT_FILE_EXT;
+                Log.v(TAG, filename);
+                mRecorder = new MediaRecorder();
+                mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
+                mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
+                mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);          
+                mRecorder.setOutputFile(filename);
+                mRecorder.setVideoFrameRate(20);
+                mRecorder.setVideoSize(352,288);
+                mRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H263);
+                mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
+                Log.v(TAG, "mediaRecorder setPreview");
+                mRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
+                mRecorder.prepare();
+                mRecorder.start();               
+                Thread.sleep(WAIT_TIME_RECORD);
+                Log.v(TAG, "Before stop");
+                mRecorder.stop();
+                mRecorder.release();
+                //start the playback
+                MediaPlayer mp = new MediaPlayer();
+                mp.setDataSource(filename);
+                mp.setDisplay(MediaFrameworkTest.mSurfaceView.getHolder());
+                mp.prepare();
+                mp.start();
+                Thread.sleep(WAIT_TIME_PLAYBACK);
+                mp.release();
+            }
+        } catch (Exception e) {
+                Log.v(TAG, e.toString());
+        }
+    }   
+}
+
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaMetadataRetrieverTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaMetadataRetrieverTest.java
new file mode 100644
index 0000000..61a8a29
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaMetadataRetrieverTest.java
@@ -0,0 +1,242 @@
+/*
+ * 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.
+ */
+
+package com.android.mediaframeworktest.unit;
+
+import android.util.Log;
+import android.media.MediaMetadataRetriever;
+import android.graphics.Bitmap;
+import java.io.FileOutputStream;
+import android.test.AndroidTestCase;
+import com.android.mediaframeworktest.MediaNames;
+import android.test.suitebuilder.annotation.*;
+
+/**
+ * WARNING:
+ * Currently, captureFrame() does not work, due to hardware access permission problem.
+ * We are currently only testing the metadata/album art retrieval features.
+ */
+public class MediaMetadataRetrieverTest extends AndroidTestCase {
+    
+    private static final String TAG         = "MediaMetadataRetrieverTest";
+   
+    // Test album art extraction.
+    @MediumTest
+    public static void testAlbumArt() throws Exception {
+        Log.v(TAG, "testAlbumArt starts.");
+        MediaMetadataRetriever retriever = new MediaMetadataRetriever();
+        retriever.setMode(MediaMetadataRetriever.MODE_GET_METADATA_ONLY);
+        for (int i = 0, n = MediaNames.ALBUMART_TEST_FILES.length; i < n; ++i) {
+            try {
+                Log.v(TAG, "File " + i + ": " + MediaNames.ALBUMART_TEST_FILES[i]);
+                retriever.setDataSource(MediaNames.ALBUMART_TEST_FILES[i]);
+                byte[] albumArt = retriever.extractAlbumArt();
+
+                // TODO:
+                // A better test would be to compare the retrieved album art with the
+                // known result.
+                if (albumArt == null) {  // Do we have expect in JUnit?
+                    fail("Fails to extract album art for " + MediaNames.ALBUMART_TEST_FILES[i]);
+                }
+            } catch(Exception e) {
+                throw new Exception("Fails to setDataSource for " + MediaNames.ALBUMART_TEST_FILES[i], e);
+            }
+            Thread.yield();  // Don't be evil
+        }
+        retriever.release();
+        Log.v(TAG, "testAlbumArt completes.");
+    }
+
+    // Test frame capture
+    // Suppressing until 1259652 is fixed.
+    @Suppress
+    public static void disableTestThumbnailCapture() throws Exception {
+        MediaMetadataRetriever retriever = new MediaMetadataRetriever();
+        Log.v(TAG, "Thumbnail processing starts");
+        long startedAt = System.currentTimeMillis();
+        for(int i = 0, n = MediaNames.THUMBNAIL_CAPTURE_TEST_FILES.length; i < n; ++i) {
+            try {
+                Log.v(TAG, "File " + i + ": " + MediaNames.THUMBNAIL_CAPTURE_TEST_FILES[i]);
+                retriever.setDataSource(MediaNames.THUMBNAIL_CAPTURE_TEST_FILES[i]);
+                Bitmap bitmap = retriever.captureFrame();
+                assertTrue(bitmap != null);
+                try {
+                    java.io.OutputStream stream = new FileOutputStream(MediaNames.THUMBNAIL_CAPTURE_TEST_FILES[i] + ".jpg");
+                    bitmap.compress(Bitmap.CompressFormat.JPEG, 75, stream);
+                    stream.close();
+                } catch (Exception e) {
+                    throw new Exception("Fails to convert the bitmap to a JPEG file for " + MediaNames.THUMBNAIL_CAPTURE_TEST_FILES[i], e);
+                }
+            } catch(Exception e) {
+                throw new Exception("Fails to setDataSource for file " + MediaNames.THUMBNAIL_CAPTURE_TEST_FILES[i], e);
+            }
+            Thread.yield();  // Don't be evil
+        }
+        long endedAt = System.currentTimeMillis();
+        Log.v(TAG, "Average processing time per thumbnail: " + (endedAt - startedAt)/MediaNames.THUMBNAIL_CAPTURE_TEST_FILES.length + " ms");
+        retriever.release();
+    }
+    
+    @LargeTest
+    public static void testMetadataRetrieval() throws Exception {
+        MediaMetadataRetriever retriever = new MediaMetadataRetriever();
+        retriever.setMode(MediaMetadataRetriever.MODE_GET_METADATA_ONLY);
+        for(int i = 0, n = MediaNames.METADATA_RETRIEVAL_TEST_FILES.length; i < n; ++i) {
+            try {
+                retriever.setDataSource(MediaNames.METADATA_RETRIEVAL_TEST_FILES[i]);
+                extractAllSupportedMetadataValues(retriever);
+            } catch(Exception e) {
+                throw new Exception("Fails to setDataSource for file " + MediaNames.METADATA_RETRIEVAL_TEST_FILES[i], e);
+            }
+            Thread.yield();  // Don't be evil
+        }
+        retriever.release();
+    }
+
+    // If the specified call order and valid media file is used, no exception
+    // should be thrown.
+    @MediumTest
+    public static void testBasicNormalMethodCallSequence() throws Exception {
+        MediaMetadataRetriever retriever = new MediaMetadataRetriever();
+        retriever.setMode(MediaMetadataRetriever.MODE_GET_METADATA_ONLY);
+        try {
+            retriever.setDataSource(MediaNames.TEST_PATH_1);
+            /*
+             * captureFrame() fails due to lack of permission to access hardware decoder devices
+            Bitmap bitmap = retriever.captureFrame();
+            assertTrue(bitmap != null);
+            try {
+                java.io.OutputStream stream = new FileOutputStream("/sdcard/thumbnailout.jpg");
+                bitmap.compress(Bitmap.CompressFormat.JPEG, 75, stream);
+                stream.close();
+            } catch (Exception e) {
+                throw new Exception("Fails to convert the bitmap to a JPEG file for " + MediaNames.TEST_PATH_1, e);
+            }
+            */
+            extractAllSupportedMetadataValues(retriever);
+        } catch(Exception e) {
+            throw new Exception("Fails to setDataSource for " + MediaNames.TEST_PATH_1, e);
+        }
+        retriever.release();
+    }
+
+    // If setDataSource() has not been called, both captureFrame() and extractMetadata() must
+    // return null.
+    @MediumTest
+    public static void testBasicAbnormalMethodCallSequence() {
+        MediaMetadataRetriever retriever = new MediaMetadataRetriever();
+        retriever.setMode(MediaMetadataRetriever.MODE_GET_METADATA_ONLY);
+        assertTrue(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ALBUM) == null);
+        assertTrue(retriever.captureFrame() == null);
+    }
+
+    // Test setDataSource()
+    @MediumTest
+    public static void testSetDataSource() {
+        MediaMetadataRetriever retriever = new MediaMetadataRetriever();
+        retriever.setMode(MediaMetadataRetriever.MODE_GET_METADATA_ONLY);
+
+        // Null pointer argument
+        try {
+            String path = null;
+            retriever.setDataSource(path);
+            fail("IllegalArgumentException must be thrown.");
+        } catch(Exception e) {
+            assertTrue(e instanceof IllegalArgumentException);
+        }
+
+        // Use mem:// path
+        try {
+            retriever.setDataSource(MediaNames.TEST_PATH_5);
+            fail("IllegalArgumentException must be thrown.");
+        } catch(Exception e) {
+            assertTrue(e instanceof IllegalArgumentException);
+        }
+
+        // The pathname does not correspond to any existing file
+        try {
+            retriever.setDataSource(MediaNames.TEST_PATH_4);
+            fail("Runtime exception must be thrown.");
+        } catch(Exception e) {
+            assertTrue(e instanceof RuntimeException);
+        }
+
+        // The pathname does correspond to a file, but this file
+        // is not a valid media file
+        try {
+            retriever.setDataSource(MediaNames.TEST_PATH_3);
+            fail("Runtime exception must be thrown.");
+        } catch(Exception e) {
+            assertTrue(e instanceof RuntimeException);
+        }
+        
+        retriever.release();
+    }
+
+    // Due to the lack of permission to access hardware decoder, any calls
+    // attempting to capture a frame will fail. These are commented out for now
+    // until we find a solution to this access permission problem.
+    @MediumTest
+    public static void testIntendedUsage() {
+        // By default, capture frame and retrieve metadata
+        MediaMetadataRetriever retriever = new MediaMetadataRetriever();
+        // retriever.setDataSource(MediaNames.TEST_PATH_1);
+        // assertTrue(retriever.captureFrame() != null);
+        // assertTrue(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_NUM_TRACKS) != null);
+
+        // Do not capture frame or retrieve metadata
+        retriever.setMode(MediaMetadataRetriever.MODE_CAPTURE_FRAME_ONLY & MediaMetadataRetriever.MODE_GET_METADATA_ONLY);
+        retriever.setDataSource(MediaNames.TEST_PATH_1);
+        assertTrue(retriever.captureFrame() == null);
+        assertTrue(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_NUM_TRACKS) == null);
+
+        // Capture frame only
+        // retriever.setMode(MediaMetadataRetriever.MODE_CAPTURE_FRAME_ONLY);
+        // retriever.setDataSource(MediaNames.TEST_PATH_1);
+        // assertTrue(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_NUM_TRACKS) == null);
+
+        // Retriever metadata only
+        retriever.setMode(MediaMetadataRetriever.MODE_GET_METADATA_ONLY);
+        retriever.setDataSource(MediaNames.TEST_PATH_1);
+        assertTrue(retriever.captureFrame() == null);
+
+        // Capture frame and retrieve metadata
+        // retriever.setMode(MediaMetadataRetriever.MODE_CAPTURE_FRAME_ONLY | MediaMetadataRetriever.MODE_GET_METADATA_ONLY);
+        // retriever.setDataSource(MediaNames.TEST_PATH_1);
+        // assertTrue(retriever.captureFrame() != null);
+        // assertTrue(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_NUM_TRACKS) != null);
+        retriever.release();
+    }
+
+    // TODO:
+    // Encode and test for the correct mix of metadata elements on a per-file basis?
+    // We should be able to compare the actual returned metadata with the expected metadata
+    // with each given sample test file.
+    private static void extractAllSupportedMetadataValues(MediaMetadataRetriever retriever) {
+        String value = null;
+        Log.v(TAG, (value = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_CD_TRACK_NUMBER)) == null? "not found": value);
+        Log.v(TAG, (value = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)) == null? "not found": value);
+        Log.v(TAG, (value = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_NUM_TRACKS)) == null? "not found": value);
+        Log.v(TAG, (value = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ALBUM)) == null? "not found": value);
+        Log.v(TAG, (value = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST)) == null? "not found": value);
+        Log.v(TAG, (value = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_AUTHOR)) == null? "not found": value);
+        Log.v(TAG, (value = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_COMPOSER)) == null? "not found": value);
+        Log.v(TAG, (value = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DATE)) == null? "not found": value);
+        Log.v(TAG, (value = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_GENRE)) == null? "not found": value);
+        Log.v(TAG, (value = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE)) == null? "not found": value);
+        Log.v(TAG, (value = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_YEAR)) == null? "not found": value);
+    }
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerGetCurrentPositionStateUnitTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerGetCurrentPositionStateUnitTest.java
new file mode 100644
index 0000000..032b469
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerGetCurrentPositionStateUnitTest.java
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+
+package com.android.mediaframeworktest.unit;
+
+import android.media.MediaPlayer;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.LargeTest;;
+
+/**
+ * Unit test class to test the set of valid and invalid states that
+ * MediaPlayer.getCurrentPosition() method can be called.
+ */
+public class MediaPlayerGetCurrentPositionStateUnitTest extends AndroidTestCase implements MediaPlayerMethodUnderTest {
+    private MediaPlayerStateUnitTestTemplate mTestTemplate = new MediaPlayerStateUnitTestTemplate();
+ 
+    /**
+     * 1. It is valid to call getCurrentPosition() in the following states:
+     *    {Idle, Initialized, Prepared, Started, Paused, Stopped, PlaybackCompleted}.
+     * 2. It is invalid to call getCurrentPosition() in the following states:
+     *    {Error}
+     *    
+     * @param stateErrors the MediaPlayerStateErrors to check against.
+     */
+    public void checkStateErrors(MediaPlayerStateErrors stateErrors) {
+        // Valid states.
+        assertTrue(!stateErrors.errorInInitializedState);
+        assertTrue(!stateErrors.errorInPreparedState);
+        assertTrue(!stateErrors.errorInPreparedStateAfterStop);
+        assertTrue(!stateErrors.errorInStartedState);
+        assertTrue(!stateErrors.errorInStartedStateAfterPause);
+        assertTrue(!stateErrors.errorInPausedState);
+        assertTrue(!stateErrors.errorInStoppedState);
+        assertTrue(!stateErrors.errorInPlaybackCompletedState);
+        assertTrue(!stateErrors.errorInIdleStateAfterReset);
+        
+        // Invalid states.
+        assertTrue(stateErrors.errorInErrorState);
+        assertTrue(!stateErrors.errorInIdleState);  // onError() won't be called
+    }
+    
+    public void invokeMethodUnderTest(MediaPlayer player) {
+        player.getCurrentPosition();
+    }
+    
+    @LargeTest
+    public void testGetCurrentPosition() {
+        mTestTemplate.runTestOnMethod(this);
+    }
+
+    @Override
+    public String toString() {
+        return "getCurrentPosition()";
+    }
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerGetDurationStateUnitTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerGetDurationStateUnitTest.java
new file mode 100644
index 0000000..5f7abe5
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerGetDurationStateUnitTest.java
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+
+package com.android.mediaframeworktest.unit;
+
+import android.media.MediaPlayer;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+
+/**
+ * Unit test class to test the set of valid and invalid states that
+ * MediaPlayer.getDuration() method can be called.
+ */
+public class MediaPlayerGetDurationStateUnitTest extends AndroidTestCase implements MediaPlayerMethodUnderTest {
+    private MediaPlayerStateUnitTestTemplate mTestTemplate = new MediaPlayerStateUnitTestTemplate();
+
+    /**
+     * 1. It is valid to call getDuration() in the following states:
+     *    {Prepared, Started, Paused, Stopped, PlaybackCompleted}.
+     * 2. It is invalid to call getDuration() in the following states:
+     *    {Idle, Initialized, Error}
+     *    
+     * @param stateErrors the MediaPlayerStateErrors to check against.
+     */
+    public void checkStateErrors(MediaPlayerStateErrors stateErrors) {
+        // Valid states.
+        assertTrue(!stateErrors.errorInPreparedStateAfterStop);
+        assertTrue(!stateErrors.errorInPreparedState);
+        assertTrue(!stateErrors.errorInStartedState);
+        assertTrue(!stateErrors.errorInStartedStateAfterPause);
+        assertTrue(!stateErrors.errorInPausedState);
+        assertTrue(!stateErrors.errorInStoppedState);
+        assertTrue(!stateErrors.errorInPlaybackCompletedState);
+        
+        // Invalid states.
+        assertTrue(!stateErrors.errorInIdleState);  // onError() won't be called
+        assertTrue(stateErrors.errorInInitializedState);
+        assertTrue(stateErrors.errorInErrorState);
+        assertTrue(stateErrors.errorInIdleStateAfterReset);
+    }
+    
+    public void invokeMethodUnderTest(MediaPlayer player) {
+        player.getDuration();
+    }
+
+    @LargeTest
+    public void testGetDuration() {
+        mTestTemplate.runTestOnMethod(this);
+    }
+
+    @Override
+    public String toString() {
+        return "getDuration()";
+    }
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerGetVideoHeightStateUnitTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerGetVideoHeightStateUnitTest.java
new file mode 100644
index 0000000..6d3c083
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerGetVideoHeightStateUnitTest.java
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+
+package com.android.mediaframeworktest.unit;
+
+import android.media.MediaPlayer;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+
+/**
+ * Unit test class to test the set of valid and invalid states that
+ * MediaPlayer.getVideoHeight() method can be called.
+ */
+public class MediaPlayerGetVideoHeightStateUnitTest extends AndroidTestCase implements MediaPlayerMethodUnderTest {
+    private MediaPlayerStateUnitTestTemplate mTestTemplate = new MediaPlayerStateUnitTestTemplate();
+
+    /**
+     * 1. It is valid to call getVideoHeight() in the following states:
+     *    {Idle, Initialized, Prepared, Started, Paused, Stopped, PlaybackCompleted}.
+     * 2. It is invalid to call getVideoHeight() in the following states:
+     *    {Error}
+     *    
+     * @param stateErrors the MediaPlayerStateErrors to check against.
+     */
+    public void checkStateErrors(MediaPlayerStateErrors stateErrors) {
+        // Valid states.
+        assertTrue(!stateErrors.errorInPreparedState);
+        assertTrue(!stateErrors.errorInPreparedStateAfterStop);
+        assertTrue(!stateErrors.errorInStartedState);
+        assertTrue(!stateErrors.errorInStartedStateAfterPause);
+        assertTrue(!stateErrors.errorInPausedState);
+        assertTrue(!stateErrors.errorInPlaybackCompletedState);
+        assertTrue(!stateErrors.errorInIdleState);
+        assertTrue(!stateErrors.errorInIdleStateAfterReset);
+        assertTrue(!stateErrors.errorInInitializedState);
+        assertTrue(!stateErrors.errorInStoppedState);
+        
+        // Invalid states.
+        assertTrue(stateErrors.errorInErrorState);
+    }
+
+    public void invokeMethodUnderTest(MediaPlayer player) {
+        player.getVideoHeight();
+    }
+
+    @LargeTest
+    public void testGetVideoHeight() {
+        mTestTemplate.runTestOnMethod(this);
+    }
+
+    @Override
+    public String toString() {
+        return "getVideoHeight()";
+    }
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerGetVideoWidthStateUnitTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerGetVideoWidthStateUnitTest.java
new file mode 100644
index 0000000..198439c
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerGetVideoWidthStateUnitTest.java
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+
+package com.android.mediaframeworktest.unit;
+
+import android.media.MediaPlayer;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+
+/**
+ * Unit test class to test the set of valid and invalid states that
+ * MediaPlayer.getVideoWidth() method can be called.
+ */
+public class MediaPlayerGetVideoWidthStateUnitTest extends AndroidTestCase implements MediaPlayerMethodUnderTest {
+    private MediaPlayerStateUnitTestTemplate mTestTemplate = new MediaPlayerStateUnitTestTemplate();
+
+    /**
+     * 1. It is valid to call getVideoWidth() in the following states:
+     *    {Idle, Initialized, Prepared, Started, Paused, Stopped, PlaybackCompleted}.
+     * 2. It is invalid to call getVideoWidth() in the following states:
+     *    {Error}
+     *    
+     * @param stateErrors the MediaPlayerStateErrors to check against.
+     */
+    public void checkStateErrors(MediaPlayerStateErrors stateErrors) {
+        // Valid states.
+        assertTrue(!stateErrors.errorInPreparedState);
+        assertTrue(!stateErrors.errorInStartedState);
+        assertTrue(!stateErrors.errorInStartedStateAfterPause);
+        assertTrue(!stateErrors.errorInPausedState);
+        assertTrue(!stateErrors.errorInPlaybackCompletedState);
+        assertTrue(!stateErrors.errorInIdleState);
+        assertTrue(!stateErrors.errorInIdleStateAfterReset);
+        assertTrue(!stateErrors.errorInInitializedState);
+        assertTrue(!stateErrors.errorInStoppedState);
+        assertTrue(!stateErrors.errorInPreparedStateAfterStop);
+
+        // Invalid states.
+        assertTrue(stateErrors.errorInErrorState);
+    }
+
+    public void invokeMethodUnderTest(MediaPlayer player) {
+        player.getVideoWidth();
+    }
+
+    @LargeTest
+    public void testGetVideoWidth() {
+        mTestTemplate.runTestOnMethod(this);
+    }
+
+    @Override
+    public String toString() {
+        return "getVideoWidth()";
+    }
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerIsPlayingStateUnitTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerIsPlayingStateUnitTest.java
new file mode 100644
index 0000000..b9c63fd
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerIsPlayingStateUnitTest.java
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+
+package com.android.mediaframeworktest.unit;
+
+import android.media.MediaPlayer;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+
+/**
+ * Unit test class to test the set of valid and invalid states that
+ * MediaPlayer.isPlaying() method can be called.
+ */
+public class MediaPlayerIsPlayingStateUnitTest extends AndroidTestCase implements MediaPlayerMethodUnderTest {
+    private MediaPlayerStateUnitTestTemplate mTestTemplate = new MediaPlayerStateUnitTestTemplate();
+
+    /**
+     * 1. It is valid to call isPlaying() in the following states:
+     *    {Idle, Initialized, Prepared, Started, Paused, Stopped, PlaybackCompleted}.
+     * 2. It is invalid to call isPlaying() in the following states:
+     *    {Error}
+     *    
+     * @param stateErrors the MediaPlayerStateErrors to check against.
+     */
+    public void checkStateErrors(MediaPlayerStateErrors stateErrors) {
+        // Valid states.
+        assertTrue(!stateErrors.errorInPreparedState);
+        assertTrue(!stateErrors.errorInPreparedStateAfterStop);
+        assertTrue(!stateErrors.errorInStartedState);
+        assertTrue(!stateErrors.errorInStartedStateAfterPause);
+        assertTrue(!stateErrors.errorInPausedState);
+        assertTrue(!stateErrors.errorInPlaybackCompletedState);
+        assertTrue(!stateErrors.errorInIdleState);
+        assertTrue(!stateErrors.errorInIdleStateAfterReset);
+        assertTrue(!stateErrors.errorInInitializedState);
+        assertTrue(!stateErrors.errorInStoppedState);
+        
+        // Invalid states.
+        assertTrue(stateErrors.errorInErrorState);
+    }
+
+    public void invokeMethodUnderTest(MediaPlayer player) {
+        player.isPlaying();
+    }
+
+    @LargeTest
+    public void testIsPlaying() {
+        mTestTemplate.runTestOnMethod(this);
+    }
+
+    @Override
+    public String toString() {
+        return "isPlaying()";
+    }
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerMethodUnderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerMethodUnderTest.java
new file mode 100644
index 0000000..91ed694
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerMethodUnderTest.java
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+
+package com.android.mediaframeworktest.unit;
+
+import android.media.MediaPlayer;
+
+/**
+ * All MediaPlayer method unit test subclass must implement this interface. 
+ */
+interface MediaPlayerMethodUnderTest {
+    public void checkStateErrors(MediaPlayerStateErrors stateErrors);
+    public void invokeMethodUnderTest(MediaPlayer player);
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerPauseStateUnitTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerPauseStateUnitTest.java
new file mode 100644
index 0000000..0a18a39
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerPauseStateUnitTest.java
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+
+package com.android.mediaframeworktest.unit;
+
+import android.media.MediaPlayer;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+
+/**
+ * Unit test class to test the set of valid and invalid states that
+ * MediaPlayer.pause() method can be called.
+ */          
+public class MediaPlayerPauseStateUnitTest extends AndroidTestCase implements MediaPlayerMethodUnderTest {
+    private MediaPlayerStateUnitTestTemplate mTestTemplate = new MediaPlayerStateUnitTestTemplate();
+
+    /**
+     * 1. It is valid to call pause() in the following states:
+     *    {Started, Paused}.
+     * 2. It is invalid to call pause() in the following states:
+     *    {Idle, Initialized, Prepared, Stopped, PlaybackCompleted, Error}
+     *    
+     * @param stateErrors the MediaPlayerStateErrors to check against.
+     */
+    public void checkStateErrors(MediaPlayerStateErrors stateErrors) {
+        // Valid states.
+        assertTrue(!stateErrors.errorInStartedState);
+        assertTrue(!stateErrors.errorInStartedStateAfterPause);
+        assertTrue(!stateErrors.errorInPausedState);
+
+        // Invalid states.
+        assertTrue(stateErrors.errorInPreparedState);
+        assertTrue(stateErrors.errorInPreparedStateAfterStop);
+        assertTrue(stateErrors.errorInPlaybackCompletedState);
+        assertTrue(!stateErrors.errorInIdleState);  // noError() won't be called
+        assertTrue(stateErrors.errorInIdleStateAfterReset);
+        assertTrue(stateErrors.errorInInitializedState);
+        assertTrue(stateErrors.errorInStoppedState);
+        assertTrue(stateErrors.errorInErrorState);
+    }
+
+    public void invokeMethodUnderTest(MediaPlayer player) {
+        player.pause();
+    }
+
+    @LargeTest
+    public void testPause() {
+        mTestTemplate.runTestOnMethod(this);
+    }
+    
+    @Override
+    public String toString() {
+        return "pause()";
+    }
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerResetStateUnitTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerResetStateUnitTest.java
new file mode 100644
index 0000000..2497cd7
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerResetStateUnitTest.java
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+
+package com.android.mediaframeworktest.unit;
+
+import android.media.MediaPlayer;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+
+/**
+ * Unit test class to test the set of valid and invalid states that
+ * MediaPlayer.reset() method can be called.
+ */
+public class MediaPlayerResetStateUnitTest extends AndroidTestCase implements MediaPlayerMethodUnderTest {
+    private MediaPlayerStateUnitTestTemplate mTestTemplate = new MediaPlayerStateUnitTestTemplate();
+    
+    /**
+     * 1. It is valid to call reset() in the following states:
+     *    {Idle, Initialized, Prepared, Started, Paused, Stopped, PlaybackCompleted}.
+     * 2. It is invalid to call reset() in the following states:
+     *    {Error}
+     *    
+     * @param stateErrors the MediaPlayerStateErrors to check against.
+     */
+    public void checkStateErrors(MediaPlayerStateErrors stateErrors) {
+        // Valid states.
+        assertTrue(!stateErrors.errorInPreparedState);
+        assertTrue(!stateErrors.errorInPreparedStateAfterStop);
+        assertTrue(!stateErrors.errorInStartedState);
+        assertTrue(!stateErrors.errorInStartedStateAfterPause);
+        assertTrue(!stateErrors.errorInPausedState);
+        assertTrue(!stateErrors.errorInPlaybackCompletedState);
+        assertTrue(!stateErrors.errorInIdleState);
+        assertTrue(!stateErrors.errorInIdleStateAfterReset);
+        assertTrue(!stateErrors.errorInInitializedState);
+        assertTrue(!stateErrors.errorInStoppedState);
+
+        // Invalid states.
+        assertTrue(stateErrors.errorInErrorState);
+    }
+
+    public void invokeMethodUnderTest(MediaPlayer player) {
+        player.reset();
+    }
+
+    @LargeTest
+    public void testReset() {
+        mTestTemplate.runTestOnMethod(this);
+    }
+
+    @Override
+    public String toString() {
+        return "reset()";
+    }
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerSeekToStateUnitTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerSeekToStateUnitTest.java
new file mode 100644
index 0000000..46bba9b
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerSeekToStateUnitTest.java
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+
+package com.android.mediaframeworktest.unit;
+
+import android.media.MediaPlayer;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+
+/**
+ * Unit test class to test the set of valid and invalid states that
+ * MediaPlayer.seekTo() method can be called.
+ */
+public class MediaPlayerSeekToStateUnitTest extends AndroidTestCase implements MediaPlayerMethodUnderTest {
+    private MediaPlayerStateUnitTestTemplate mTestTemplate = new MediaPlayerStateUnitTestTemplate();
+ 
+    /**
+     * 1. It is valid to call seekTo() in the following states:
+     *    {Prepared, Started, Paused, PlaybackComplted}.
+     * 2. It is invalid to call seekTo() in the following states:
+     *    {Idle, Initialized, Stopped, Error}
+     *    
+     * @param stateErrors the MediaPlayerStateErrors to check against.
+     */
+    public void checkStateErrors(MediaPlayerStateErrors stateErrors) {
+        // Valid states.
+        assertTrue(!stateErrors.errorInPreparedState);
+        assertTrue(!stateErrors.errorInPreparedStateAfterStop);
+        assertTrue(!stateErrors.errorInStartedState);
+        assertTrue(!stateErrors.errorInStartedStateAfterPause);
+        assertTrue(!stateErrors.errorInPausedState);
+        assertTrue(!stateErrors.errorInPlaybackCompletedState);
+
+        // Invalid states.
+        assertTrue(!stateErrors.errorInIdleState);  // onError() won't be called
+        assertTrue(stateErrors.errorInIdleStateAfterReset);
+        assertTrue(stateErrors.errorInInitializedState);
+        assertTrue(stateErrors.errorInStoppedState);
+        assertTrue(stateErrors.errorInErrorState);
+    }
+
+    public void invokeMethodUnderTest(MediaPlayer player) {
+        player.seekTo(0);
+    }
+
+    @LargeTest
+    public void testSeekTo() {
+        mTestTemplate.runTestOnMethod(this);
+    }
+    
+    @Override
+    public String toString() {
+        return "seekTo()";
+    }
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerSetAudioStreamTypeStateUnitTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerSetAudioStreamTypeStateUnitTest.java
new file mode 100644
index 0000000..3153792
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerSetAudioStreamTypeStateUnitTest.java
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+
+package com.android.mediaframeworktest.unit;
+
+import android.media.MediaPlayer;
+import android.media.AudioManager;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+
+/**
+ * Unit test class to test the set of valid and invalid states that
+ * MediaPlayer.setAudioStreamType() method can be called.
+ */          
+public class MediaPlayerSetAudioStreamTypeStateUnitTest extends AndroidTestCase implements MediaPlayerMethodUnderTest {
+    private MediaPlayerStateUnitTestTemplate mTestTemplate = new MediaPlayerStateUnitTestTemplate();
+    
+    /**
+     * 1. It is valid to call setAudioStreamType() in the following states:
+     *    {Idle, Initialized, Stopped, Prepared, Started, Paused, PlaybackComplted}.
+     * 2. It is invalid to call setAudioStreamType() in the following states:
+     *    {Error}
+     *    
+     * @param stateErrors the MediaPlayerStateErrors to check against.
+     */
+    public void checkStateErrors(MediaPlayerStateErrors stateErrors) {
+        // Valid states.
+        assertTrue(!stateErrors.errorInIdleState);
+        assertTrue(!stateErrors.errorInIdleStateAfterReset);
+        assertTrue(!stateErrors.errorInPreparedStateAfterStop);
+        assertTrue(!stateErrors.errorInStartedState);
+        assertTrue(!stateErrors.errorInStartedStateAfterPause);
+        assertTrue(!stateErrors.errorInPausedState);
+        assertTrue(!stateErrors.errorInPreparedState);
+        assertTrue(!stateErrors.errorInPlaybackCompletedState);
+        assertTrue(!stateErrors.errorInInitializedState);
+        assertTrue(!stateErrors.errorInStoppedState);
+        
+        // Invalid states.
+        assertTrue(stateErrors.errorInErrorState);
+    }
+
+    public void invokeMethodUnderTest(MediaPlayer player) {
+        player.setAudioStreamType(AudioManager.STREAM_MUSIC);
+    }
+
+    @LargeTest
+    public void testSetAudioSystemType() {
+        mTestTemplate.runTestOnMethod(this);
+    }
+    
+    @Override
+    public String toString() {
+        return "setAudioStreamType()";
+    }
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerSetLoopingStateUnitTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerSetLoopingStateUnitTest.java
new file mode 100644
index 0000000..17c9d8c
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerSetLoopingStateUnitTest.java
@@ -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.
+ */
+
+package com.android.mediaframeworktest.unit;
+
+import android.media.MediaPlayer;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+
+/**
+ * Unit test class to test the set of valid and invalid states that
+ * MediaPlayer.setLooping() method can be called.
+ */          
+public class MediaPlayerSetLoopingStateUnitTest extends AndroidTestCase implements MediaPlayerMethodUnderTest {
+    private MediaPlayerStateUnitTestTemplate mTestTemplate = new MediaPlayerStateUnitTestTemplate();
+    private boolean looping = false;
+    
+    /**
+     * 1. It is valid to call setLooping() in the following states:
+     *    {Idle, Initialized, Stopped, Prepared, Started, Paused, PlaybackComplted}.
+     * 2. It is invalid to call setLooping() in the following states:
+     *    {Error}
+     *    
+     * @param stateErrors the MediaPlayerStateErrors to check against.
+     */
+    public void checkStateErrors(MediaPlayerStateErrors stateErrors) {
+        // Valid states.
+        assertTrue(!stateErrors.errorInStartedState);
+        assertTrue(!stateErrors.errorInStartedStateAfterPause);
+        assertTrue(!stateErrors.errorInPausedState);
+        assertTrue(!stateErrors.errorInPreparedState);
+        assertTrue(!stateErrors.errorInPreparedStateAfterStop);
+        assertTrue(!stateErrors.errorInPlaybackCompletedState);
+        assertTrue(!stateErrors.errorInIdleStateAfterReset);
+        assertTrue(!stateErrors.errorInInitializedState);
+        assertTrue(!stateErrors.errorInStoppedState);
+        assertTrue(!stateErrors.errorInIdleState);
+        
+        // Invalid states.
+        assertTrue(stateErrors.errorInErrorState);
+    }
+
+    public void invokeMethodUnderTest(MediaPlayer player) {
+        looping = !looping;  // Flip the looping mode.
+        player.setLooping(looping);
+    }
+
+    @LargeTest
+    public void testSetLooping() {
+        mTestTemplate.runTestOnMethod(this);
+    }
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerSetVolumeStateUnitTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerSetVolumeStateUnitTest.java
new file mode 100644
index 0000000..a149565
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerSetVolumeStateUnitTest.java
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+
+package com.android.mediaframeworktest.unit;
+
+import android.media.MediaPlayer;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+
+/**
+ * Unit test class to test the set of valid and invalid states that
+ * MediaPlayer.setVolume() method can be called.
+ */          
+public class MediaPlayerSetVolumeStateUnitTest extends AndroidTestCase implements MediaPlayerMethodUnderTest {
+    private MediaPlayerStateUnitTestTemplate mTestTemplate = new MediaPlayerStateUnitTestTemplate();
+
+    /**
+     * 1. It is valid to call setVolume() in the following states:
+     *    {Idle, Initialized, Stopped, Prepared, Started, Paused, PlaybackComplted}.
+     * 2. It is invalid to call setVolume() in the following states:
+     *    {Error}
+     *    
+     * @param stateErrors the MediaPlayerStateErrors to check against.
+     */
+    public void checkStateErrors(MediaPlayerStateErrors stateErrors) {
+        // Valid states.
+        assertTrue(!stateErrors.errorInStartedState);
+        assertTrue(!stateErrors.errorInStartedStateAfterPause);
+        assertTrue(!stateErrors.errorInPausedState);
+        assertTrue(!stateErrors.errorInPreparedState);
+        assertTrue(!stateErrors.errorInPreparedStateAfterStop);
+        assertTrue(!stateErrors.errorInPlaybackCompletedState);
+        assertTrue(!stateErrors.errorInIdleStateAfterReset);
+        assertTrue(!stateErrors.errorInInitializedState);
+        assertTrue(!stateErrors.errorInStoppedState);
+        assertTrue(!stateErrors.errorInIdleState);
+        
+        // Invalid states.
+        assertTrue(stateErrors.errorInErrorState);
+    }
+
+    public void invokeMethodUnderTest(MediaPlayer player) {
+        player.setVolume(0.5f, 0.5f);
+    }
+
+    @LargeTest
+    public void testSetVolume() {
+        mTestTemplate.runTestOnMethod(this);
+    }
+    
+    @Override
+    public String toString() {
+        return "setVolume()";
+    }
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerStartStateUnitTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerStartStateUnitTest.java
new file mode 100644
index 0000000..6debbb4
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerStartStateUnitTest.java
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+
+package com.android.mediaframeworktest.unit;
+
+import android.media.MediaPlayer;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+
+/**
+ * Unit test class to test the set of valid and invalid states that
+ * MediaPlayer.start() method can be called.
+ */
+public class MediaPlayerStartStateUnitTest extends AndroidTestCase implements MediaPlayerMethodUnderTest {
+    private MediaPlayerStateUnitTestTemplate mTestTemplate = new MediaPlayerStateUnitTestTemplate();
+
+    /**
+     * 1. It is valid to call start() in the following states:
+     *    {Prepared, Started, Paused, PlaybackComplted}.
+     * 2. It is invalid to call start() in the following states:
+     *    {Idle, Initialized, Stopped, Error}
+     *    
+     * @param stateErrors the MediaPlayerStateErrors to check against.
+     */
+    public void checkStateErrors(MediaPlayerStateErrors stateErrors) {
+        // Valid states.
+        assertTrue(!stateErrors.errorInPreparedState);
+        assertTrue(!stateErrors.errorInPreparedStateAfterStop);
+        assertTrue(!stateErrors.errorInStartedState);
+        assertTrue(!stateErrors.errorInStartedStateAfterPause);
+        assertTrue(!stateErrors.errorInPausedState);
+        assertTrue(!stateErrors.errorInPlaybackCompletedState);
+        
+        // Invalid states.
+        assertTrue(!stateErrors.errorInIdleState);  // onError() won't be called
+        assertTrue(stateErrors.errorInErrorState);
+        assertTrue(stateErrors.errorInIdleStateAfterReset);
+        assertTrue(stateErrors.errorInInitializedState);
+        assertTrue(stateErrors.errorInStoppedState);
+    }
+
+    public void invokeMethodUnderTest(MediaPlayer player) {
+        player.start();
+    }
+
+    @LargeTest
+    public void testStart() {
+        mTestTemplate.runTestOnMethod(this);
+    }
+
+    @Override
+    public String toString() {
+        return "start()";
+    }
+
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerStateErrors.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerStateErrors.java
new file mode 100644
index 0000000..5be6fe3
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerStateErrors.java
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+package com.android.mediaframeworktest.unit;
+
+class MediaPlayerStateErrors {
+    public static final int MEDIA_PLAYER_ERROR = 100;
+    public static enum MediaPlayerState {
+        IDLE,
+        IDLE_AFTER_RESET,
+        INITIALIZED,
+        PREPARED,
+        PREPARED_AFTER_STOP,
+        STARTED,
+        STARTED_AFTER_PAUSE,
+        PAUSED,
+        STOPPED,
+        PLAYBACK_COMPLETED,
+        ERROR,
+    }
+    
+    // Error occurs in the states below?
+    public boolean errorInIdleState = false;
+    public boolean errorInIdleStateAfterReset = false;
+    public boolean errorInInitializedState = false;
+    public boolean errorInPreparedState = false;
+    public boolean errorInStartedState = false;
+    public boolean errorInPausedState = false;
+    public boolean errorInStartedStateAfterPause = false;
+    public boolean errorInStoppedState = false;
+    public boolean errorInPreparedStateAfterStop = false;
+    public boolean errorInPlaybackCompletedState = false;
+    public boolean errorInErrorState = false;
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerStateUnitTestTemplate.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerStateUnitTestTemplate.java
new file mode 100644
index 0000000..6abfbb2
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerStateUnitTestTemplate.java
@@ -0,0 +1,506 @@
+/*
+ * 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.
+ */
+
+package com.android.mediaframeworktest.unit;
+
+import android.util.Log;
+import android.os.Looper;
+import android.os.Handler;
+import android.os.Message;
+import android.media.MediaPlayer;
+import android.test.AndroidTestCase;
+import com.android.mediaframeworktest.MediaNames;
+
+/**
+ * A template class for running a method under test in all possible
+ * states of a MediaPlayer object.
+ * 
+ * @see com.android.mediaframeworktest.unit.MediaPlayerSeekToStateUnitTest
+ * for an example of using this class.
+ * 
+ * A typical concrete unit test class would implement the 
+ * MediaPlayerMethodUnderTest interface and have a reference to an object of
+ * this class. Then it calls runTestOnMethod() to actually perform the unit
+ * tests.
+ * 
+ */
+class MediaPlayerStateUnitTestTemplate extends AndroidTestCase {
+    private static final String TEST_PATH = MediaNames.TEST_PATH_1;
+    private static final String TAG = "MediaPlayerSeekToStateUnitTest";
+    private static final int SEEK_TO_END  = 135110;  // Milliseconds.
+    private static int WAIT_FOR_COMMAND_TO_COMPLETE = 1000;  // Milliseconds.
+    
+    private MediaPlayerStateErrors mStateErrors = new MediaPlayerStateErrors();
+    private MediaPlayer mMediaPlayer = null;
+    private boolean mInitialized = false;
+    private boolean mOnCompletionHasBeenCalled = false;
+    private MediaPlayerStateErrors.MediaPlayerState mMediaPlayerState = null;
+    private Looper mLooper = null;
+    private final Object lock = new Object();
+    private MediaPlayerMethodUnderTest mMethodUnderTest = null;
+    
+    // An Handler object is absolutely necessary for receiving callback 
+    // messages from MediaPlayer objects.
+    private Handler mHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            /*
+            switch(msg.what) {
+                case MediaPlayerStateErrors.MEDIA_PLAYER_ERROR:
+                    Log.v(TAG, "handleMessage: received MEDIA_PLAYER_ERROR message");
+                    break;
+                default:
+                    Log.v(TAG, "handleMessage: received unknown message");
+                break;
+            }
+            */
+        }
+    };
+    
+    /**
+     * Runs the given method under test in all possible states of a MediaPlayer
+     * object.
+     * 
+     * @param testMethod the method under test.
+     */
+    public void runTestOnMethod(MediaPlayerMethodUnderTest testMethod) {
+        mMethodUnderTest = testMethod;
+        if (mMethodUnderTest != null) {  // Method under test has been set?
+            initializeMessageLooper();
+            synchronized(lock) {
+                try {
+                    lock.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
+                } catch(Exception e) {
+                    Log.v(TAG, "runTestOnMethod: wait was interrupted.");
+                }
+            }
+            assertTrue(mInitialized);  // mMediaPlayer has been initialized?
+            checkMethodUnderTestInAllPossibleStates();
+            terminateMessageLooper();   // Release message looper thread.
+            assertTrue(mOnCompletionHasBeenCalled);
+            mMethodUnderTest.checkStateErrors(mStateErrors);
+            cleanUp();
+        }
+    }
+    
+    /*
+     * Initializes the message looper so that the MediaPlayer object can 
+     * receive the callback messages.
+     */
+    private void initializeMessageLooper() {
+        new Thread() {
+            @Override
+            public void run() {
+                // Set up a looper to be used by mMediaPlayer.
+                Looper.prepare();
+
+                // Save the looper so that we can terminate this thread 
+                // after we are done with it.
+                mLooper = Looper.myLooper();
+                
+                mMediaPlayer = new MediaPlayer();                
+                mMediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
+                    public boolean onError(MediaPlayer player, int what, int extra) {
+                        Log.v(TAG, "onError has been called.");
+                        synchronized(lock) {
+                            Log.v(TAG, "notify lock.");
+                            setStateError(mMediaPlayerState, true);
+                            if (mMediaPlayerState != MediaPlayerStateErrors.MediaPlayerState.ERROR) {
+                                notifyStateError();
+                            }
+                            lock.notify();
+                        }
+                        return true;
+                    }
+                });
+                mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
+                    public void onCompletion(MediaPlayer player) {
+                        Log.v(TAG, "onCompletion has been called.");
+                        synchronized(lock) {
+                            if (mMediaPlayerState == MediaPlayerStateErrors.MediaPlayerState.PLAYBACK_COMPLETED) {
+                                mOnCompletionHasBeenCalled = true;
+                            }
+                            lock.notify();
+                        }
+                    }
+                });
+                synchronized(lock) {
+                    mInitialized = true;
+                    lock.notify();
+                }
+                Looper.loop();  // Blocks forever until Looper.quit() is called.
+                Log.v(TAG, "initializeMessageLooper: quit.");
+            }
+        }.start();
+    }
+    
+    /*
+     * Calls method under test in the given state of the MediaPlayer object.
+     * 
+     * @param state the MediaPlayer state in which the method under test is called.
+     */
+    private void callMediaPlayerMethodUnderTestInState(MediaPlayerStateErrors.MediaPlayerState state) {
+        Log.v(TAG, "call " + mMethodUnderTest + ": started in state " + state);
+        setMediaPlayerToState(state);
+        mMethodUnderTest.invokeMethodUnderTest(mMediaPlayer);
+        synchronized(lock) {
+            try {
+                lock.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
+           } catch(Exception e) {
+               Log.v(TAG, "callMediaPlayerMethodUnderTestInState: wait is interrupted in state " + state);
+           }
+        }
+        Log.v(TAG, "call " + mMethodUnderTest + ": ended in state " + state);
+    }
+
+    /*
+     * The following setMediaPlayerToXXXStateXXX methods sets the MediaPlayer
+     * object to the corresponding state, given the assumption that reset()
+     * always resets the MediaPlayer object to Idle (after reset) state. 
+     */
+    private void setMediaPlayerToIdleStateAfterReset() {
+        try {
+            mMediaPlayer.reset();
+            mMediaPlayer.setDataSource(TEST_PATH);
+            mMediaPlayer.prepare();
+            mMediaPlayer.reset();
+        } catch(Exception e) {
+            Log.v(TAG, "setMediaPlayerToIdleStateAfterReset: Exception " + e.getClass().getName() + " was thrown.");
+            assertTrue(false);
+        }
+    }
+    
+    private void setMediaPlayerToInitializedState() {
+        try {
+            mMediaPlayer.reset();
+            mMediaPlayer.setDataSource(TEST_PATH);
+        } catch(Exception e) {
+            Log.v(TAG, "setMediaPlayerToInitializedState: Exception " + e.getClass().getName() + " was thrown.");
+            assertTrue(false);
+        }
+    }
+    
+    private void setMediaPlayerToPreparedState() {
+        try {
+            mMediaPlayer.reset();
+            mMediaPlayer.setDataSource(TEST_PATH);
+            mMediaPlayer.prepare();
+        } catch(Exception e) {
+            Log.v(TAG, "setMediaPlayerToPreparedState: Exception " + e.getClass().getName() + " was thrown.");
+            assertTrue(false);
+        }
+    }
+    
+    private void setMediaPlayerToPreparedStateAfterStop() {
+        try {
+            mMediaPlayer.reset();
+            mMediaPlayer.setDataSource(TEST_PATH);
+            mMediaPlayer.prepare();
+            mMediaPlayer.start();
+            mMediaPlayer.stop();
+            mMediaPlayer.prepare();
+        } catch(Exception e) {
+            Log.v(TAG, "setMediaPlayerToPreparedStateAfterStop: Exception " + e.getClass().getName() + " was thrown.");
+            assertTrue(false);
+        }
+    }
+    
+    private void setMediaPlayerToStartedState() {
+        try {
+            mMediaPlayer.reset();
+            mMediaPlayer.setDataSource(TEST_PATH);
+            mMediaPlayer.prepare();
+            mMediaPlayer.start();
+        } catch(Exception e) {
+            Log.v(TAG, "setMediaPlayerToStartedState: Exception " + e.getClass().getName() + " was thrown.");
+            assertTrue(false);
+        }
+    }
+    
+    private void setMediaPlayerToStartedStateAfterPause() {
+        try {
+            mMediaPlayer.reset();
+            mMediaPlayer.setDataSource(TEST_PATH);
+            mMediaPlayer.prepare();
+            mMediaPlayer.start();
+            mMediaPlayer.pause();
+
+            // pause() is an asynchronous call and returns immediately, but 
+            // PV player engine may take quite a while to actually set the 
+            // player state to Paused; if we call start() right after pause() 
+            // without waiting, start() may fail.
+            try {
+                Thread.sleep(MediaNames.PAUSE_WAIT_TIME);
+            } catch(Exception ie) {
+                Log.v(TAG, "sleep was interrupted and terminated prematurely");
+            }
+
+            mMediaPlayer.start();
+        } catch(Exception e) {
+            Log.v(TAG, "setMediaPlayerToStartedStateAfterPause: Exception " + e.getClass().getName() + " was thrown.");
+            assertTrue(false);
+        }
+    }
+    
+    private void setMediaPlayerToPausedState() {
+        try {
+            mMediaPlayer.reset();
+            mMediaPlayer.setDataSource(TEST_PATH);
+            mMediaPlayer.prepare();
+            mMediaPlayer.start();
+            mMediaPlayer.pause();
+        } catch(Exception e) {
+            Log.v(TAG, "setMediaPlayerToPausedState: Exception " + e.getClass().getName() + " was thrown.");
+            assertTrue(false);
+        }
+    }
+    
+    private void setMediaPlayerToStoppedState() {
+        try {
+            mMediaPlayer.reset();
+            mMediaPlayer.setDataSource(TEST_PATH);
+            mMediaPlayer.prepare();
+            mMediaPlayer.start();
+            mMediaPlayer.stop();
+        } catch(Exception e) {
+            Log.v(TAG, "setMediaPlayerToStoppedState: Exception " + e.getClass().getName() + " was thrown.");
+            assertTrue(false);
+        }
+    }
+    
+    private void setMediaPlayerToPlaybackCompletedState() {
+        try {
+            mMediaPlayer.reset();
+            mMediaPlayer.setDataSource(TEST_PATH);
+            mMediaPlayer.prepare();
+            mMediaPlayer.seekTo(SEEK_TO_END);
+            mMediaPlayer.start();
+            synchronized(lock) {
+                try {
+                    lock.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
+                } catch(Exception e) {
+                    Log.v(TAG, "setMediaPlayerToPlaybackCompletedState: wait was interrupted.");
+                }
+            }
+        } catch(Exception e) {
+            Log.v(TAG, "setMediaPlayerToPlaybackCompletedState: Exception " + e.getClass().getName() + " was thrown.");
+            assertTrue(false);
+        }
+        Log.v(TAG, "setMediaPlayerToPlaybackCompletedState: done.");
+    }
+    
+    /*
+     * There are a lot of ways to force the MediaPlayer object to enter
+     * the Error state. The impact (such as onError is called or not) highly 
+     * depends on how the Error state is entered.
+     */
+    private void setMediaPlayerToErrorState() {
+        try {
+            mMediaPlayer.reset();
+            mMediaPlayer.setDataSource(TEST_PATH);
+            mMediaPlayer.start();
+            synchronized(lock) {
+                try {
+                    lock.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
+                } catch(Exception e) {
+                    Log.v(TAG, "setMediaPlayerToErrorState: wait was interrupted.");
+                }
+            }
+        } catch(Exception e) {
+            Log.v(TAG, "setMediaPlayerToErrorState: Exception " + e.getClass().getName() + " was thrown.");
+            assertTrue(e instanceof IllegalStateException);
+        }
+        Log.v(TAG, "setMediaPlayerToErrorState: done.");
+    }
+    
+    /*
+     * Sets the state of the MediaPlayer object to the specified one.
+     * 
+     * @param state the state of the MediaPlayer object.
+     */
+    private void setMediaPlayerToState(MediaPlayerStateErrors.MediaPlayerState state) {
+        mMediaPlayerState = state;
+        switch(state) {
+            case IDLE:
+                // Does nothing.
+                break;
+            case IDLE_AFTER_RESET:
+                setMediaPlayerToIdleStateAfterReset();
+                break;
+            case INITIALIZED:
+                setMediaPlayerToInitializedState();
+                break;
+            case PREPARED:
+                setMediaPlayerToPreparedState();
+                break;
+            case PREPARED_AFTER_STOP:
+                setMediaPlayerToPreparedStateAfterStop();
+                break;
+            case STARTED:
+                setMediaPlayerToStartedState();
+                break;
+            case STARTED_AFTER_PAUSE:
+                setMediaPlayerToStartedStateAfterPause();
+                break;
+            case PAUSED:
+                setMediaPlayerToPausedState();
+                break;
+            case STOPPED:
+                setMediaPlayerToStoppedState();
+                break;
+            case PLAYBACK_COMPLETED:
+                setMediaPlayerToPlaybackCompletedState();
+                break;
+            case ERROR:
+                setMediaPlayerToErrorState();
+                break;
+        }
+    }
+    
+    /*
+     * Sets the error value of the corresponding state to the given error.
+     * 
+     * @param state the state of the MediaPlayer object.
+     * @param error the value of the state error to be set.
+     */
+    private void setStateError(MediaPlayerStateErrors.MediaPlayerState state, boolean error) {
+        switch(state) {
+            case IDLE:
+                mStateErrors.errorInIdleState = error;
+                break;
+            case IDLE_AFTER_RESET:
+                mStateErrors.errorInIdleStateAfterReset = error;
+                break;
+            case INITIALIZED:
+                mStateErrors.errorInInitializedState = error;
+                break;
+            case PREPARED:
+                mStateErrors.errorInPreparedState = error;
+                break;
+            case PREPARED_AFTER_STOP:
+                mStateErrors.errorInPreparedStateAfterStop = error;
+                break;
+            case STARTED:
+                mStateErrors.errorInStartedState = error;
+                break;
+            case STARTED_AFTER_PAUSE:
+                mStateErrors.errorInStartedStateAfterPause = error;
+                break;
+            case PAUSED:
+                mStateErrors.errorInPausedState = error;
+                break;
+            case STOPPED:
+                mStateErrors.errorInStoppedState = error;
+                break;
+            case PLAYBACK_COMPLETED:
+                mStateErrors.errorInPlaybackCompletedState = error;
+                break;
+            case ERROR:
+                mStateErrors.errorInErrorState = error;
+                break;
+        }
+    }
+    
+    private void notifyStateError() {
+        mHandler.sendMessage(mHandler.obtainMessage(MediaPlayerStateErrors.MEDIA_PLAYER_ERROR));
+    }
+
+    private void checkIdleState() {
+        callMediaPlayerMethodUnderTestInState(MediaPlayerStateErrors.MediaPlayerState.IDLE);
+    }
+    
+    private void checkIdleStateAfterReset() {
+        callMediaPlayerMethodUnderTestInState(MediaPlayerStateErrors.MediaPlayerState.IDLE_AFTER_RESET);
+    }
+    
+    private void checkInitializedState() {
+        callMediaPlayerMethodUnderTestInState(MediaPlayerStateErrors.MediaPlayerState.INITIALIZED);
+    }
+    
+    private void checkPreparedState() {
+        callMediaPlayerMethodUnderTestInState(MediaPlayerStateErrors.MediaPlayerState.PREPARED);
+    }
+    
+    private void checkPreparedStateAfterStop() {
+        callMediaPlayerMethodUnderTestInState(MediaPlayerStateErrors.MediaPlayerState.PREPARED_AFTER_STOP);
+    }
+    
+    private void checkStartedState() {
+        callMediaPlayerMethodUnderTestInState(MediaPlayerStateErrors.MediaPlayerState.STARTED);
+    }
+    
+    private void checkPausedState() {
+        callMediaPlayerMethodUnderTestInState(MediaPlayerStateErrors.MediaPlayerState.PAUSED);
+    }
+    
+    private void checkStartedStateAfterPause() {
+        callMediaPlayerMethodUnderTestInState(MediaPlayerStateErrors.MediaPlayerState.STARTED_AFTER_PAUSE);
+    }
+    
+    private void checkStoppedState() {
+        callMediaPlayerMethodUnderTestInState(MediaPlayerStateErrors.MediaPlayerState.STOPPED);
+    }
+    
+    private void checkPlaybackCompletedState() {
+        callMediaPlayerMethodUnderTestInState(MediaPlayerStateErrors.MediaPlayerState.PLAYBACK_COMPLETED);
+    }
+    
+    private void checkErrorState() {
+        callMediaPlayerMethodUnderTestInState(MediaPlayerStateErrors.MediaPlayerState.ERROR);
+    }
+
+    /*
+     * Checks the given method under test in all possible states of the MediaPlayer object.
+     */
+    private void checkMethodUnderTestInAllPossibleStates() {
+        // Must be called first.
+        checkIdleState(); 
+        
+        // The sequence of the following method calls should not 
+        // affect the test results.
+        checkErrorState();
+        checkIdleStateAfterReset();
+        checkInitializedState();
+        checkStartedState();
+        checkStartedStateAfterPause();
+        checkPausedState();
+        checkPreparedState();
+        
+        checkPreparedStateAfterStop();
+        
+        checkPlaybackCompletedState();
+        checkStoppedState();
+    }
+    
+    /*
+     * Terminates the message looper thread.
+     */
+    private void terminateMessageLooper() {
+        mLooper.quit();
+        mMediaPlayer.release();
+    }
+    
+    /*
+     * Cleans up all the internal object references.
+     */
+    private void cleanUp() {
+        mMediaPlayer = null;
+        mMediaPlayerState = null;
+        mLooper = null;
+        mStateErrors = null;
+        mMethodUnderTest = null;
+    }
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerStopStateUnitTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerStopStateUnitTest.java
new file mode 100644
index 0000000..3427f86
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerStopStateUnitTest.java
@@ -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.
+ */
+
+package com.android.mediaframeworktest.unit;
+
+import android.media.MediaPlayer;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+
+/**
+ * Unit test class to test the set of valid and invalid states that
+ * MediaPlayer.stop() method can be called.
+ */          
+public class MediaPlayerStopStateUnitTest extends AndroidTestCase implements MediaPlayerMethodUnderTest {
+    private MediaPlayerStateUnitTestTemplate mTestTemplate = new MediaPlayerStateUnitTestTemplate();
+
+    /**
+     * 1. It is valid to call stop() in the following states:
+     *    {Prepared, Started, Stopped, Paused, PlaybackCompleted}.
+     * 2. It is invalid to call stop() in the following states:
+     *    {Idle, Initialized, Error}
+     *    
+     * @param stateErrors the MediaPlayerStateErrors to check against.
+     */
+    public void checkStateErrors(MediaPlayerStateErrors stateErrors) {
+        // Valid states.
+        assertTrue(!stateErrors.errorInStartedState);
+        assertTrue(!stateErrors.errorInStartedStateAfterPause);
+        assertTrue(!stateErrors.errorInStoppedState);
+        assertTrue(!stateErrors.errorInPreparedState);
+        assertTrue(!stateErrors.errorInPreparedStateAfterStop);
+        assertTrue(!stateErrors.errorInPlaybackCompletedState);
+        assertTrue(!stateErrors.errorInPausedState);
+        
+        // Invalid states.
+        assertTrue(!stateErrors.errorInIdleState);  // noError() won't be called
+        assertTrue(stateErrors.errorInIdleStateAfterReset);
+        assertTrue(stateErrors.errorInInitializedState);
+        assertTrue(stateErrors.errorInErrorState);
+    }
+
+    public void invokeMethodUnderTest(MediaPlayer player) {
+        player.stop();
+    }
+
+    @LargeTest
+    public void testStop() {
+        mTestTemplate.runTestOnMethod(this);
+    }
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderMethodUnderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderMethodUnderTest.java
new file mode 100644
index 0000000..3f46f74
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderMethodUnderTest.java
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+
+package com.android.mediaframeworktest.unit;
+
+import android.media.MediaRecorder;
+
+/**
+ * All MediaRecorder method unit test subclass must implement this interface. 
+ */
+interface MediaRecorderMethodUnderTest {
+    public void checkStateErrors(MediaRecorderStateErrors stateErrors);
+    public void invokeMethodUnderTest(MediaRecorder player);
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderPrepareStateUnitTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderPrepareStateUnitTest.java
new file mode 100644
index 0000000..134144d
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderPrepareStateUnitTest.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.mediaframeworktest.unit;
+
+import android.media.MediaRecorder;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.suitebuilder.annotation.Suppress;
+import java.io.IOException;
+
+/**
+ * Unit test class to test the set of valid and invalid states that
+ * MediaRecorder.prepare() method can be called.
+ */
+public class MediaRecorderPrepareStateUnitTest extends AndroidTestCase implements MediaRecorderMethodUnderTest {
+    private MediaRecorderStateUnitTestTemplate mTestTemplate = new MediaRecorderStateUnitTestTemplate();
+    
+    /**
+     * 1. It is valid to call prepare() in the following states:
+     *    {DataSourceConfigured}.
+     * 2. It is invalid to call prepare() in the following states:
+     *    {Prepared, Initial, Initialized, Recording, Error}
+     *    
+     * @param stateErrors the MediaRecorderStateErrors to check against.
+     */
+    public void checkStateErrors(MediaRecorderStateErrors stateErrors) {
+        // Valid states.
+        assertTrue(!stateErrors.errorInDataSourceConfiguredState);
+        
+        // Invalid states.
+        assertTrue(stateErrors.errorInPreparedState);
+        assertTrue(stateErrors.errorInRecordingState);
+        assertTrue(stateErrors.errorInInitialState);
+        assertTrue(stateErrors.errorInInitialStateAfterReset);
+        assertTrue(stateErrors.errorInInitialStateAfterStop);
+        assertTrue(stateErrors.errorInInitializedState);
+        assertTrue(stateErrors.errorInErrorState);
+    }
+
+    public void invokeMethodUnderTest(MediaRecorder recorder) {
+        try {
+            recorder.prepare();
+        } catch (IOException exception) {
+            throw new RuntimeException();
+        }
+    }
+
+    @MediumTest
+    public void testPrepare() {
+        mTestTemplate.runTestOnMethod(this);
+    }
+    
+    @Override
+    public String toString() {
+        return "prepare()";
+    }
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderResetStateUnitTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderResetStateUnitTest.java
new file mode 100644
index 0000000..cae9e31
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderResetStateUnitTest.java
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+
+package com.android.mediaframeworktest.unit;
+
+import android.media.MediaRecorder;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.suitebuilder.annotation.Suppress;
+
+/**
+ * Unit test class to test the set of valid and invalid states that
+ * MediaRecorder.reset() method can be called.
+ */
+public class MediaRecorderResetStateUnitTest extends AndroidTestCase implements MediaRecorderMethodUnderTest {
+    private MediaRecorderStateUnitTestTemplate mTestTemplate = new MediaRecorderStateUnitTestTemplate();
+    
+    /**
+     * 1. It is valid to call reset() in the following states:
+     *    {Prepared, Initial, Initialized, DataSourceConfigured, Recording, Error}.
+     * 2. It is invalid to call reset() in the following states:
+     *    {}
+     *    
+     * @param stateErrors the MediaRecorderStateErrors to check against.
+     */
+    public void checkStateErrors(MediaRecorderStateErrors stateErrors) {
+        // Valid states.
+        assertTrue(!stateErrors.errorInPreparedState);
+        assertTrue(!stateErrors.errorInRecordingState);
+        assertTrue(!stateErrors.errorInInitialState);
+        assertTrue(!stateErrors.errorInInitialStateAfterReset);
+        assertTrue(!stateErrors.errorInInitialStateAfterStop);
+        assertTrue(!stateErrors.errorInInitializedState);
+        assertTrue(!stateErrors.errorInErrorState);
+        assertTrue(!stateErrors.errorInDataSourceConfiguredState);
+        
+        // Invalid states.
+    }
+
+    public void invokeMethodUnderTest(MediaRecorder recorder) {
+        recorder.reset();
+    }
+
+    @MediumTest
+    public void testReset() {
+        mTestTemplate.runTestOnMethod(this);
+    }
+    
+    @Override
+    public String toString() {
+        return "reset()";
+    }
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderSetAudioEncoderStateUnitTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderSetAudioEncoderStateUnitTest.java
new file mode 100644
index 0000000..4b5a818
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderSetAudioEncoderStateUnitTest.java
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+
+package com.android.mediaframeworktest.unit;
+
+import android.media.MediaRecorder;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.suitebuilder.annotation.Suppress;
+
+/**
+ * Unit test class to test the set of valid and invalid states that
+ * MediaRecorder.setAudioEncoder() method can be called.
+ */
+public class MediaRecorderSetAudioEncoderStateUnitTest extends AndroidTestCase implements MediaRecorderMethodUnderTest {
+    private MediaRecorderStateUnitTestTemplate mTestTemplate = new MediaRecorderStateUnitTestTemplate();
+    
+    /**
+     * 1. It is valid to call setAudioEncoder() in the following states:
+     *    {DataSourceConfigured}.
+     * 2. It is invalid to call setAudioEncoder() in the following states:
+     *    {Initial, Initialized, Prepared, Recording, Error}
+     *    
+     * @param stateErrors the MediaRecorderStateErrors to check against.
+     */
+    public void checkStateErrors(MediaRecorderStateErrors stateErrors) {
+        // Valid states.
+        assertTrue(!stateErrors.errorInDataSourceConfiguredState);
+        
+        // Invalid states.
+        assertTrue(stateErrors.errorInPreparedState);
+        assertTrue(stateErrors.errorInRecordingState);
+        assertTrue(stateErrors.errorInErrorState);
+        assertTrue(stateErrors.errorInInitialState);
+        assertTrue(stateErrors.errorInInitialStateAfterReset);
+        assertTrue(stateErrors.errorInInitialStateAfterStop);
+        assertTrue(stateErrors.errorInInitializedState);
+    }
+
+    public void invokeMethodUnderTest(MediaRecorder recorder) {
+        recorder.setAudioEncoder(MediaRecorderStateUnitTestTemplate.AUDIO_ENCODER);
+    }
+
+    @MediumTest
+    public void testSetAudioEncoder() {
+        mTestTemplate.runTestOnMethod(this);
+    }
+    
+    @Override
+    public String toString() {
+        return "setAudioEncoder()";
+    }
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderSetAudioSourceStateUnitTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderSetAudioSourceStateUnitTest.java
new file mode 100644
index 0000000..f8ab48cf
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderSetAudioSourceStateUnitTest.java
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+
+package com.android.mediaframeworktest.unit;
+
+import android.media.MediaRecorder;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.suitebuilder.annotation.Suppress;
+
+/**
+ * Unit test class to test the set of valid and invalid states that
+ * MediaRecorder.setAudioSource() method can be called.
+ */
+public class MediaRecorderSetAudioSourceStateUnitTest extends AndroidTestCase implements MediaRecorderMethodUnderTest {
+    private MediaRecorderStateUnitTestTemplate mTestTemplate = new MediaRecorderStateUnitTestTemplate();
+    
+    /**
+     * 1. It is valid to call setAudioSource() in the following states:
+     *    {Initial, Initialized}.
+     * 2. It is invalid to call setAudioSource() in the following states:
+     *    {Prepared, DataSourceConfigured, Recording, Error}
+     *    
+     * @param stateErrors the MediaRecorderStateErrors to check against.
+     */
+    public void checkStateErrors(MediaRecorderStateErrors stateErrors) {
+        // Valid states.
+        assertTrue(!stateErrors.errorInInitialState);
+        assertTrue(!stateErrors.errorInInitialStateAfterReset);
+        assertTrue(!stateErrors.errorInInitialStateAfterStop);
+        assertTrue(!stateErrors.errorInInitializedState);
+        
+        // Invalid states.
+        assertTrue(stateErrors.errorInPreparedState);
+        assertTrue(stateErrors.errorInRecordingState);
+        assertTrue(stateErrors.errorInDataSourceConfiguredState);
+        assertTrue(stateErrors.errorInErrorState);
+    }
+
+    public void invokeMethodUnderTest(MediaRecorder recorder) {
+        recorder.setAudioSource(MediaRecorderStateUnitTestTemplate.AUDIO_SOURCE);
+    }
+
+    @MediumTest
+    public void testSetAudioSource() {
+        mTestTemplate.runTestOnMethod(this);
+    }
+    
+    @Override
+    public String toString() {
+        return "setAudioSource()";
+    }
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderSetOutputFileStateUnitTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderSetOutputFileStateUnitTest.java
new file mode 100644
index 0000000..712a758
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderSetOutputFileStateUnitTest.java
@@ -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.
+ */
+
+package com.android.mediaframeworktest.unit;
+
+import android.media.MediaRecorder;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.suitebuilder.annotation.Suppress;
+
+/**
+ * Unit test class to test the set of valid and invalid states that
+ * MediaRecorder.setOutputFile() method can be called.
+ */
+public class MediaRecorderSetOutputFileStateUnitTest extends AndroidTestCase implements MediaRecorderMethodUnderTest {
+    private MediaRecorderStateUnitTestTemplate mTestTemplate = new MediaRecorderStateUnitTestTemplate();
+    /**
+     * 1. It is valid to call setOutputFile() in the following states:
+     *    {DataSourceConfigured, Initial, Initialized, Prepared, Recording, Error}.
+     * 2. It is invalid to call setOutputFile() in the following states:
+     *    {}
+     *    
+     * @param stateErrors the MediaRecorderStateErrors to check against.
+     */
+    public void checkStateErrors(MediaRecorderStateErrors stateErrors) {
+        // Valid states.
+        assertTrue(!stateErrors.errorInDataSourceConfiguredState);
+        assertTrue(!stateErrors.errorInPreparedState);
+        assertTrue(!stateErrors.errorInRecordingState);
+        assertTrue(!stateErrors.errorInErrorState);
+        assertTrue(!stateErrors.errorInInitialState);
+        assertTrue(!stateErrors.errorInInitialStateAfterReset);
+        assertTrue(!stateErrors.errorInInitialStateAfterStop);
+        assertTrue(!stateErrors.errorInInitializedState);
+    }
+
+    public void invokeMethodUnderTest(MediaRecorder recorder) {
+        recorder.setOutputFile(MediaRecorderStateUnitTestTemplate.RECORD_OUTPUT_PATH);
+    }
+
+    @MediumTest
+    public void testSetOutputFile() {
+        mTestTemplate.runTestOnMethod(this);
+    }
+    
+    @Override
+    public String toString() {
+        return "setOutputFile()";
+    }
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderSetOutputFormatStateUnitTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderSetOutputFormatStateUnitTest.java
new file mode 100644
index 0000000..cacdd87
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderSetOutputFormatStateUnitTest.java
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+
+package com.android.mediaframeworktest.unit;
+
+import android.media.MediaRecorder;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.suitebuilder.annotation.Suppress;
+
+/**
+ * Unit test class to test the set of valid and invalid states that
+ * MediaRecorder.setOutputFormat() method can be called.
+ */
+public class MediaRecorderSetOutputFormatStateUnitTest extends AndroidTestCase implements MediaRecorderMethodUnderTest {
+    private MediaRecorderStateUnitTestTemplate mTestTemplate = new MediaRecorderStateUnitTestTemplate();
+    
+    /**
+     * 1. It is valid to call setOutputFormat() in the following states:
+     *    {Initialized}.
+     * 2. It is invalid to call setOutputFormat() in the following states:
+     *    {Initial, Prepared, DataSourceConfigured, Recording, Error}
+     *    
+     * @param stateErrors the MediaRecorderStateErrors to check against.
+     */
+    public void checkStateErrors(MediaRecorderStateErrors stateErrors) {
+        // Valid states.
+        assertTrue(!stateErrors.errorInInitializedState);
+        
+        // Invalid states.
+        assertTrue(stateErrors.errorInInitialState);
+        assertTrue(stateErrors.errorInInitialStateAfterReset);
+        assertTrue(stateErrors.errorInInitialStateAfterStop);
+        assertTrue(stateErrors.errorInPreparedState);
+        assertTrue(stateErrors.errorInRecordingState);
+        assertTrue(stateErrors.errorInErrorState);
+        assertTrue(stateErrors.errorInDataSourceConfiguredState);
+    }
+
+    public void invokeMethodUnderTest(MediaRecorder recorder) {
+        recorder.setOutputFormat(MediaRecorderStateUnitTestTemplate.OUTPUT_FORMAT);
+    }
+
+    @MediumTest
+    public void testSetOutputFormat() {
+        mTestTemplate.runTestOnMethod(this);
+    }
+    
+    @Override
+    public String toString() {
+        return "setOutputFormat()";
+    }
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderStartStateUnitTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderStartStateUnitTest.java
new file mode 100644
index 0000000..d1232fc
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderStartStateUnitTest.java
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+
+package com.android.mediaframeworktest.unit;
+
+import android.media.MediaRecorder;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.suitebuilder.annotation.Suppress;
+
+/**
+ * Unit test class to test the set of valid and invalid states that
+ * MediaRecorder.start() method can be called.
+ */
+public class MediaRecorderStartStateUnitTest extends AndroidTestCase implements MediaRecorderMethodUnderTest {
+    private MediaRecorderStateUnitTestTemplate mTestTemplate = new MediaRecorderStateUnitTestTemplate();
+
+    /**
+     * 1. It is valid to call start() in the following states:
+     *    {Prepared}.
+     * 2. It is invalid to call start() in the following states:
+     *    {Initial, Initialized, DataSourceConfigured, Recording, Error}
+     *    
+     * @param stateErrors the MediaRecorderStateErrors to check against.
+     */
+    public void checkStateErrors(MediaRecorderStateErrors stateErrors) {
+        // Valid states.
+        assertTrue(!stateErrors.errorInPreparedState);
+        
+        // Invalid states.
+        assertTrue(stateErrors.errorInRecordingState);
+        assertTrue(stateErrors.errorInInitialState);
+        assertTrue(stateErrors.errorInInitialStateAfterReset);
+        assertTrue(stateErrors.errorInInitialStateAfterStop);
+        assertTrue(stateErrors.errorInInitializedState);
+        assertTrue(stateErrors.errorInErrorState);
+        assertTrue(stateErrors.errorInDataSourceConfiguredState);
+    }
+
+    public void invokeMethodUnderTest(MediaRecorder recorder) {
+        recorder.start();
+    }
+
+    @MediumTest
+    public void testStart() {
+        mTestTemplate.runTestOnMethod(this);
+    }
+    
+    @Override
+    public String toString() {
+        return "start()";
+    }
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderStateErrors.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderStateErrors.java
new file mode 100644
index 0000000..2d6e5a2
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderStateErrors.java
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+package com.android.mediaframeworktest.unit;
+
+class MediaRecorderStateErrors {
+    public static enum MediaRecorderState {
+        INITIAL,
+        INITIAL_AFTER_RESET,
+        INITIAL_AFTER_STOP,
+        INITIALIZED,
+        DATASOURCECONFIGURED,
+        PREPARED,
+        RECORDING,
+        ERROR,
+    }
+    
+    // Error occurs in the states below?
+    public boolean errorInInitialState = false;
+    public boolean errorInInitialStateAfterReset = false;
+    public boolean errorInInitialStateAfterStop = false;
+    public boolean errorInInitializedState = false;
+    public boolean errorInDataSourceConfiguredState = false;
+    public boolean errorInPreparedState = false;
+    public boolean errorInRecordingState = false;
+    public boolean errorInErrorState = false;
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderStateUnitTestTemplate.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderStateUnitTestTemplate.java
new file mode 100644
index 0000000..9edc9aa
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderStateUnitTestTemplate.java
@@ -0,0 +1,340 @@
+/*
+ * 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.
+ */
+
+package com.android.mediaframeworktest.unit;
+
+import android.util.Log;
+import android.media.MediaRecorder;
+import android.test.AndroidTestCase;
+
+/**
+ * A template class for running a method under test in all possible
+ * states of a MediaRecorder object.
+ * 
+ * @see com.android.mediaframeworktest.unit.MediaRecorderStopStateUnitTest
+ * for an example of using this class.
+ * 
+ * A typical concrete unit test class would implement the 
+ * MediaRecorderMethodUnderTest interface and have a reference to an object of
+ * this class. Then it calls runTestOnMethod() to actually perform the unit
+ * tests. It is recommended that the toString() method of the concrete unit test
+ * class be overridden to use the actual method name under test for logging 
+ * purpose.
+ * 
+ */
+class MediaRecorderStateUnitTestTemplate extends AndroidTestCase {
+    public static final String RECORD_OUTPUT_PATH = "/sdcard/recording.3gp";
+    public static final int OUTPUT_FORMAT= MediaRecorder.OutputFormat.THREE_GPP;
+    public static final int AUDIO_ENCODER = MediaRecorder.AudioEncoder.AMR_NB;
+    public static final int AUDIO_SOURCE = MediaRecorder.AudioSource.MIC;
+    private static final String TAG = "MediaRecorderStateUnitTest";
+    private MediaRecorderStateErrors mStateErrors = new MediaRecorderStateErrors();
+    private MediaRecorder mMediaRecorder = new MediaRecorder();
+    private MediaRecorderStateErrors.MediaRecorderState mMediaRecorderState = null;
+    private MediaRecorderMethodUnderTest mMethodUnderTest = null;
+    
+    /**
+     * Runs the given method under test in all possible states of a MediaRecorder
+     * object.
+     * 
+     * @param testMethod the method under test.
+     */
+    public void runTestOnMethod(MediaRecorderMethodUnderTest testMethod) {
+        mMethodUnderTest = testMethod;
+        if (mMethodUnderTest != null) {  // Method under test has been set?
+            checkMethodUnderTestInAllPossibleStates();
+            mMethodUnderTest.checkStateErrors(mStateErrors);
+            cleanUp();
+        }
+    }
+    
+    /*
+     * Calls method under test in the given state of the MediaRecorder object.
+     * 
+     * @param state the MediaRecorder state in which the method under test is called.
+     */
+    private void callMediaRecorderMethodUnderTestInState(MediaRecorderStateErrors.MediaRecorderState state) {
+        Log.v(TAG, "call " + mMethodUnderTest + ": started in state " + state);
+        setMediaRecorderToState(state);
+        try {
+            mMethodUnderTest.invokeMethodUnderTest(mMediaRecorder);
+        } catch(Exception e) {
+            setStateError(mMediaRecorderState, true);
+        }
+        Log.v(TAG, "call " + mMethodUnderTest + ": ended in state " + state);
+    }
+
+    /*
+     * The following setMediaRecorderToXXXStateXXX methods sets the MediaRecorder
+     * object to the corresponding state, given the assumption that reset()
+     * always resets the MediaRecorder object to Initial (after reset) state. 
+     */
+    private void setMediaRecorderToInitialStateAfterReset() {
+        try {
+            mMediaRecorder.reset();
+        } catch(Exception e) {
+            fail("setMediaRecorderToInitialStateAfterReset: Exception " + e.getClass().getName() + " was thrown.");
+        }
+    }
+
+    // FIXME:
+    // In the past, stop() == reset().
+    // However, this is no longer true. The plan is to have a STOPPED state.
+    // and from STOPPED state, start can be called without the need to
+    // do the recording configuration again. 
+    private void setMediaRecorderToInitialStateAfterStop() {
+        try {
+            mMediaRecorder.reset();
+/*
+            mMediaRecorder.setAudioSource(AUDIO_SOURCE);
+            mMediaRecorder.setOutputFormat(OUTPUT_FORMAT);
+            mMediaRecorder.setAudioEncoder(AUDIO_ENCODER);
+            mMediaRecorder.setOutputFile(RECORD_OUTPUT_PATH);
+            mMediaRecorder.prepare();
+            mMediaRecorder.start();
+            mMediaRecorder.stop();
+*/
+        } catch(Exception e) {
+            fail("setMediaRecorderToInitialStateAfterReset: Exception " + e.getClass().getName() + " was thrown.");
+        }
+    }
+    
+    private void setMediaRecorderToInitializedState() {
+        try {
+            mMediaRecorder.reset();
+            if (mMethodUnderTest.toString() != "setAudioSource()") {
+                mMediaRecorder.setAudioSource(AUDIO_SOURCE);
+            }
+        } catch(Exception e) {
+            fail("setMediaRecorderToInitializedState: Exception " + e.getClass().getName() + " was thrown.");
+        }
+    }
+    
+    private void setMediaRecorderToPreparedState() {
+        try {
+            mMediaRecorder.reset();
+            mMediaRecorder.setAudioSource(AUDIO_SOURCE);
+            mMediaRecorder.setOutputFormat(OUTPUT_FORMAT);
+            mMediaRecorder.setAudioEncoder(AUDIO_ENCODER);
+            mMediaRecorder.setOutputFile(RECORD_OUTPUT_PATH);
+            mMediaRecorder.prepare();
+        } catch(Exception e) {
+            fail("setMediaRecorderToPreparedState: Exception " + e.getClass().getName() + " was thrown.");
+        }
+    }
+    
+    private void setMediaRecorderToRecordingState() {
+        try {
+            mMediaRecorder.reset();
+            mMediaRecorder.setAudioSource(AUDIO_SOURCE);
+            mMediaRecorder.setOutputFormat(OUTPUT_FORMAT);
+            mMediaRecorder.setAudioEncoder(AUDIO_ENCODER);
+            mMediaRecorder.setOutputFile(RECORD_OUTPUT_PATH);
+            mMediaRecorder.prepare();
+            mMediaRecorder.start();
+        } catch(Exception e) {
+            fail("setMediaRecorderToRecordingState: Exception " + e.getClass().getName() + " was thrown.");
+        }
+    }
+    
+    private void setMediaRecorderToDataSourceConfiguredState() {
+        try {
+            mMediaRecorder.reset();
+            mMediaRecorder.setAudioSource(AUDIO_SOURCE);
+            mMediaRecorder.setOutputFormat(OUTPUT_FORMAT);
+            
+            /* Skip setAudioEncoder() and setOutputFile() calls if
+             * the method under test is setAudioEncoder() since this
+             * method can only be called once even in the DATASOURCECONFIGURED state
+             */
+            if (mMethodUnderTest.toString() != "setAudioEncoder()") {
+                mMediaRecorder.setAudioEncoder(AUDIO_ENCODER);
+            }
+            
+            if (mMethodUnderTest.toString() != "setOutputFile()") {
+                mMediaRecorder.setOutputFile(RECORD_OUTPUT_PATH);
+            }
+        } catch(Exception e) {
+            fail("setMediaRecorderToDataSourceConfiguredState: Exception " + e.getClass().getName() + " was thrown.");
+        }
+    }
+    
+    /*
+     * There are a lot of ways to force the MediaRecorder object to enter
+     * the Error state. We arbitrary choose one here.
+     */
+    private void setMediaRecorderToErrorState() {
+        try {
+            mMediaRecorder.reset();
+            
+            /* Skip setAudioSource() if the method under test is setAudioEncoder()
+             * Because, otherwise, it is valid to call setAudioEncoder() after
+             * start() since start() will fail, and then the mMediaRecorder 
+             * won't be set to the Error state
+             */ 
+            if (mMethodUnderTest.toString() != "setAudioEncoder()") {
+                mMediaRecorder.setAudioSource(AUDIO_SOURCE);
+            }
+            
+            /* Skip setOutputFormat if the method under test is setOutputFile()
+             *  Because, otherwise, it is valid to call setOutputFile() after
+             * start() since start() will fail, and then the mMediaRecorder 
+             * won't be set to the Error state
+             */ 
+            if (mMethodUnderTest.toString() != "setOutputFile()") {
+                mMediaRecorder.setOutputFormat(OUTPUT_FORMAT);
+            }
+            
+            mMediaRecorder.start();
+        } catch(Exception e) {
+            if (!(e instanceof IllegalStateException)) {
+                fail("setMediaRecorderToErrorState: Exception " + e.getClass().getName() + " was thrown.");
+            }
+        }
+        Log.v(TAG, "setMediaRecorderToErrorState: done.");
+    }
+    
+    /*
+     * Sets the state of the MediaRecorder object to the specified one.
+     * 
+     * @param state the state of the MediaRecorder object.
+     */
+    private void setMediaRecorderToState(MediaRecorderStateErrors.MediaRecorderState state) {
+        mMediaRecorderState = state;
+        switch(state) {
+            case INITIAL:
+                // Does nothing.
+                break;
+            case INITIAL_AFTER_RESET:
+                setMediaRecorderToInitialStateAfterReset();
+                break;
+            case INITIAL_AFTER_STOP:
+                setMediaRecorderToInitialStateAfterStop();
+                break;
+            case INITIALIZED:
+                setMediaRecorderToInitializedState();
+                break;
+            case DATASOURCECONFIGURED:
+                setMediaRecorderToDataSourceConfiguredState();
+                break;
+            case PREPARED:
+                setMediaRecorderToPreparedState();
+                break;
+            case RECORDING:
+                setMediaRecorderToRecordingState();
+                break;
+            case ERROR:
+                setMediaRecorderToErrorState();
+                break;
+        }
+    }
+    
+    /*
+     * Sets the error value of the corresponding state to the given error.
+     * 
+     * @param state the state of the MediaRecorder object.
+     * @param error the value of the state error to be set.
+     */
+    private void setStateError(MediaRecorderStateErrors.MediaRecorderState state, boolean error) {
+        switch(state) {
+            case INITIAL:
+                mStateErrors.errorInInitialState = error;
+                break;
+            case INITIAL_AFTER_RESET:
+                mStateErrors.errorInInitialStateAfterReset = error;
+                break;
+            case INITIAL_AFTER_STOP:
+                mStateErrors.errorInInitialStateAfterStop = error;
+                break;
+            case INITIALIZED:
+                mStateErrors.errorInInitializedState = error;
+                break;
+            case DATASOURCECONFIGURED:
+                mStateErrors.errorInDataSourceConfiguredState = error;
+                break;
+            case PREPARED:
+                mStateErrors.errorInPreparedState = error;
+                break;
+            case RECORDING:
+                mStateErrors.errorInRecordingState = error;
+                break;
+            case ERROR:
+                mStateErrors.errorInErrorState = error;
+                break;
+        }
+    }
+
+    private void checkInitialState() {
+        callMediaRecorderMethodUnderTestInState(MediaRecorderStateErrors.MediaRecorderState.INITIAL);
+    }
+    
+    private void checkInitialStateAfterReset() {
+        callMediaRecorderMethodUnderTestInState(MediaRecorderStateErrors.MediaRecorderState.INITIAL_AFTER_RESET);
+    }
+    
+    private void checkInitialStateAfterStop() {
+        callMediaRecorderMethodUnderTestInState(MediaRecorderStateErrors.MediaRecorderState.INITIAL_AFTER_STOP);
+    }
+
+    private void checkInitializedState() {
+        callMediaRecorderMethodUnderTestInState(MediaRecorderStateErrors.MediaRecorderState.INITIALIZED);
+    }
+    
+    private void checkPreparedState() {
+        callMediaRecorderMethodUnderTestInState(MediaRecorderStateErrors.MediaRecorderState.PREPARED);
+    }
+    
+    private void checkRecordingState() {
+        callMediaRecorderMethodUnderTestInState(MediaRecorderStateErrors.MediaRecorderState.RECORDING);
+    }
+    
+    private void checkDataSourceConfiguredState() {
+        callMediaRecorderMethodUnderTestInState(MediaRecorderStateErrors.MediaRecorderState.DATASOURCECONFIGURED);
+    }
+    
+    private void checkErrorState() {
+        callMediaRecorderMethodUnderTestInState(MediaRecorderStateErrors.MediaRecorderState.ERROR);
+    }
+
+    /*
+     * Checks the given method under test in all possible states of the MediaRecorder object.
+     */
+    private void checkMethodUnderTestInAllPossibleStates() {
+        // Must be called first.
+        checkInitialState(); 
+        
+        // The sequence of the following method calls should not 
+        // affect the test results.
+        checkErrorState();
+        checkInitialStateAfterReset();
+        checkInitialStateAfterStop();
+        checkInitializedState();
+        checkRecordingState();
+        checkDataSourceConfiguredState();
+        checkPreparedState();
+    }
+    
+    /*
+     * Cleans up all the internal object references.
+     */
+    private void cleanUp() {
+        mMediaRecorder.release();
+        mMediaRecorder = null;
+        mMediaRecorderState = null;
+        mStateErrors = null;
+        mMethodUnderTest = null;
+    }
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderStopStateUnitTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderStopStateUnitTest.java
new file mode 100644
index 0000000..8737595
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderStopStateUnitTest.java
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+
+package com.android.mediaframeworktest.unit;
+
+import android.media.MediaRecorder;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.suitebuilder.annotation.Suppress;
+
+/**
+ * Unit test class to test the set of valid and invalid states that
+ * MediaRecorder.stop() method can be called.
+ */          
+public class MediaRecorderStopStateUnitTest extends AndroidTestCase implements MediaRecorderMethodUnderTest {
+    private MediaRecorderStateUnitTestTemplate mTestTemplate = new MediaRecorderStateUnitTestTemplate();
+
+    /**
+     * 1. It is valid to call stop() in the following states:
+     *    {Recording}.
+     * 2. It is invalid to call stop() in the following states:
+     *    {Initial, Initialized, DataSourceConfigured, Prepared, Error}
+     *    
+     * @param stateErrors the MediaRecorderStateErrors to check against.
+     */
+    public void checkStateErrors(MediaRecorderStateErrors stateErrors) {
+        // Valid states.
+        assertTrue(!stateErrors.errorInRecordingState);
+        
+        // Invalid states.
+        assertTrue(stateErrors.errorInInitialState);
+        assertTrue(stateErrors.errorInInitialStateAfterReset);
+        assertTrue(stateErrors.errorInInitialStateAfterStop);
+        assertTrue(stateErrors.errorInInitializedState);
+        assertTrue(stateErrors.errorInErrorState);
+        assertTrue(stateErrors.errorInDataSourceConfiguredState);
+        assertTrue(stateErrors.errorInPreparedState);
+    }
+
+    public void invokeMethodUnderTest(MediaRecorder recorder) {
+        recorder.stop();
+    }
+
+    @MediumTest
+    public void testStop() {
+        mTestTemplate.runTestOnMethod(this);
+    }
+    
+    @Override
+    public String toString() {
+        return "stop()";
+    }
+}