Merge "Turn off debug messge"
diff --git a/include/binder/CursorWindow.h b/include/binder/CursorWindow.h
index f0b2909..d227244 100644
--- a/include/binder/CursorWindow.h
+++ b/include/binder/CursorWindow.h
@@ -143,8 +143,6 @@
                          */
     uint32_t            alloc(size_t size, bool aligned = false);
 
-    uint32_t            read_field_slot(int row, int column, field_slot_t * slot);
-
                         /**
                          * Copy data into the window at the given offset.
                          */
@@ -181,6 +179,32 @@
                                 return ((field_slot_t *)offsetToPtr(fieldDirOffset)) + column;
                             }
 
+    int64_t getFieldSlotValueLong(field_slot_t* fieldSlot) {
+#if WINDOW_STORAGE_INLINE_NUMERICS
+        return fieldSlot->data.l;
+#else
+        return copyOutLong(fieldSlot->data.buffer.offset);
+#endif
+    }
+
+    double getFieldSlotValueDouble(field_slot_t* fieldSlot) {
+#if WINDOW_STORAGE_INLINE_NUMERICS
+        return fieldSlot->data.d;
+#else
+        return copyOutDouble(fieldSlot->data.buffer.offset);
+#endif
+    }
+
+#if WINDOW_STORAGE_UTF8
+    char* getFieldSlotValueString(field_slot_t* fieldSlot) {
+        return reinterpret_cast<char*>(offsetToPtr(fieldSlot->data.buffer.offset));
+    }
+#else
+    char16_t* getFieldSlotValueString(field_slot_t* fieldSlot) {
+        return reinterpret_cast<char16_t*>(offsetToPtr(fieldSlot->data.buffer.offset));
+    }
+#endif
+
 private:
     uint8_t * mData;
     size_t mSize;
diff --git a/include/binder/Parcel.h b/include/binder/Parcel.h
index bfe13f0..3fa2acb 100644
--- a/include/binder/Parcel.h
+++ b/include/binder/Parcel.h
@@ -38,6 +38,9 @@
 class Parcel
 {
 public:
+    class ReadableBlob;
+    class WritableBlob;
+
                         Parcel();
                         ~Parcel();
     
@@ -46,7 +49,7 @@
     size_t              dataAvail() const;
     size_t              dataPosition() const;
     size_t              dataCapacity() const;
-    
+
     status_t            setDataSize(size_t size);
     void                setDataPosition(size_t pos) const;
     status_t            setDataCapacity(size_t size);
@@ -56,6 +59,9 @@
     status_t            appendFrom(const Parcel *parcel,
                                    size_t start, size_t len);
 
+    bool                pushAllowFds(bool allowFds);
+    void                restoreAllowFds(bool lastValue);
+
     bool                hasFileDescriptors() const;
 
     // Writes the RPC header.
@@ -109,7 +115,13 @@
     // Place a file descriptor into the parcel.  A dup of the fd is made, which
     // will be closed once the parcel is destroyed.
     status_t            writeDupFileDescriptor(int fd);
-    
+
+    // Writes a blob to the parcel.
+    // If the blob is small, then it is stored in-place, otherwise it is
+    // transferred by way of an anonymous shared memory region.
+    // The caller should call release() on the blob after writing its contents.
+    status_t            writeBlob(size_t len, WritableBlob* outBlob);
+
     status_t            writeObject(const flat_binder_object& val, bool nullMetaData);
 
     // Like Parcel.java's writeNoException().  Just writes a zero int32.
@@ -157,7 +169,11 @@
     // Retrieve a file descriptor from the parcel.  This returns the raw fd
     // in the parcel, which you do not own -- use dup() to get your own copy.
     int                 readFileDescriptor() const;
-    
+
+    // Reads a blob from the parcel.
+    // The caller should call release() on the blob after reading its contents.
+    status_t            readBlob(size_t len, ReadableBlob* outBlob) const;
+
     const flat_binder_object* readObject(bool nullMetaData) const;
 
     // Explicitly close all file descriptors in the parcel.
@@ -177,7 +193,7 @@
                                             release_func relFunc, void* relCookie);
     
     void                print(TextOutput& to, uint32_t flags = 0) const;
-        
+
 private:
                         Parcel(const Parcel& o);
     Parcel&             operator=(const Parcel& o);
@@ -212,9 +228,40 @@
 
     mutable bool        mFdsKnown;
     mutable bool        mHasFds;
+    bool                mAllowFds;
     
     release_func        mOwner;
     void*               mOwnerCookie;
+
+    class Blob {
+    public:
+        Blob();
+        ~Blob();
+
+        void release();
+        inline size_t size() const { return mSize; }
+
+    protected:
+        void init(bool mapped, void* data, size_t size);
+        void clear();
+
+        bool mMapped;
+        void* mData;
+        size_t mSize;
+    };
+
+public:
+    class ReadableBlob : public Blob {
+        friend class Parcel;
+    public:
+        inline const void* data() const { return mData; }
+    };
+
+    class WritableBlob : public Blob {
+        friend class Parcel;
+    public:
+        inline void* data() { return mData; }
+    };
 };
 
 // ---------------------------------------------------------------------------
diff --git a/include/gui/SurfaceTexture.h b/include/gui/SurfaceTexture.h
index 926eb9a..e2d6179 100644
--- a/include/gui/SurfaceTexture.h
+++ b/include/gui/SurfaceTexture.h
@@ -20,6 +20,7 @@
 #include <EGL/egl.h>
 #include <EGL/eglext.h>
 #include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
 
 #include <gui/ISurfaceTexture.h>
 
@@ -61,7 +62,8 @@
 
     // tex indicates the name OpenGL texture to which images are to be streamed.
     // This texture name cannot be changed once the SurfaceTexture is created.
-    SurfaceTexture(GLuint tex, bool allowSynchronousMode = true);
+    SurfaceTexture(GLuint tex, bool allowSynchronousMode = true,
+            GLenum texTarget = GL_TEXTURE_EXTERNAL_OES);
 
     virtual ~SurfaceTexture();
 
@@ -458,6 +460,14 @@
     // member variables are accessed.
     mutable Mutex mMutex;
 
+    // mTexTarget is the GL texture target with which the GL texture object is
+    // associated.  It is set in the constructor and never changed.  It is
+    // almost always GL_TEXTURE_EXTERNAL_OES except for one use case in Android
+    // Browser.  In that case it is set to GL_TEXTURE_2D to allow
+    // glCopyTexSubImage to read from the texture.  This is a hack to work
+    // around a GL driver limitation on the number of FBO attachments, which the
+    // browser's tile cache exceeds.
+    const GLenum mTexTarget;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/include/utils/Errors.h b/include/utils/Errors.h
index 81f818b..0b75b19 100644
--- a/include/utils/Errors.h
+++ b/include/utils/Errors.h
@@ -72,6 +72,7 @@
     TIMED_OUT           = 0x80000005,
     UNKNOWN_TRANSACTION = 0x80000006,
 #endif    
+    FDS_NOT_ALLOWED     = 0x80000007,
 };
 
 // Restore define; enumeration is in "android" namespace, so the value defined
diff --git a/libs/binder/CursorWindow.cpp b/libs/binder/CursorWindow.cpp
index 47bbd04..b02374f 100644
--- a/libs/binder/CursorWindow.cpp
+++ b/libs/binder/CursorWindow.cpp
@@ -236,33 +236,6 @@
   return ((field_slot_t *)offsetToPtr(fieldDirOffset)) + column;  
 }
 
-uint32_t CursorWindow::read_field_slot(int row, int column, field_slot_t * slotOut)
-{
-    if (row < 0 || row >= mHeader->numRows || column < 0 || column >= mHeader->numColumns) {
-        LOGE("Can't read row# %d, col# %d from CursorWindow. Make sure your Cursor is initialized correctly.",
-                row, column);
-        return -1;
-    }        
-    row_slot_t * rowSlot = getRowSlot(row);
-    if (!rowSlot) {
-        LOGE("Failed to find rowSlot for row %d", row);
-        return -1;
-    }
-    if (rowSlot->offset == 0 || rowSlot->offset >= mSize) {
-        LOGE("Invalid rowSlot, offset = %d", rowSlot->offset);
-        return -1;
-    }
-LOG_WINDOW("Found field directory for %d,%d at rowSlot %d, offset %d", row, column, (uint8_t *)rowSlot - mData, rowSlot->offset);
-    field_slot_t * fieldDir = (field_slot_t *)offsetToPtr(rowSlot->offset);
-LOG_WINDOW("Read field_slot_t %d,%d: offset = %d, size = %d, type = %d", row, column, fieldDir[column].data.buffer.offset, fieldDir[column].data.buffer.size, fieldDir[column].type);
-
-    // Copy the data to the out param
-    slotOut->data.buffer.offset = fieldDir[column].data.buffer.offset;
-    slotOut->data.buffer.size = fieldDir[column].data.buffer.size;
-    slotOut->type = fieldDir[column].type;
-    return 0;
-}
-
 void CursorWindow::copyIn(uint32_t offset, uint8_t const * data, size_t size)
 {
     assert(offset + size <= mSize);    
@@ -370,12 +343,8 @@
     if (!fieldSlot || fieldSlot->type != FIELD_TYPE_INTEGER) {
         return false;
     }
-    
-#if WINDOW_STORAGE_INLINE_NUMERICS
-    *valueOut = fieldSlot->data.l;
-#else
-    *valueOut = copyOutLong(fieldSlot->data.buffer.offset);
-#endif
+
+    *valueOut = getFieldSlotValueLong(fieldSlot);
     return true;
 }
 
@@ -386,11 +355,7 @@
         return false;
     }
 
-#if WINDOW_STORAGE_INLINE_NUMERICS
-    *valueOut = fieldSlot->data.d;
-#else
-    *valueOut = copyOutDouble(fieldSlot->data.buffer.offset);
-#endif
+    *valueOut = getFieldSlotValueDouble(fieldSlot);
     return true;
 }
 
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index a0fc4d0..608877e 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -30,12 +30,14 @@
 #include <utils/TextOutput.h>
 #include <utils/misc.h>
 #include <utils/Flattenable.h>
+#include <cutils/ashmem.h>
 
 #include <private/binder/binder_module.h>
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdint.h>
+#include <sys/mman.h>
 
 #ifndef INT32_MAX
 #define INT32_MAX ((int32_t)(2147483647))
@@ -54,6 +56,9 @@
 // Note: must be kept in sync with android/os/Parcel.java's EX_HAS_REPLY_HEADER
 #define EX_HAS_REPLY_HEADER -128
 
+// Maximum size of a blob to transfer in-place.
+static const size_t IN_PLACE_BLOB_LIMIT = 40 * 1024;
+
 // XXX This can be made public if we want to provide
 // support for typed data.
 struct small_flat_data
@@ -399,6 +404,8 @@
     mDataPos += len;
     mDataSize += len;
 
+    err = NO_ERROR;
+
     if (numObjects > 0) {
         // grow objects
         if (mObjectsCapacity < mObjectsSize + numObjects) {
@@ -430,11 +437,28 @@
                 flat->handle = dup(flat->handle);
                 flat->cookie = (void*)1;
                 mHasFds = mFdsKnown = true;
+                if (!mAllowFds) {
+                    err = FDS_NOT_ALLOWED;
+                }
             }
         }
     }
 
-    return NO_ERROR;
+    return err;
+}
+
+bool Parcel::pushAllowFds(bool allowFds)
+{
+    const bool origValue = mAllowFds;
+    if (!allowFds) {
+        mAllowFds = false;
+    }
+    return origValue;
+}
+
+void Parcel::restoreAllowFds(bool lastValue)
+{
+    mAllowFds = lastValue;
 }
 
 bool Parcel::hasFileDescriptors() const
@@ -706,6 +730,54 @@
     return writeObject(obj, true);
 }
 
+status_t Parcel::writeBlob(size_t len, WritableBlob* outBlob)
+{
+    status_t status;
+
+    if (!mAllowFds || len <= IN_PLACE_BLOB_LIMIT) {
+        LOGV("writeBlob: write in place");
+        status = writeInt32(0);
+        if (status) return status;
+
+        void* ptr = writeInplace(len);
+        if (!ptr) return NO_MEMORY;
+
+        outBlob->init(false /*mapped*/, ptr, len);
+        return NO_ERROR;
+    }
+
+    LOGV("writeBlob: write to ashmem");
+    int fd = ashmem_create_region("Parcel Blob", len);
+    if (fd < 0) return NO_MEMORY;
+
+    int result = ashmem_set_prot_region(fd, PROT_READ | PROT_WRITE);
+    if (result < 0) {
+        status = -result;
+    } else {
+        void* ptr = ::mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+        if (ptr == MAP_FAILED) {
+            status = -errno;
+        } else {
+            result = ashmem_set_prot_region(fd, PROT_READ);
+            if (result < 0) {
+                status = -result;
+            } else {
+                status = writeInt32(1);
+                if (!status) {
+                    status = writeFileDescriptor(fd);
+                    if (!status) {
+                        outBlob->init(true /*mapped*/, ptr, len);
+                        return NO_ERROR;
+                    }
+                }
+            }
+        }
+        ::munmap(ptr, len);
+    }
+    ::close(fd);
+    return status;
+}
+
 status_t Parcel::write(const Flattenable& val)
 {
     status_t err;
@@ -759,6 +831,9 @@
         
         // remember if it's a file descriptor
         if (val.type == BINDER_TYPE_FD) {
+            if (!mAllowFds) {
+                return FDS_NOT_ALLOWED;
+            }
             mHasFds = mFdsKnown = true;
         }
 
@@ -1025,6 +1100,32 @@
     return BAD_TYPE;
 }
 
+status_t Parcel::readBlob(size_t len, ReadableBlob* outBlob) const
+{
+    int32_t useAshmem;
+    status_t status = readInt32(&useAshmem);
+    if (status) return status;
+
+    if (!useAshmem) {
+        LOGV("readBlob: read in place");
+        const void* ptr = readInplace(len);
+        if (!ptr) return BAD_VALUE;
+
+        outBlob->init(false /*mapped*/, const_cast<void*>(ptr), len);
+        return NO_ERROR;
+    }
+
+    LOGV("readBlob: read from ashmem");
+    int fd = readFileDescriptor();
+    if (fd == int(BAD_TYPE)) return BAD_VALUE;
+
+    void* ptr = ::mmap(NULL, len, PROT_READ, MAP_SHARED, fd, 0);
+    if (!ptr) return NO_MEMORY;
+
+    outBlob->init(true /*mapped*/, ptr, len);
+    return NO_ERROR;
+}
+
 status_t Parcel::read(Flattenable& val) const
 {
     // size
@@ -1283,6 +1384,7 @@
     mNextObjectHint = 0;
     mHasFds = false;
     mFdsKnown = true;
+    mAllowFds = true;
     
     return NO_ERROR;
 }
@@ -1434,6 +1536,7 @@
     mNextObjectHint = 0;
     mHasFds = false;
     mFdsKnown = true;
+    mAllowFds = true;
     mOwner = NULL;
 }
 
@@ -1452,4 +1555,33 @@
     mFdsKnown = true;
 }
 
+// --- Parcel::Blob ---
+
+Parcel::Blob::Blob() :
+        mMapped(false), mData(NULL), mSize(0) {
+}
+
+Parcel::Blob::~Blob() {
+    release();
+}
+
+void Parcel::Blob::release() {
+    if (mMapped && mData) {
+        ::munmap(mData, mSize);
+    }
+    clear();
+}
+
+void Parcel::Blob::init(bool mapped, void* data, size_t size) {
+    mMapped = mapped;
+    mData = data;
+    mSize = size;
+}
+
+void Parcel::Blob::clear() {
+    mMapped = false;
+    mData = NULL;
+    mSize = 0;
+}
+
 }; // namespace android
diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp
index dac9418..c72a45b 100644
--- a/libs/gui/SurfaceTexture.cpp
+++ b/libs/gui/SurfaceTexture.cpp
@@ -94,7 +94,8 @@
     return android_atomic_inc(&globalCounter);
 }
 
-SurfaceTexture::SurfaceTexture(GLuint tex, bool allowSynchronousMode) :
+SurfaceTexture::SurfaceTexture(GLuint tex, bool allowSynchronousMode,
+        GLenum texTarget) :
     mDefaultWidth(1),
     mDefaultHeight(1),
     mPixelFormat(PIXEL_FORMAT_RGBA_8888),
@@ -110,7 +111,8 @@
     mSynchronousMode(false),
     mAllowSynchronousMode(allowSynchronousMode),
     mConnectedApi(NO_CONNECTED_API),
-    mAbandoned(false) {
+    mAbandoned(false),
+    mTexTarget(texTarget) {
     // Choose a name using the PID and a process-unique ID.
     mName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId());
 
@@ -698,9 +700,8 @@
             ST_LOGW("updateTexImage: clearing GL error: %#04x", error);
         }
 
-        glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTexName);
-        glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES,
-                (GLeglImageOES)image);
+        glBindTexture(mTexTarget, mTexName);
+        glEGLImageTargetTexture2DOES(mTexTarget, (GLeglImageOES)image);
 
         bool failed = false;
         while ((error = glGetError()) != GL_NO_ERROR) {
@@ -735,7 +736,7 @@
         mDequeueCondition.signal();
     } else {
         // We always bind the texture even if we don't update its contents.
-        glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTexName);
+        glBindTexture(mTexTarget, mTexName);
     }
 
     return OK;
@@ -761,7 +762,7 @@
 }
 
 GLenum SurfaceTexture::getCurrentTextureTarget() const {
-    return GL_TEXTURE_EXTERNAL_OES;
+    return mTexTarget;
 }
 
 void SurfaceTexture::getTransformMatrix(float mtx[16]) {
diff --git a/libs/utils/Android.mk b/libs/utils/Android.mk
index e4eadbd..638f72f 100644
--- a/libs/utils/Android.mk
+++ b/libs/utils/Android.mk
@@ -100,12 +100,8 @@
 LOCAL_SHARED_LIBRARIES := \
 	libz \
 	liblog \
-	libcutils
-
-ifeq ($(TARGET_OS)-$(TARGET_ARCH),linux-x86)
-# This is needed on x86 to bring in dl_iterate_phdr for CallStack.cpp
-LOCAL_SHARED_LIBRARIES += libdl
-endif # linux-x86
+	libcutils \
+	libdl
 
 LOCAL_MODULE:= libutils
 include $(BUILD_SHARED_LIBRARY)
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index d2bba0b..be9b226 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -75,7 +75,7 @@
 }
 
 void HWComposer::invalidate() {
-    mFlinger->signalEvent();
+    mFlinger->repaintEverything();
 }
 
 void HWComposer::setFrameBuffer(EGLDisplay dpy, EGLSurface sur) {
@@ -176,9 +176,9 @@
                 mList->numHwLayers, mList->flags);
         result.append(buffer);
         result.append(
-                "    type   |   hints  |   flags  | tr | blend |  format  |       source crop         |           frame           name \n"
-                "-----------+----------+----------+----+-------+----------+---------------------------+--------------------------------\n");
-        //      "  ________ | ________ | ________ | __ | _____ | ________ | [_____,_____,_____,_____] | [_____,_____,_____,_____]
+                "   type   |  handle  |   hints  |   flags  | tr | blend |  format  |       source crop         |           frame           name \n"
+                "----------+----------+----------+----------+----+-------+----------+---------------------------+--------------------------------\n");
+        //      " ________ | ________ | ________ | ________ | __ | _____ | ________ | [_____,_____,_____,_____] | [_____,_____,_____,_____]
         for (size_t i=0 ; i<mList->numHwLayers ; i++) {
             const hwc_layer_t& l(mList->hwLayers[i]);
             const sp<LayerBase> layer(visibleLayersSortedByZ[i]);
@@ -190,9 +190,9 @@
                 }
             }
             snprintf(buffer, SIZE,
-                    "  %8s | %08x | %08x | %02x | %05x | %08x | [%5d,%5d,%5d,%5d] | [%5d,%5d,%5d,%5d] %s\n",
+                    " %8s | %08x | %08x | %08x | %02x | %05x | %08x | [%5d,%5d,%5d,%5d] | [%5d,%5d,%5d,%5d] %s\n",
                     l.compositionType ? "OVERLAY" : "FB",
-                    l.hints, l.flags, l.transform, l.blending, format,
+                    intptr_t(l.handle), l.hints, l.flags, l.transform, l.blending, format,
                     l.sourceCrop.left, l.sourceCrop.top, l.sourceCrop.right, l.sourceCrop.bottom,
                     l.displayFrame.left, l.displayFrame.top, l.displayFrame.right, l.displayFrame.bottom,
                     layer->getName().string());
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 43191b7..128a64d 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -256,12 +256,11 @@
 public:     // hack to work around gcc 4.0.3 bug
     const GraphicPlane&     graphicPlane(int dpy) const;
           GraphicPlane&     graphicPlane(int dpy);
-private:
+          void              signalEvent();
+          void              repaintEverything();
 
-            void        waitForEvent();
-public:     // hack to work around gcc 4.0.3 bug
-            void        signalEvent();
 private:
+            void        waitForEvent();
             void        handleConsoleEvents();
             void        handleTransaction(uint32_t transactionFlags);
             void        handleTransactionLocked(uint32_t transactionFlags);
@@ -279,7 +278,6 @@
             void        postFramebuffer();
             void        setupHardwareComposer(Region& dirtyInOut);
             void        composeSurfaces(const Region& dirty);
-            void        repaintEverything();
 
 
             ssize_t     addClientLayer(const sp<Client>& client,