am 4b2b0a74: am 74bd799e: Merge "Exit dumpstate on SIGPIPE to avoid cascading child crashes"

* commit '4b2b0a7494c872b7d545a9abe2d08ca0d0325073':
  Exit dumpstate on SIGPIPE to avoid cascading child crashes
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index 1911839..6d6f77e 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -82,6 +82,7 @@
     { "hal",        "Hardware Modules", ATRACE_TAG_HAL, { } },
     { "res",        "Resource Loading", ATRACE_TAG_RESOURCES, { } },
     { "dalvik",     "Dalvik VM",        ATRACE_TAG_DALVIK, { } },
+    { "rs",         "RenderScript",     ATRACE_TAG_RS, { } },
     { "sched",      "CPU Scheduling",   0, {
         { REQ,      "/sys/kernel/debug/tracing/events/sched/sched_switch/enable" },
         { REQ,      "/sys/kernel/debug/tracing/events/sched/sched_wakeup/enable" },
diff --git a/cmds/dumpsys/dumpsys.cpp b/cmds/dumpsys/dumpsys.cpp
index c9fcc00..7cd5afd 100644
--- a/cmds/dumpsys/dumpsys.cpp
+++ b/cmds/dumpsys/dumpsys.cpp
@@ -9,7 +9,7 @@
 #include <binder/Parcel.h>
 #include <binder/ProcessState.h>
 #include <binder/IServiceManager.h>
-#include <utils/TextOutput.h>
+#include <binder/TextOutput.h>
 #include <utils/Vector.h>
 
 #include <getopt.h>
diff --git a/cmds/flatland/Main.cpp b/cmds/flatland/Main.cpp
index 99715d3..d6ac3d2 100644
--- a/cmds/flatland/Main.cpp
+++ b/cmds/flatland/Main.cpp
@@ -56,7 +56,7 @@
 
 static const BenchmarkDesc benchmarks[] = {
     { "16:10 Single Static Window",
-        2560, 1600, { 800, 1600, 2400 },
+        2560, 1600, { 800, 1200, 1600, 2400 },
         {
             {   // Window
                 0, staticGradient, opaque,
@@ -73,8 +73,26 @@
         },
     },
 
+    { "3:2 Single Static Window",
+        2048, 1536, { 1536 },
+        {
+            {   // Window
+                0, staticGradient, opaque,
+                0,    50,     2048,   1440,
+            },
+            {   // Status bar
+                0, staticGradient, opaque,
+                0,    0,      2048,   50,
+            },
+            {   // Navigation bar
+                0, staticGradient, opaque,
+                0,    1440,   2048,   96,
+            },
+        },
+    },
+
     { "16:10 App -> Home Transition",
-        2560, 1600, { 800, 1600, 2400 },
+        2560, 1600, { 800, 1200, 1600, 2400 },
         {
             {   // Wallpaper
                 0, staticGradient, opaque,
@@ -99,8 +117,34 @@
         },
     },
 
+    { "3:2 App -> Home Transition",
+        2048, 1536, { 1536 },
+        {
+            {   // Wallpaper
+                0, staticGradient, opaque,
+                0,    50,     2048,   1440,
+            },
+            {   // Launcher
+                0, staticGradient, blend,
+                0,    50,     2048,   1440,
+            },
+            {   // Outgoing activity
+                0, staticGradient, blendShrink,
+                20,    70,     2048,   1400,
+            },
+            {   // Status bar
+                0, staticGradient, opaque,
+                0,    0,      2048,   50,
+            },
+            {   // Navigation bar
+                0, staticGradient, opaque,
+                0,    1440,   2048,   96,
+            },
+        },
+    },
+
     { "16:10 SurfaceView -> Home Transition",
-        2560, 1600, { 800, 1600, 2400 },
+        2560, 1600, { 800, 1200, 1600, 2400 },
         {
             {   // Wallpaper
                 0, staticGradient, opaque,
@@ -128,6 +172,36 @@
             },
         },
     },
+
+    { "3:2 SurfaceView -> Home Transition",
+        2048, 1536, { 1536 },
+        {
+            {   // Wallpaper
+                0, staticGradient, opaque,
+                0,    50,     2048,   1440,
+            },
+            {   // Launcher
+                0, staticGradient, blend,
+                0,    50,     2048,   1440,
+            },
+            {   // Outgoing SurfaceView
+                0, staticGradient, blendShrink,
+                20,    70,     2048,   1400,
+            },
+            {   // Outgoing activity
+                0, staticGradient, blendShrink,
+                20,    70,     2048,   1400,
+            },
+            {   // Status bar
+                0, staticGradient, opaque,
+                0,    0,      2048,   50,
+            },
+            {   // Navigation bar
+                0, staticGradient, opaque,
+                0,    1440,   2048,   96,
+            },
+        },
+    },
 };
 
 static const ShaderDesc shaders[] = {
diff --git a/cmds/service/service.cpp b/cmds/service/service.cpp
index 32db83b..97fc47c 100644
--- a/cmds/service/service.cpp
+++ b/cmds/service/service.cpp
@@ -1,12 +1,23 @@
 /*
- * Command line access to services.
+ * Copyright 2013 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 <binder/Parcel.h>
 #include <binder/ProcessState.h>
 #include <binder/IServiceManager.h>
-#include <utils/TextOutput.h>
+#include <binder/TextOutput.h>
 
 #include <getopt.h>
 #include <stdlib.h>
diff --git a/include/binder/BinderService.h b/include/binder/BinderService.h
index 5ac36d9..ef703bd 100644
--- a/include/binder/BinderService.h
+++ b/include/binder/BinderService.h
@@ -42,19 +42,20 @@
     }
 
     static void publishAndJoinThreadPool(bool allowIsolated = false) {
-        sp<IServiceManager> sm(defaultServiceManager());
-        sm->addService(
-                String16(SERVICE::getServiceName()),
-                new SERVICE(), allowIsolated);
-        ProcessState::self()->startThreadPool();
-        ProcessState::self()->giveThreadPoolName();
-        IPCThreadState::self()->joinThreadPool();
+        publish(allowIsolated);
+        joinThreadPool();
     }
 
     static void instantiate() { publish(); }
 
-    static status_t shutdown() {
-        return NO_ERROR;
+    static status_t shutdown() { return NO_ERROR; }
+
+private:
+    static void joinThreadPool() {
+        sp<ProcessState> ps(ProcessState::self());
+        ps->startThreadPool();
+        ps->giveThreadPoolName();
+        IPCThreadState::self()->joinThreadPool();
     }
 };
 
diff --git a/include/utils/BufferedTextOutput.h b/include/binder/BufferedTextOutput.h
similarity index 98%
rename from include/utils/BufferedTextOutput.h
rename to include/binder/BufferedTextOutput.h
index 69c6240..adf3c32 100644
--- a/include/utils/BufferedTextOutput.h
+++ b/include/binder/BufferedTextOutput.h
@@ -17,7 +17,7 @@
 #ifndef ANDROID_BUFFEREDTEXTOUTPUT_H
 #define ANDROID_BUFFEREDTEXTOUTPUT_H
 
-#include <utils/TextOutput.h>
+#include <binder/TextOutput.h>
 #include <utils/threads.h>
 #include <cutils/uio.h>
 
diff --git a/include/binder/Debug.h b/include/binder/Debug.h
new file mode 100644
index 0000000..f6a3355
--- /dev/null
+++ b/include/binder/Debug.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2005 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_BINDER_DEBUG_H
+#define ANDROID_BINDER_DEBUG_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+const char* stringForIndent(int32_t indentLevel);
+
+typedef void (*debugPrintFunc)(void* cookie, const char* txt);
+
+void printTypeCode(uint32_t typeCode,
+    debugPrintFunc func = 0, void* cookie = 0);
+
+void printHexData(int32_t indent, const void *buf, size_t length,
+    size_t bytesPerLine=16, int32_t singleLineBytesCutoff=16,
+    size_t alignment=0, bool cArrayStyle=false,
+    debugPrintFunc func = 0, void* cookie = 0);
+
+#ifdef __cplusplus
+}
+#endif
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+
+#endif // ANDROID_BINDER_DEBUG_H
diff --git a/include/utils/TextOutput.h b/include/binder/TextOutput.h
similarity index 100%
rename from include/utils/TextOutput.h
rename to include/binder/TextOutput.h
diff --git a/include/gui/BufferQueue.h b/include/gui/BufferQueue.h
index 6c1b691..766fa0f 100644
--- a/include/gui/BufferQueue.h
+++ b/include/gui/BufferQueue.h
@@ -229,7 +229,7 @@
 
     // dump our state in a String
     virtual void dump(String8& result) const;
-    virtual void dump(String8& result, const char* prefix, char* buffer, size_t SIZE) const;
+    virtual void dump(String8& result, const char* prefix) const;
 
     // public facing structure for BufferSlot
     struct BufferItem {
@@ -240,7 +240,8 @@
            mScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
            mTimestamp(0),
            mFrameNumber(0),
-           mBuf(INVALID_BUFFER_SLOT) {
+           mBuf(INVALID_BUFFER_SLOT),
+           mAcquireCalled(false) {
              mCrop.makeInvalid();
         }
         // mGraphicBuffer points to the buffer allocated for this slot, or is NULL
@@ -269,6 +270,9 @@
 
         // mFence is a fence that will signal when the buffer is idle.
         sp<Fence> mFence;
+
+        // Indicates whether this buffer has been seen by a consumer yet
+        bool mAcquireCalled;
     };
 
     // The following public functions are the consumer-facing interface
@@ -285,7 +289,7 @@
     // releaseBuffer releases a buffer slot from the consumer back to the
     // BufferQueue.  This may be done while the buffer's contents are still
     // being accessed.  The fence will signal when the buffer is no longer
-    // in use.
+    // in use. frameNumber is used to indentify the exact buffer returned.
     //
     // If releaseBuffer returns STALE_BUFFER_SLOT, then the consumer must free
     // any references to the just-released buffer that it might have, as if it
@@ -294,7 +298,8 @@
     //
     // Note that the dependencies on EGL will be removed once we switch to using
     // the Android HW Sync HAL.
-    status_t releaseBuffer(int buf, EGLDisplay display, EGLSyncKHR fence,
+    status_t releaseBuffer(int buf, uint64_t frameNumber,
+            EGLDisplay display, EGLSyncKHR fence,
             const sp<Fence>& releaseFence);
 
     // consumerConnect connects a consumer to the BufferQueue.  Only one
@@ -368,10 +373,6 @@
     // all slots.
     void freeAllBuffersLocked();
 
-    // freeAllBuffersExceptHeadLocked frees the GraphicBuffer and sync
-    // resources for all slots except the head of mQueue.
-    void freeAllBuffersExceptHeadLocked();
-
     // drainQueueLocked waits for the buffer queue to empty if we're in
     // synchronous mode, or returns immediately otherwise. It returns NO_INIT
     // if the BufferQueue is abandoned (consumer disconnected) or disconnected
@@ -410,20 +411,20 @@
     // connected, mDequeueCondition must be broadcast.
     int getMaxBufferCountLocked() const;
 
+    // stillTracking returns true iff the buffer item is still being tracked
+    // in one of the slots.
+    bool stillTracking(const BufferItem *item) const;
+
     struct BufferSlot {
 
         BufferSlot()
         : mEglDisplay(EGL_NO_DISPLAY),
           mBufferState(BufferSlot::FREE),
           mRequestBufferCalled(false),
-          mTransform(0),
-          mScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
-          mTimestamp(0),
           mFrameNumber(0),
           mEglFence(EGL_NO_SYNC_KHR),
           mAcquireCalled(false),
           mNeedsCleanupOnRelease(false) {
-            mCrop.makeInvalid();
         }
 
         // mGraphicBuffer points to the buffer allocated for this slot or is NULL
@@ -482,21 +483,6 @@
         // needed but useful for debugging and catching producer bugs.
         bool mRequestBufferCalled;
 
-        // mCrop is the current crop rectangle for this buffer slot.
-        Rect mCrop;
-
-        // mTransform is the current transform flags for this buffer slot.
-        // (example: NATIVE_WINDOW_TRANSFORM_ROT_90)
-        uint32_t mTransform;
-
-        // mScalingMode is the current scaling mode for this buffer slot.
-        // (example: NATIVE_WINDOW_SCALING_MODE_FREEZE)
-        uint32_t mScalingMode;
-
-        // mTimestamp is the current timestamp for this buffer slot. This gets
-        // to set by queueBuffer each time this slot is queued.
-        int64_t mTimestamp;
-
         // mFrameNumber is the number of the queued frame for this slot.  This
         // is used to dequeue buffers in LRU order (useful because buffers
         // may be released before their release fence is signaled).
@@ -592,7 +578,7 @@
     mutable Condition mDequeueCondition;
 
     // mQueue is a FIFO of queued buffers used in synchronous mode
-    typedef Vector<int> Fifo;
+    typedef Vector<BufferItem> Fifo;
     Fifo mQueue;
 
     // mAbandoned indicates that the BufferQueue will no longer be used to
@@ -613,7 +599,7 @@
     mutable Mutex mMutex;
 
     // mFrameCounter is the free running counter, incremented on every
-    // successful queueBuffer call.
+    // successful queueBuffer call, and buffer allocation.
     uint64_t mFrameCounter;
 
     // mBufferHasBeenQueued is true once a buffer has been queued.  It is
diff --git a/include/gui/ConsumerBase.h b/include/gui/ConsumerBase.h
index 8a7545d..1d51bc9 100644
--- a/include/gui/ConsumerBase.h
+++ b/include/gui/ConsumerBase.h
@@ -73,7 +73,7 @@
     // their state to the dump by overriding the dumpLocked method, which is
     // called by these methods after locking the mutex.
     void dump(String8& result) const;
-    void dump(String8& result, const char* prefix, char* buffer, size_t SIZE) const;
+    void dump(String8& result, const char* prefix) const;
 
     // setFrameAvailableListener sets the listener object that will be notified
     // when a new frame becomes available.
@@ -143,8 +143,7 @@
     // should call ConsumerBase::dumpLocked.
     //
     // This method must be called with mMutex locked.
-    virtual void dumpLocked(String8& result, const char* prefix, char* buffer,
-            size_t size) const;
+    virtual void dumpLocked(String8& result, const char* prefix) const;
 
     // acquireBufferLocked fetches the next buffer from the BufferQueue and
     // updates the buffer slot for the buffer returned.
@@ -161,17 +160,23 @@
     // Derived classes should override this method to perform any cleanup that
     // must take place when a buffer is released back to the BufferQueue.  If
     // it is overridden the derived class's implementation must call
-    // ConsumerBase::releaseBufferLocked.
-    virtual status_t releaseBufferLocked(int buf, EGLDisplay display,
-           EGLSyncKHR eglFence);
+    // ConsumerBase::releaseBufferLocked.e
+    virtual status_t releaseBufferLocked(int slot,
+            const sp<GraphicBuffer> graphicBuffer,
+            EGLDisplay display, EGLSyncKHR eglFence);
+
+    // returns true iff the slot still has the graphicBuffer in it.
+    bool stillTracking(int slot, const sp<GraphicBuffer> graphicBuffer);
 
     // addReleaseFence* adds the sync points associated with a fence to the set
     // of sync points that must be reached before the buffer in the given slot
     // may be used after the slot has been released.  This should be called by
     // derived classes each time some asynchronous work is kicked off that
     // references the buffer.
-    status_t addReleaseFence(int slot, const sp<Fence>& fence);
-    status_t addReleaseFenceLocked(int slot, const sp<Fence>& fence);
+    status_t addReleaseFence(int slot,
+            const sp<GraphicBuffer> graphicBuffer, const sp<Fence>& fence);
+    status_t addReleaseFenceLocked(int slot,
+            const sp<GraphicBuffer> graphicBuffer, const sp<Fence>& fence);
 
     // Slot contains the information and object references that
     // ConsumerBase maintains about a BufferQueue buffer slot.
@@ -185,6 +190,9 @@
         // overwritten. The buffer can be dequeued before the fence signals;
         // the producer is responsible for delaying writes until it signals.
         sp<Fence> mFence;
+
+        // the frame number of the last acquired frame for this slot
+        uint64_t mFrameNumber;
     };
 
     // mSlots stores the buffers that have been allocated by the BufferQueue
diff --git a/include/gui/GLConsumer.h b/include/gui/GLConsumer.h
index f0a75dc..031684e 100644
--- a/include/gui/GLConsumer.h
+++ b/include/gui/GLConsumer.h
@@ -233,8 +233,7 @@
 
     // dumpLocked overrides the ConsumerBase method to dump GLConsumer-
     // specific info in addition to the ConsumerBase behavior.
-    virtual void dumpLocked(String8& result, const char* prefix, char* buffer,
-           size_t size) const;
+    virtual void dumpLocked(String8& result, const char* prefix) const;
 
     // acquireBufferLocked overrides the ConsumerBase method to update the
     // mEglSlots array in addition to the ConsumerBase behavior.
@@ -242,11 +241,13 @@
 
     // releaseBufferLocked overrides the ConsumerBase method to update the
     // mEglSlots array in addition to the ConsumerBase.
-    virtual status_t releaseBufferLocked(int buf, EGLDisplay display,
-           EGLSyncKHR eglFence);
+    virtual status_t releaseBufferLocked(int slot,
+            const sp<GraphicBuffer> graphicBuffer,
+            EGLDisplay display, EGLSyncKHR eglFence);
 
-    status_t releaseBufferLocked(int buf, EGLSyncKHR eglFence) {
-        return releaseBufferLocked(buf, mEglDisplay, eglFence);
+    status_t releaseBufferLocked(int slot,
+            const sp<GraphicBuffer> graphicBuffer, EGLSyncKHR eglFence) {
+        return releaseBufferLocked(slot, graphicBuffer, mEglDisplay, eglFence);
     }
 
     static bool isExternalFormat(uint32_t format);
diff --git a/include/media/hardware/HDCPAPI.h b/include/media/hardware/HDCPAPI.h
index 147448e..b3f4222 100644
--- a/include/media/hardware/HDCPAPI.h
+++ b/include/media/hardware/HDCPAPI.h
@@ -19,6 +19,7 @@
 #define HDCP_API_H_
 
 #include <utils/Errors.h>
+#include <system/window.h>
 
 namespace android {
 
@@ -90,6 +91,20 @@
         return INVALID_OPERATION;
     }
 
+    // Encrypt data according to the HDCP spec. "size" bytes of data starting
+    // at location "offset" are available in "buffer" (buffer handle). "size"
+    // may not be a multiple of 128 bits (16 bytes). An equal number of
+    // encrypted bytes should be written to the buffer at "outData" (virtual
+    // address). This operation is to be synchronous, i.e. this call does not
+    // return until outData contains size bytes of encrypted data.
+    // streamCTR will be assigned by the caller (to 0 for the first PES stream,
+    // 1 for the second and so on)
+    // inputCTR _will_be_maintained_by_the_callee_ for each PES stream.
+    virtual status_t encryptNative(
+            buffer_handle_t buffer, size_t offset, size_t size,
+            uint32_t streamCTR, uint64_t *outInputCTR, void *outData) {
+        return INVALID_OPERATION;
+    }
     // DECRYPTION only:
     // Decrypt data according to the HDCP spec.
     // "size" bytes of encrypted data are available at "inData"
diff --git a/include/media/openmax/OMX_IVCommon.h b/include/media/openmax/OMX_IVCommon.h
index 85bf00d..96a4396 100644
--- a/include/media/openmax/OMX_IVCommon.h
+++ b/include/media/openmax/OMX_IVCommon.h
@@ -161,6 +161,7 @@
     OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00,
     OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka = 0x7FA30C03,
     OMX_SEC_COLOR_FormatNV12Tiled = 0x7FC00002,
+    OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar32m = 0x7FA30C04,
     OMX_COLOR_FormatMax = 0x7FFFFFFF
 } OMX_COLOR_FORMATTYPE;
 
diff --git a/include/powermanager/IPowerManager.h b/include/powermanager/IPowerManager.h
index 1723f04..e21e6a8 100644
--- a/include/powermanager/IPowerManager.h
+++ b/include/powermanager/IPowerManager.h
@@ -30,7 +30,8 @@
 public:
     DECLARE_META_INTERFACE(PowerManager);
 
-    virtual status_t acquireWakeLock(int flags, const sp<IBinder>& lock, const String16& tag) = 0;
+    virtual status_t acquireWakeLock(int flags, const sp<IBinder>& lock, const String16& tag,
+            const String16& packageName) = 0;
     virtual status_t releaseWakeLock(const sp<IBinder>& lock, int flags) = 0;
 };
 
diff --git a/include/private/binder/Static.h b/include/private/binder/Static.h
index 5b0f9fc..6a03594 100644
--- a/include/private/binder/Static.h
+++ b/include/private/binder/Static.h
@@ -27,6 +27,9 @@
 
 namespace android {
 
+// For TextStream.cpp
+extern Vector<int32_t> gTextBuffers;
+
 // For ProcessState.cpp
 extern Mutex gProcessMutex;
 extern sp<ProcessState> gProcess;
diff --git a/include/private/utils/Static.h b/include/private/utils/Static.h
deleted file mode 100644
index d95ae0d..0000000
--- a/include/private/utils/Static.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// All static variables go here, to control initialization and
-// destruction order in the library.
-
-#include <utils/threads.h>
-#include <utils/KeyedVector.h>
-
-namespace android {
-// For TextStream.cpp
-extern Vector<int32_t> gTextBuffers;
-
-// For String8.cpp
-extern void initialize_string8();
-extern void terminate_string8();
-
-// For String16.cpp
-extern void initialize_string16();
-extern void terminate_string16();
-
-}   // namespace android
diff --git a/include/ui/Rect.h b/include/ui/Rect.h
index 47d37b6..6cf64eb 100644
--- a/include/ui/Rect.h
+++ b/include/ui/Rect.h
@@ -35,14 +35,25 @@
 
     inline Rect() {
     }
+
     inline Rect(int32_t w, int32_t h) {
-        left = top = 0; right = w; bottom = h;
+        left = top = 0;
+        right = w;
+        bottom = h;
     }
+
     inline Rect(int32_t l, int32_t t, int32_t r, int32_t b) {
-        left = l; top = t; right = r; bottom = b;
+        left = l;
+        top = t;
+        right = r;
+        bottom = b;
     }
+
     inline Rect(const Point& lt, const Point& rb) {
-        left = lt.x; top = lt.y; right = rb.x; bottom = rb.y;
+        left = lt.x;
+        top = lt.y;
+        right = rb.x;
+        bottom = rb.y;
     }
 
     void makeInvalid();
@@ -53,43 +64,36 @@
 
     // a valid rectangle has a non negative width and height
     inline bool isValid() const {
-        return (width()>=0) && (height()>=0);
+        return (getWidth() >= 0) && (getHeight() >= 0);
     }
 
     // an empty rect has a zero width or height, or is invalid
     inline bool isEmpty() const {
-        return (width()<=0) || (height()<=0);
-    }
-
-    inline void set(const Rect& rhs) {
-        operator = (rhs);
+        return (getWidth() <= 0) || (getHeight() <= 0);
     }
 
     // rectangle's width
     inline int32_t getWidth() const {
-        return right-left;
+        return right - left;
     }
-    
+
     // rectangle's height
     inline int32_t getHeight() const {
-        return bottom-top;
+        return bottom - top;
     }
 
     inline Rect getBounds() const {
-        return Rect(right-left, bottom-top);
+        return Rect(right - left, bottom - top);
     }
 
-    inline int32_t width() const { return getWidth(); }
-    inline int32_t height() const { return getHeight(); }
-
     void setLeftTop(const Point& lt) {
         left = lt.x;
-        top  = lt.y;
+        top = lt.y;
     }
 
     void setRightBottom(const Point& rb) {
         right = rb.x;
-        bottom  = rb.y;
+        bottom = rb.y;
     }
     
     // the following 4 functions return the 4 corners of the rect as Point
@@ -120,6 +124,16 @@
     // vectors.
     bool operator < (const Rect& rhs) const;
 
+    const Rect operator + (const Point& rhs) const;
+    const Rect operator - (const Point& rhs) const;
+
+    Rect& operator += (const Point& rhs) {
+        return offsetBy(rhs.x, rhs.y);
+    }
+    Rect& operator -= (const Point& rhs) {
+        return offsetBy(-rhs.x, -rhs.y);
+    }
+
     Rect& offsetToOrigin() {
         right -= left;
         bottom -= top;
@@ -132,22 +146,11 @@
     Rect& offsetBy(const Point& dp) {
         return offsetBy(dp.x, dp.y);
     }
-    Rect& operator += (const Point& rhs) {
-        return offsetBy(rhs.x, rhs.y);
-    }
-    Rect& operator -= (const Point& rhs) {
-        return offsetBy(-rhs.x, -rhs.y);
-    }
-    const Rect operator + (const Point& rhs) const;
-    const Rect operator - (const Point& rhs) const;
 
-    void translate(int32_t dx, int32_t dy) { // legacy, don't use.
-        offsetBy(dx, dy);
-    }
+    Rect& offsetTo(int32_t x, int32_t y);
+    Rect& offsetBy(int32_t x, int32_t y);
 
-    Rect&   offsetTo(int32_t x, int32_t y);
-    Rect&   offsetBy(int32_t x, int32_t y);
-    bool    intersect(const Rect& with, Rect* result) const;
+    bool intersect(const Rect& with, Rect* result) const;
 
     // Create a new Rect by transforming this one using a graphics HAL
     // transform.  This rectangle is defined in a coordinate space starting at
@@ -156,6 +159,15 @@
     // (height, width).  Otherwise the output rectangle is in the same space as
     // the input.
     Rect transform(uint32_t xform, int32_t width, int32_t height) const;
+
+    // this calculates (Region(*this) - exclude).bounds() efficiently
+    Rect reduce(const Rect& exclude) const;
+
+
+    // for backward compatibility
+    inline int32_t width() const { return getWidth(); }
+    inline int32_t height() const { return getHeight(); }
+    inline void set(const Rect& rhs) { operator = (rhs); }
 };
 
 ANDROID_BASIC_TYPES_TRAITS(Rect)
diff --git a/include/utils/Debug.h b/include/utils/Debug.h
index d9ed32d..08893bd 100644
--- a/include/utils/Debug.h
+++ b/include/utils/Debug.h
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_DEBUG_H
-#define ANDROID_DEBUG_H
+#ifndef ANDROID_UTILS_DEBUG_H
+#define ANDROID_UTILS_DEBUG_H
 
 #include <stdint.h>
 #include <sys/types.h>
@@ -43,28 +43,6 @@
 #endif
 
 // ---------------------------------------------------------------------------
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-const char* stringForIndent(int32_t indentLevel);
-
-typedef void (*debugPrintFunc)(void* cookie, const char* txt);
-
-void printTypeCode(uint32_t typeCode,
-    debugPrintFunc func = 0, void* cookie = 0);
-
-void printHexData(int32_t indent, const void *buf, size_t length,
-    size_t bytesPerLine=16, int32_t singleLineBytesCutoff=16,
-    size_t alignment=0, bool cArrayStyle=false,
-    debugPrintFunc func = 0, void* cookie = 0);
-
-#ifdef __cplusplus
-}
-#endif
-
-// ---------------------------------------------------------------------------
 }; // namespace android
 
-#endif // ANDROID_DEBUG_H
+#endif // ANDROID_UTILS_DEBUG_H
diff --git a/include/utils/GenerationCache.h b/include/utils/GenerationCache.h
deleted file mode 100644
index 40722d1..0000000
--- a/include/utils/GenerationCache.h
+++ /dev/null
@@ -1,247 +0,0 @@
-/*
- * Copyright (C) 2010 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_UTILS_GENERATION_CACHE_H
-#define ANDROID_UTILS_GENERATION_CACHE_H
-
-#include <utils/KeyedVector.h>
-#include <utils/RefBase.h>
-
-namespace android {
-
-/**
- * GenerationCache callback used when an item is removed
- */
-template<typename EntryKey, typename EntryValue>
-class OnEntryRemoved {
-public:
-    virtual ~OnEntryRemoved() { };
-    virtual void operator()(EntryKey& key, EntryValue& value) = 0;
-}; // class OnEntryRemoved
-
-template<typename EntryKey, typename EntryValue>
-struct Entry: public LightRefBase<Entry<EntryKey, EntryValue> > {
-    Entry(const Entry<EntryKey, EntryValue>& e) :
-            key(e.key), value(e.value),
-            parent(e.parent), child(e.child) { }
-    Entry(const EntryKey& key, const EntryValue& value) :
-            key(key), value(value) { }
-
-    EntryKey key;
-    EntryValue value;
-
-    sp<Entry<EntryKey, EntryValue> > parent; // next older entry
-    sp<Entry<EntryKey, EntryValue> > child;  // next younger entry
-}; // struct Entry
-
-/**
- * A LRU type cache
- */
-template<typename K, typename V>
-class GenerationCache {
-public:
-    GenerationCache(uint32_t maxCapacity);
-    virtual ~GenerationCache();
-
-    enum Capacity {
-        kUnlimitedCapacity,
-    };
-
-    void setOnEntryRemovedListener(OnEntryRemoved<K, V>* listener);
-
-    size_t size() const;
-
-    void clear();
-
-    bool contains(const K& key) const;
-    const K& getKeyAt(size_t index) const;
-    const V& getValueAt(size_t index) const;
-
-    const V& get(const K& key);
-    bool put(const K& key, const V& value);
-
-    void removeAt(ssize_t index);
-    bool remove(const K& key);
-    bool removeOldest();
-
-private:
-    KeyedVector<K, sp<Entry<K, V> > > mCache;
-    uint32_t mMaxCapacity;
-
-    OnEntryRemoved<K, V>* mListener;
-
-    sp<Entry<K, V> > mOldest;
-    sp<Entry<K, V> > mYoungest;
-
-    void attachToCache(const sp<Entry<K, V> >& entry);
-    void detachFromCache(const sp<Entry<K, V> >& entry);
-
-    const V mNullValue;
-}; // class GenerationCache
-
-template<typename K, typename V>
-GenerationCache<K, V>::GenerationCache(uint32_t maxCapacity): mMaxCapacity(maxCapacity),
-    mListener(NULL), mNullValue(NULL) {
-};
-
-template<typename K, typename V>
-GenerationCache<K, V>::~GenerationCache() {
-    clear();
-};
-
-template<typename K, typename V>
-uint32_t GenerationCache<K, V>::size() const {
-    return mCache.size();
-}
-
-/**
- * Should be set by the user of the Cache so that the callback is called whenever an item is
- * removed from the cache
- */
-template<typename K, typename V>
-void GenerationCache<K, V>::setOnEntryRemovedListener(OnEntryRemoved<K, V>* listener) {
-    mListener = listener;
-}
-
-template<typename K, typename V>
-void GenerationCache<K, V>::clear() {
-    if (mListener) {
-        for (uint32_t i = 0; i < mCache.size(); i++) {
-            sp<Entry<K, V> > entry = mCache.valueAt(i);
-            if (mListener) {
-                (*mListener)(entry->key, entry->value);
-            }
-        }
-    }
-    mCache.clear();
-    mYoungest.clear();
-    mOldest.clear();
-}
-
-template<typename K, typename V>
-bool GenerationCache<K, V>::contains(const K& key) const {
-    return mCache.indexOfKey(key) >= 0;
-}
-
-template<typename K, typename V>
-const K& GenerationCache<K, V>::getKeyAt(size_t index) const {
-    return mCache.keyAt(index);
-}
-
-template<typename K, typename V>
-const V& GenerationCache<K, V>::getValueAt(size_t index) const {
-    return mCache.valueAt(index)->value;
-}
-
-template<typename K, typename V>
-const V& GenerationCache<K, V>::get(const K& key) {
-    ssize_t index = mCache.indexOfKey(key);
-    if (index >= 0) {
-        const sp<Entry<K, V> >& entry = mCache.valueAt(index);
-        detachFromCache(entry);
-        attachToCache(entry);
-        return entry->value;
-    }
-
-    return mNullValue;
-}
-
-template<typename K, typename V>
-bool GenerationCache<K, V>::put(const K& key, const V& value) {
-    if (mMaxCapacity != kUnlimitedCapacity && mCache.size() >= mMaxCapacity) {
-        removeOldest();
-    }
-
-    ssize_t index = mCache.indexOfKey(key);
-    if (index < 0) {
-        sp<Entry<K, V> > entry = new Entry<K, V>(key, value);
-        mCache.add(key, entry);
-        attachToCache(entry);
-        return true;
-    }
-
-    return false;
-}
-
-template<typename K, typename V>
-bool GenerationCache<K, V>::remove(const K& key) {
-    ssize_t index = mCache.indexOfKey(key);
-    if (index >= 0) {
-        removeAt(index);
-        return true;
-    }
-
-    return false;
-}
-
-template<typename K, typename V>
-void GenerationCache<K, V>::removeAt(ssize_t index) {
-    sp<Entry<K, V> > entry = mCache.valueAt(index);
-    if (mListener) {
-        (*mListener)(entry->key, entry->value);
-    }
-    mCache.removeItemsAt(index, 1);
-    detachFromCache(entry);
-}
-
-template<typename K, typename V>
-bool GenerationCache<K, V>::removeOldest() {
-    if (mOldest.get()) {
-        ssize_t index = mCache.indexOfKey(mOldest->key);
-        if (index >= 0) {
-            removeAt(index);
-            return true;
-        }
-        ALOGE("GenerationCache: removeOldest failed to find the item in the cache "
-                "with the given key, but we know it must be in there.  "
-                "Is the key comparator kaput?");
-    }
-
-    return false;
-}
-
-template<typename K, typename V>
-void GenerationCache<K, V>::attachToCache(const sp<Entry<K, V> >& entry) {
-    if (!mYoungest.get()) {
-        mYoungest = mOldest = entry;
-    } else {
-        entry->parent = mYoungest;
-        mYoungest->child = entry;
-        mYoungest = entry;
-    }
-}
-
-template<typename K, typename V>
-void GenerationCache<K, V>::detachFromCache(const sp<Entry<K, V> >& entry) {
-    if (entry->parent.get()) {
-        entry->parent->child = entry->child;
-    } else {
-        mOldest = entry->child;
-    }
-
-    if (entry->child.get()) {
-        entry->child->parent = entry->parent;
-    } else {
-        mYoungest = entry->parent;
-    }
-
-    entry->parent.clear();
-    entry->child.clear();
-}
-
-}; // namespace android
-
-#endif // ANDROID_UTILS_GENERATION_CACHE_H
diff --git a/include/utils/Looper.h b/include/utils/Looper.h
index d4a0067..2e0651a 100644
--- a/include/utils/Looper.h
+++ b/include/utils/Looper.h
@@ -297,6 +297,13 @@
     void removeMessages(const sp<MessageHandler>& handler, int what);
 
     /**
+     * Return whether this looper's thread is currently idling -- that is, whether it
+     * stopped waiting for more work to do.  Note that this is intrinsically racy, since
+     * its state can change before you get the result back.
+     */
+    bool isIdling() const;
+
+    /**
      * Prepares a looper associated with the calling thread, and returns it.
      * If the thread already has a looper, it is returned.  Otherwise, a new
      * one is created, associated with the thread, and returned.
@@ -353,6 +360,10 @@
     Vector<MessageEnvelope> mMessageEnvelopes; // guarded by mLock
     bool mSendingMessage; // guarded by mLock
 
+    // Whether we are currently waiting for work.  Not protected by a lock,
+    // any use of it is racy anyway.
+    volatile bool mIdling;
+
     int mEpollFd; // immutable
 
     // Locked list of file descriptor monitoring requests.
diff --git a/include/utils/LruCache.h b/include/utils/LruCache.h
index 302b929..053bfaf 100644
--- a/include/utils/LruCache.h
+++ b/include/utils/LruCache.h
@@ -18,12 +18,19 @@
 #define ANDROID_UTILS_LRU_CACHE_H
 
 #include <utils/BasicHashtable.h>
-#include <utils/GenerationCache.h>
 #include <utils/UniquePtr.h>
 
 namespace android {
 
-// OnEntryRemoved is defined in GenerationCache.h, but maybe should move here.
+/**
+ * GenerationCache callback used when an item is removed
+ */
+template<typename EntryKey, typename EntryValue>
+class OnEntryRemoved {
+public:
+    virtual ~OnEntryRemoved() { };
+    virtual void operator()(EntryKey& key, EntryValue& value) = 0;
+}; // class OnEntryRemoved
 
 template <typename TKey, typename TValue>
 class LruCache {
diff --git a/include/utils/String16.h b/include/utils/String16.h
index fe06c57..d131bfc 100644
--- a/include/utils/String16.h
+++ b/include/utils/String16.h
@@ -41,7 +41,16 @@
 class String16
 {
 public:
+    /* use String16(StaticLinkage) if you're statically linking against
+     * libutils and declaring an empty static String16, e.g.:
+     *
+     *   static String16 sAStaticEmptyString(String16::kEmptyString);
+     *   static String16 sAnotherStaticEmptyString(sAStaticEmptyString);
+     */
+    enum StaticLinkage { kEmptyString };
+
                                 String16();
+    explicit                    String16(StaticLinkage);
                                 String16(const String16& o);
                                 String16(const String16& o,
                                          size_t len,
@@ -117,8 +126,6 @@
 // require any change to the underlying SharedBuffer contents or reference count.
 ANDROID_TRIVIAL_MOVE_TRAIT(String16)
 
-TextOutput& operator<<(TextOutput& to, const String16& val);
-
 // ---------------------------------------------------------------------------
 // No user servicable parts below.
 
diff --git a/include/utils/String8.h b/include/utils/String8.h
index 335e7f1..ef59470 100644
--- a/include/utils/String8.h
+++ b/include/utils/String8.h
@@ -37,7 +37,16 @@
 class String8
 {
 public:
+    /* use String8(StaticLinkage) if you're statically linking against
+     * libutils and declaring an empty static String8, e.g.:
+     *
+     *   static String8 sAStaticEmptyString(String8::kEmptyString);
+     *   static String8 sAnotherStaticEmptyString(sAStaticEmptyString);
+     */
+    enum StaticLinkage { kEmptyString };
+
                                 String8();
+    explicit                    String8(StaticLinkage);
                                 String8(const String8& o);
     explicit                    String8(const char* o);
     explicit                    String8(const char* o, size_t numChars);
@@ -224,8 +233,6 @@
 // require any change to the underlying SharedBuffer contents or reference count.
 ANDROID_TRIVIAL_MOVE_TRAIT(String8)
 
-TextOutput& operator<<(TextOutput& to, const String16& val);
-
 // ---------------------------------------------------------------------------
 // No user servicable parts below.
 
diff --git a/include/utils/StringArray.h b/include/utils/StringArray.h
deleted file mode 100644
index c2445871..0000000
--- a/include/utils/StringArray.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * 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.
- */
-
-//
-// Sortable array of strings.  STL-ish, but STL-free.
-//  
-#ifndef _LIBS_UTILS_STRING_ARRAY_H
-#define _LIBS_UTILS_STRING_ARRAY_H
-
-#include <stdlib.h>
-#include <string.h>
-
-namespace android {
-
-//
-// An expanding array of strings.  Add, get, sort, delete.
-//
-class StringArray {
-public:
-    StringArray();
-    virtual ~StringArray();
-
-    //
-    // Add a string.  A copy of the string is made.
-    //
-    bool push_back(const char* str);
-
-    //
-    // Delete an entry.
-    //
-    void erase(int idx);
-
-    //
-    // Sort the array.
-    //
-    void sort(int (*compare)(const void*, const void*));
-    
-    //
-    // Pass this to the sort routine to do an ascending alphabetical sort.
-    //
-    static int cmpAscendingAlpha(const void* pstr1, const void* pstr2);
-    
-    //
-    // Get the #of items in the array.
-    //
-    inline int size(void) const { return mCurrent; }
-
-    //
-    // Return entry N.
-    // [should use operator[] here]
-    //
-    const char* getEntry(int idx) const {
-        return (unsigned(idx) >= unsigned(mCurrent)) ? NULL : mArray[idx];
-    }
-
-    //
-    // Set entry N to specified string.
-    // [should use operator[] here]
-    //
-    void setEntry(int idx, const char* str);
-
-private:
-    int     mMax;
-    int     mCurrent;
-    char**  mArray;
-};
-
-}; // namespace android
-
-#endif // _LIBS_UTILS_STRING_ARRAY_H
diff --git a/include/utils/StrongPointer.h b/include/utils/StrongPointer.h
index 49fa3a8..aba9577 100644
--- a/include/utils/StrongPointer.h
+++ b/include/utils/StrongPointer.h
@@ -26,9 +26,6 @@
 // ---------------------------------------------------------------------------
 namespace android {
 
-class TextOutput;
-TextOutput& printStrongPointer(TextOutput& to, const void* val);
-
 template<typename T> class wp;
 
 // ---------------------------------------------------------------------------
@@ -58,9 +55,8 @@
 
 // ---------------------------------------------------------------------------
 
-template <typename T>
-class sp
-{
+template<typename T>
+class sp {
 public:
     inline sp() : m_ptr(0) { }
 
@@ -110,92 +106,93 @@
 
 #undef COMPARE
 
-template <typename T>
-TextOutput& operator<<(TextOutput& to, const sp<T>& val);
-
 // ---------------------------------------------------------------------------
 // No user serviceable parts below here.
 
 template<typename T>
 sp<T>::sp(T* other)
-: m_ptr(other)
-  {
-    if (other) other->incStrong(this);
-  }
+        : m_ptr(other) {
+    if (other)
+        other->incStrong(this);
+}
 
 template<typename T>
 sp<T>::sp(const sp<T>& other)
-: m_ptr(other.m_ptr)
-  {
-    if (m_ptr) m_ptr->incStrong(this);
-  }
+        : m_ptr(other.m_ptr) {
+    if (m_ptr)
+        m_ptr->incStrong(this);
+}
 
 template<typename T> template<typename U>
-sp<T>::sp(U* other) : m_ptr(other)
-{
-    if (other) ((T*)other)->incStrong(this);
+sp<T>::sp(U* other)
+        : m_ptr(other) {
+    if (other)
+        ((T*) other)->incStrong(this);
 }
 
 template<typename T> template<typename U>
 sp<T>::sp(const sp<U>& other)
-: m_ptr(other.m_ptr)
-  {
-    if (m_ptr) m_ptr->incStrong(this);
-  }
-
-template<typename T>
-sp<T>::~sp()
-{
-    if (m_ptr) m_ptr->decStrong(this);
+        : m_ptr(other.m_ptr) {
+    if (m_ptr)
+        m_ptr->incStrong(this);
 }
 
 template<typename T>
-sp<T>& sp<T>::operator = (const sp<T>& other) {
+sp<T>::~sp() {
+    if (m_ptr)
+        m_ptr->decStrong(this);
+}
+
+template<typename T>
+sp<T>& sp<T>::operator =(const sp<T>& other) {
     T* otherPtr(other.m_ptr);
-    if (otherPtr) otherPtr->incStrong(this);
-    if (m_ptr) m_ptr->decStrong(this);
+    if (otherPtr)
+        otherPtr->incStrong(this);
+    if (m_ptr)
+        m_ptr->decStrong(this);
     m_ptr = otherPtr;
     return *this;
 }
 
 template<typename T>
-sp<T>& sp<T>::operator = (T* other)
-{
-    if (other) other->incStrong(this);
-    if (m_ptr) m_ptr->decStrong(this);
+sp<T>& sp<T>::operator =(T* other) {
+    if (other)
+        other->incStrong(this);
+    if (m_ptr)
+        m_ptr->decStrong(this);
     m_ptr = other;
     return *this;
 }
 
 template<typename T> template<typename U>
-sp<T>& sp<T>::operator = (const sp<U>& other)
-{
+sp<T>& sp<T>::operator =(const sp<U>& other) {
     T* otherPtr(other.m_ptr);
-    if (otherPtr) otherPtr->incStrong(this);
-    if (m_ptr) m_ptr->decStrong(this);
+    if (otherPtr)
+        otherPtr->incStrong(this);
+    if (m_ptr)
+        m_ptr->decStrong(this);
     m_ptr = otherPtr;
     return *this;
 }
 
 template<typename T> template<typename U>
-sp<T>& sp<T>::operator = (U* other)
-{
-    if (other) ((T*)other)->incStrong(this);
-    if (m_ptr) m_ptr->decStrong(this);
+sp<T>& sp<T>::operator =(U* other) {
+    if (other)
+        ((T*) other)->incStrong(this);
+    if (m_ptr)
+        m_ptr->decStrong(this);
     m_ptr = other;
     return *this;
 }
 
-template<typename T>    
-void sp<T>::force_set(T* other)
-{
+template<typename T>
+void sp<T>::force_set(T* other) {
     other->forceIncStrong(this);
     m_ptr = other;
 }
 
 template<typename T>
-void sp<T>::clear()
-{
+void sp<T>::clear() {
     if (m_ptr) {
         m_ptr->decStrong(this);
         m_ptr = 0;
@@ -207,12 +204,6 @@
     m_ptr = ptr;
 }
 
-template <typename T>
-inline TextOutput& operator<<(TextOutput& to, const sp<T>& val)
-{
-    return printStrongPointer(to, val.get());
-}
-
 }; // namespace android
 
 // ---------------------------------------------------------------------------
diff --git a/include/utils/SystemClock.h b/include/utils/SystemClock.h
index d75264c..01db340 100644
--- a/include/utils/SystemClock.h
+++ b/include/utils/SystemClock.h
@@ -22,7 +22,6 @@
 
 namespace android {
 
-int setCurrentTimeMillis(int64_t millis);
 int64_t uptimeMillis();
 int64_t elapsedRealtime();
 int64_t elapsedRealtimeNano();
diff --git a/include/utils/Timers.h b/include/utils/Timers.h
index 92f66c9..d015421 100644
--- a/include/utils/Timers.h
+++ b/include/utils/Timers.h
@@ -103,43 +103,4 @@
 } // extern "C"
 #endif
 
-// ------------------------------------------------------------------
-// C++ API
-
-#ifdef __cplusplus
-
-namespace android {
-/*
- * Time the duration of something.
- *
- * Includes some timeval manipulation functions.
- */
-class DurationTimer {
-public:
-    DurationTimer() {}
-    ~DurationTimer() {}
-
-    // Start the timer.
-    void start();
-    // Stop the timer.
-    void stop();
-    // Get the duration in microseconds.
-    long long durationUsecs() const;
-
-    // Subtract two timevals.  Returns the difference (ptv1-ptv2) in
-    // microseconds.
-    static long long subtractTimevals(const struct timeval* ptv1,
-        const struct timeval* ptv2);
-
-    // Add the specified amount of time to the timeval.
-    static void addToTimeval(struct timeval* ptv, long usec);
-
-private:
-    struct timeval  mStartWhen;
-    struct timeval  mStopWhen;
-};
-
-}; // android
-#endif // def __cplusplus
-
 #endif // _LIBS_UTILS_TIMERS_H
diff --git a/include/utils/Trace.h b/include/utils/Trace.h
index 49578c4..6ee343d 100644
--- a/include/utils/Trace.h
+++ b/include/utils/Trace.h
@@ -17,6 +17,8 @@
 #ifndef ANDROID_TRACE_H
 #define ANDROID_TRACE_H
 
+#ifdef HAVE_ANDROID_OS
+
 #include <fcntl.h>
 #include <stdint.h>
 #include <stdio.h>
@@ -57,4 +59,11 @@
 
 }; // namespace android
 
+#else // HAVE_ANDROID_OS
+
+#define ATRACE_NAME(...)
+#define ATRACE_CALL()
+
+#endif // HAVE_ANDROID_OS
+
 #endif // ANDROID_TRACE_H
diff --git a/include/utils/VectorImpl.h b/include/utils/VectorImpl.h
index 9bc50e6..21ad71c 100644
--- a/include/utils/VectorImpl.h
+++ b/include/utils/VectorImpl.h
@@ -105,16 +105,6 @@
     virtual void            do_splat(void* dest, const void* item, size_t num) const = 0;
     virtual void            do_move_forward(void* dest, const void* from, size_t num) const = 0;
     virtual void            do_move_backward(void* dest, const void* from, size_t num) const = 0;
-
-    // take care of FBC...
-    virtual void            reservedVectorImpl1();
-    virtual void            reservedVectorImpl2();
-    virtual void            reservedVectorImpl3();
-    virtual void            reservedVectorImpl4();
-    virtual void            reservedVectorImpl5();
-    virtual void            reservedVectorImpl6();
-    virtual void            reservedVectorImpl7();
-    virtual void            reservedVectorImpl8();
     
 private:
         void* _grow(size_t where, size_t amount);
@@ -166,16 +156,6 @@
 protected:
     virtual int             do_compare(const void* lhs, const void* rhs) const = 0;
 
-    // take care of FBC...
-    virtual void            reservedSortedVectorImpl1();
-    virtual void            reservedSortedVectorImpl2();
-    virtual void            reservedSortedVectorImpl3();
-    virtual void            reservedSortedVectorImpl4();
-    virtual void            reservedSortedVectorImpl5();
-    virtual void            reservedSortedVectorImpl6();
-    virtual void            reservedSortedVectorImpl7();
-    virtual void            reservedSortedVectorImpl8();
-
 private:
             ssize_t         _indexOrderOf(const void* item, size_t* order = 0) const;
 
diff --git a/include/utils/WorkQueue.h b/include/utils/WorkQueue.h
deleted file mode 100644
index e3c75b2..0000000
--- a/include/utils/WorkQueue.h
+++ /dev/null
@@ -1,119 +0,0 @@
-/*]
- * Copyright (C) 2012 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 _LIBS_UTILS_WORK_QUEUE_H
-#define _LIBS_UTILS_WORK_QUEUE_H
-
-#include <utils/Errors.h>
-#include <utils/Vector.h>
-#include <utils/threads.h>
-
-namespace android {
-
-/*
- * A threaded work queue.
- *
- * This class is designed to make it easy to run a bunch of isolated work
- * units in parallel, using up to the specified number of threads.
- * To use it, write a loop to post work units to the work queue, then synchronize
- * on the queue at the end.
- */
-class WorkQueue {
-public:
-    class WorkUnit {
-    public:
-        WorkUnit() { }
-        virtual ~WorkUnit() { }
-
-        /*
-         * Runs the work unit.
-         * If the result is 'true' then the work queue continues scheduling work as usual.
-         * If the result is 'false' then the work queue is canceled.
-         */
-        virtual bool run() = 0;
-    };
-
-    /* Creates a work queue with the specified maximum number of work threads. */
-    WorkQueue(size_t maxThreads, bool canCallJava = true);
-
-    /* Destroys the work queue.
-     * Cancels pending work and waits for all remaining threads to complete.
-     */
-    ~WorkQueue();
-
-    /* Posts a work unit to run later.
-     * If the work queue has been canceled or is already finished, returns INVALID_OPERATION
-     * and does not take ownership of the work unit (caller must destroy it itself).
-     * Otherwise, returns OK and takes ownership of the work unit (the work queue will
-     * destroy it automatically).
-     *
-     * For flow control, this method blocks when the size of the pending work queue is more
-     * 'backlog' times the number of threads.  This condition reduces the rate of entry into
-     * the pending work queue and prevents it from growing much more rapidly than the
-     * work threads can actually handle.
-     *
-     * If 'backlog' is 0, then no throttle is applied.
-     */
-    status_t schedule(WorkUnit* workUnit, size_t backlog = 2);
-
-    /* Cancels all pending work.
-     * If the work queue is already finished, returns INVALID_OPERATION.
-     * If the work queue is already canceled, returns OK and does nothing else.
-     * Otherwise, returns OK, discards all pending work units and prevents additional
-     * work units from being scheduled.
-     *
-     * Call finish() after cancel() to wait for all remaining work to complete.
-     */
-    status_t cancel();
-
-    /* Waits for all work to complete.
-     * If the work queue is already finished, returns INVALID_OPERATION.
-     * Otherwise, waits for all work to complete and returns OK.
-     */
-    status_t finish();
-
-private:
-    class WorkThread : public Thread {
-    public:
-        WorkThread(WorkQueue* workQueue, bool canCallJava);
-        virtual ~WorkThread();
-
-    private:
-        virtual bool threadLoop();
-
-        WorkQueue* const mWorkQueue;
-    };
-
-    status_t cancelLocked();
-    bool threadLoop(); // called from each work thread
-
-    const size_t mMaxThreads;
-    const bool mCanCallJava;
-
-    Mutex mLock;
-    Condition mWorkChangedCondition;
-    Condition mWorkDequeuedCondition;
-
-    bool mCanceled;
-    bool mFinished;
-    size_t mIdleThreads;
-    Vector<sp<WorkThread> > mWorkThreads;
-    Vector<WorkUnit*> mWorkUnits;
-};
-
-}; // namespace android
-
-#endif // _LIBS_UTILS_WORK_QUEUE_H
diff --git a/include/utils/ZipFileCRO.h b/include/utils/ZipFileCRO.h
deleted file mode 100644
index 3e42a95..0000000
--- a/include/utils/ZipFileCRO.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * 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.
- */
-
-//
-// C API for ead-only access to Zip archives, with minimal heap allocation.
-//
-#ifndef __LIBS_ZIPFILECRO_H
-#define __LIBS_ZIPFILECRO_H
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include <utils/Compat.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * Trivial typedef to ensure that ZipFileCRO is not treated as a simple integer.
- */
-typedef void* ZipFileCRO;
-
-/*
- * Trivial typedef to ensure that ZipEntryCRO is not treated as a simple
- * integer.  We use NULL to indicate an invalid value.
- */
-typedef void* ZipEntryCRO;
-
-extern ZipFileCRO ZipFileXRO_open(const char* path);
-
-extern void ZipFileCRO_destroy(ZipFileCRO zip);
-
-extern ZipEntryCRO ZipFileCRO_findEntryByName(ZipFileCRO zip,
-        const char* fileName);
-
-extern bool ZipFileCRO_getEntryInfo(ZipFileCRO zip, ZipEntryCRO entry,
-        int* pMethod, size_t* pUncompLen,
-        size_t* pCompLen, off64_t* pOffset, long* pModWhen, long* pCrc32);
-
-extern bool ZipFileCRO_uncompressEntry(ZipFileCRO zip, ZipEntryCRO entry, int fd);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /*__LIBS_ZIPFILECRO_H*/
diff --git a/include/utils/ZipFileRO.h b/include/utils/ZipFileRO.h
deleted file mode 100644
index 547e36a..0000000
--- a/include/utils/ZipFileRO.h
+++ /dev/null
@@ -1,262 +0,0 @@
-/*
- * 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.
- */
-
-/*
- * Read-only access to Zip archives, with minimal heap allocation.
- *
- * This is similar to the more-complete ZipFile class, but no attempt
- * has been made to make them interchangeable.  This class operates under
- * a very different set of assumptions and constraints.
- *
- * One such assumption is that if you're getting file descriptors for
- * use with this class as a child of a fork() operation, you must be on
- * a pread() to guarantee correct operation. This is because pread() can
- * atomically read at a file offset without worrying about a lock around an
- * lseek() + read() pair.
- */
-#ifndef __LIBS_ZIPFILERO_H
-#define __LIBS_ZIPFILERO_H
-
-#include <utils/Compat.h>
-#include <utils/Errors.h>
-#include <utils/FileMap.h>
-#include <utils/threads.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <time.h>
-
-namespace android {
-
-/*
- * Trivial typedef to ensure that ZipEntryRO is not treated as a simple
- * integer.  We use NULL to indicate an invalid value.
- */
-typedef void* ZipEntryRO;
-
-/*
- * Open a Zip archive for reading.
- *
- * We want "open" and "find entry by name" to be fast operations, and we
- * want to use as little memory as possible.  We memory-map the file,
- * and load a hash table with pointers to the filenames (which aren't
- * null-terminated).  The other fields are at a fixed offset from the
- * filename, so we don't need to extract those (but we do need to byte-read
- * and endian-swap them every time we want them).
- *
- * To speed comparisons when doing a lookup by name, we could make the mapping
- * "private" (copy-on-write) and null-terminate the filenames after verifying
- * the record structure.  However, this requires a private mapping of
- * every page that the Central Directory touches.  Easier to tuck a copy
- * of the string length into the hash table entry.
- *
- * NOTE: If this is used on file descriptors inherited from a fork() operation,
- * you must be on a platform that implements pread() to guarantee correctness
- * on the shared file descriptors.
- */
-class ZipFileRO {
-public:
-    ZipFileRO()
-        : mFd(-1), mFileName(NULL), mFileLength(-1),
-          mDirectoryMap(NULL),
-          mNumEntries(-1), mDirectoryOffset(-1),
-          mHashTableSize(-1), mHashTable(NULL)
-        {}
-
-    ~ZipFileRO();
-
-    /*
-     * Open an archive.
-     */
-    status_t open(const char* zipFileName);
-
-    /*
-     * Find an entry, by name.  Returns the entry identifier, or NULL if
-     * not found.
-     *
-     * If two entries have the same name, one will be chosen at semi-random.
-     */
-    ZipEntryRO findEntryByName(const char* fileName) const;
-
-    /*
-     * Return the #of entries in the Zip archive.
-     */
-    int getNumEntries(void) const {
-        return mNumEntries;
-    }
-
-    /*
-     * Return the Nth entry.  Zip file entries are not stored in sorted
-     * order, and updated entries may appear at the end, so anyone walking
-     * the archive needs to avoid making ordering assumptions.  We take
-     * that further by returning the Nth non-empty entry in the hash table
-     * rather than the Nth entry in the archive.
-     *
-     * Valid values are [0..numEntries).
-     *
-     * [This is currently O(n).  If it needs to be fast we can allocate an
-     * additional data structure or provide an iterator interface.]
-     */
-    ZipEntryRO findEntryByIndex(int idx) const;
-
-    /*
-     * Copy the filename into the supplied buffer.  Returns 0 on success,
-     * -1 if "entry" is invalid, or the filename length if it didn't fit.  The
-     * length, and the returned string, include the null-termination.
-     */
-    int getEntryFileName(ZipEntryRO entry, char* buffer, int bufLen) const;
-
-    /*
-     * Get the vital stats for an entry.  Pass in NULL pointers for anything
-     * you don't need.
-     *
-     * "*pOffset" holds the Zip file offset of the entry's data.
-     *
-     * Returns "false" if "entry" is bogus or if the data in the Zip file
-     * appears to be bad.
-     */
-    bool getEntryInfo(ZipEntryRO entry, int* pMethod, size_t* pUncompLen,
-        size_t* pCompLen, off64_t* pOffset, long* pModWhen, long* pCrc32) const;
-
-    /*
-     * Create a new FileMap object that maps a subset of the archive.  For
-     * an uncompressed entry this effectively provides a pointer to the
-     * actual data, for a compressed entry this provides the input buffer
-     * for inflate().
-     */
-    FileMap* createEntryFileMap(ZipEntryRO entry) const;
-
-    /*
-     * Uncompress the data into a buffer.  Depending on the compression
-     * format, this is either an "inflate" operation or a memcpy.
-     *
-     * Use "uncompLen" from getEntryInfo() to determine the required
-     * buffer size.
-     *
-     * Returns "true" on success.
-     */
-    bool uncompressEntry(ZipEntryRO entry, void* buffer) const;
-
-    /*
-     * Uncompress the data to an open file descriptor.
-     */
-    bool uncompressEntry(ZipEntryRO entry, int fd) const;
-
-    /* Zip compression methods we support */
-    enum {
-        kCompressStored     = 0,        // no compression
-        kCompressDeflated   = 8,        // standard deflate
-    };
-
-    /*
-     * Utility function: uncompress deflated data, buffer to buffer.
-     */
-    static bool inflateBuffer(void* outBuf, const void* inBuf,
-        size_t uncompLen, size_t compLen);
-
-    /*
-     * Utility function: uncompress deflated data, buffer to fd.
-     */
-    static bool inflateBuffer(int fd, const void* inBuf,
-        size_t uncompLen, size_t compLen);
-
-    /*
-     * Utility function to convert ZIP's time format to a timespec struct.
-     */
-    static inline void zipTimeToTimespec(long when, struct tm* timespec) {
-        const long date = when >> 16;
-        timespec->tm_year = ((date >> 9) & 0x7F) + 80; // Zip is years since 1980
-        timespec->tm_mon = (date >> 5) & 0x0F;
-        timespec->tm_mday = date & 0x1F;
-
-        timespec->tm_hour = (when >> 11) & 0x1F;
-        timespec->tm_min = (when >> 5) & 0x3F;
-        timespec->tm_sec = (when & 0x1F) << 1;
-    }
-
-    /*
-     * Some basic functions for raw data manipulation.  "LE" means
-     * Little Endian.
-     */
-    static inline unsigned short get2LE(const unsigned char* buf) {
-        return buf[0] | (buf[1] << 8);
-    }
-    static inline unsigned long get4LE(const unsigned char* buf) {
-        return buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
-    }
-
-private:
-    /* these are private and not defined */ 
-    ZipFileRO(const ZipFileRO& src);
-    ZipFileRO& operator=(const ZipFileRO& src);
-
-    /* locate and parse the central directory */
-    bool mapCentralDirectory(void);
-
-    /* parse the archive, prepping internal structures */
-    bool parseZipArchive(void);
-
-    /* add a new entry to the hash table */
-    void addToHash(const char* str, int strLen, unsigned int hash);
-
-    /* compute string hash code */
-    static unsigned int computeHash(const char* str, int len);
-
-    /* convert a ZipEntryRO back to a hash table index */
-    int entryToIndex(const ZipEntryRO entry) const;
-
-    /*
-     * One entry in the hash table.
-     */
-    typedef struct HashEntry {
-        const char*     name;
-        unsigned short  nameLen;
-        //unsigned int    hash;
-    } HashEntry;
-
-    /* open Zip archive */
-    int         mFd;
-
-    /* Lock for handling the file descriptor (seeks, etc) */
-    mutable Mutex mFdLock;
-
-    /* zip file name */
-    char*       mFileName;
-
-    /* length of file */
-    size_t      mFileLength;
-
-    /* mapped file */
-    FileMap*    mDirectoryMap;
-
-    /* number of entries in the Zip archive */
-    int         mNumEntries;
-
-    /* CD directory offset in the Zip archive */
-    off64_t     mDirectoryOffset;
-
-    /*
-     * We know how many entries are in the Zip archive, so we have a
-     * fixed-size hash table.  We probe for an empty slot.
-     */
-    int         mHashTableSize;
-    HashEntry*  mHashTable;
-};
-
-}; // namespace android
-
-#endif /*__LIBS_ZIPFILERO_H*/
diff --git a/include/utils/ZipUtils.h b/include/utils/ZipUtils.h
deleted file mode 100644
index 42c42b6..0000000
--- a/include/utils/ZipUtils.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * 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.
- */
-
-//
-// Miscellaneous zip/gzip utility functions.
-//
-#ifndef __LIBS_ZIPUTILS_H
-#define __LIBS_ZIPUTILS_H
-
-#include <stdio.h>
-
-namespace android {
-
-/*
- * Container class for utility functions, primarily for namespace reasons.
- */
-class ZipUtils {
-public:
-    /*
-     * General utility function for uncompressing "deflate" data from a file
-     * to a buffer.
-     */
-    static bool inflateToBuffer(int fd, void* buf, long uncompressedLen,
-        long compressedLen);
-    static bool inflateToBuffer(FILE* fp, void* buf, long uncompressedLen,
-        long compressedLen);
-
-    /*
-     * Someday we might want to make this generic and handle bzip2 ".bz2"
-     * files too.
-     *
-     * We could declare gzip to be a sub-class of zip that has exactly
-     * one always-compressed entry, but we currently want to treat Zip
-     * and gzip as distinct, so there's no value.
-     *
-     * The zlib library has some gzip utilities, but it has no interface
-     * for extracting the uncompressed length of the file (you do *not*
-     * want to gzseek to the end).
-     *
-     * Pass in a seeked file pointer for the gzip file.  If this is a gzip
-     * file, we set our return values appropriately and return "true" with
-     * the file seeked to the start of the compressed data.
-     */
-    static bool examineGzip(FILE* fp, int* pCompressionMethod,
-        long* pUncompressedLen, long* pCompressedLen, unsigned long* pCRC32);
-
-private:
-    ZipUtils() {}
-    ~ZipUtils() {}
-};
-
-}; // namespace android
-
-#endif /*__LIBS_ZIPUTILS_H*/
diff --git a/include/utils/misc.h b/include/utils/misc.h
index f1aa432..6cccec3 100644
--- a/include/utils/misc.h
+++ b/include/utils/misc.h
@@ -20,7 +20,6 @@
 #ifndef _LIBS_UTILS_MISC_H
 #define _LIBS_UTILS_MISC_H
 
-#include <sys/time.h>
 #include <utils/Endian.h>
 
 /* get #of elements in a static array */
@@ -30,26 +29,6 @@
 
 namespace android {
 
-/*
- * Some utility functions for working with files.  These could be made
- * part of a "File" class.
- */
-typedef enum FileType {
-    kFileTypeUnknown = 0,
-    kFileTypeNonexistent,       // i.e. ENOENT
-    kFileTypeRegular,
-    kFileTypeDirectory,
-    kFileTypeCharDev,
-    kFileTypeBlockDev,
-    kFileTypeFifo,
-    kFileTypeSymlink,
-    kFileTypeSocket,
-} FileType;
-/* get the file's type; follows symlinks */
-FileType getFileType(const char* fileName);
-/* get the file's modification date; returns -1 w/errno set on failure */
-time_t getFileModDate(const char* fileName);
-
 typedef void (*sysprop_change_callback)(void);
 void add_sysprop_change_callback(sysprop_change_callback cb, int priority);
 void report_sysprop_change();
diff --git a/libs/binder/Android.mk b/libs/binder/Android.mk
index 994d3db..4c8820e 100644
--- a/libs/binder/Android.mk
+++ b/libs/binder/Android.mk
@@ -17,6 +17,8 @@
     AppOpsManager.cpp \
     Binder.cpp \
     BpBinder.cpp \
+    BufferedTextOutput.cpp \
+    Debug.cpp \
     IAppOpsCallback.cpp \
     IAppOpsService.cpp \
     IInterface.cpp \
@@ -30,7 +32,8 @@
     Parcel.cpp \
     PermissionCache.cpp \
     ProcessState.cpp \
-    Static.cpp
+    Static.cpp \
+    TextOutput.cpp \
 
 LOCAL_PATH:= $(call my-dir)
 
diff --git a/libs/utils/BufferedTextOutput.cpp b/libs/binder/BufferedTextOutput.cpp
similarity index 98%
rename from libs/utils/BufferedTextOutput.cpp
rename to libs/binder/BufferedTextOutput.cpp
index 989662e..2d493c1 100644
--- a/libs/utils/BufferedTextOutput.cpp
+++ b/libs/binder/BufferedTextOutput.cpp
@@ -14,16 +14,16 @@
  * limitations under the License.
  */
 
-#include <utils/BufferedTextOutput.h>
+#include <binder/BufferedTextOutput.h>
+#include <binder/Debug.h>
 
 #include <utils/Atomic.h>
-#include <utils/Debug.h>
 #include <utils/Log.h>
 #include <utils/RefBase.h>
 #include <utils/Vector.h>
 #include <cutils/threads.h>
 
-#include <private/utils/Static.h>
+#include <private/binder/Static.h>
 
 #include <stdio.h>
 #include <stdlib.h>
diff --git a/libs/utils/Debug.cpp b/libs/binder/Debug.cpp
similarity index 96%
rename from libs/utils/Debug.cpp
rename to libs/binder/Debug.cpp
index e8ac983..a8b6e83 100644
--- a/libs/utils/Debug.cpp
+++ b/libs/binder/Debug.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include <utils/Debug.h>
+#include <binder/Debug.h>
 
 #include <utils/misc.h>
 
@@ -70,20 +70,6 @@
     return out;
 }
 
-static inline char makeupperhexdigit(uint32_t val)
-{
-    return "0123456789ABCDEF"[val&0xF];
-}
-
-static char* appendupperhexnum(uint32_t val, char* out)
-{
-    for( int32_t i=28; i>=0; i-=4 ) {
-        *out++ = makeupperhexdigit( val>>i );
-    }
-    *out = 0;
-    return out;
-}
-
 static char* appendcharornum(char c, char* out, bool skipzero = true)
 {
     if (skipzero && c == 0) return out;
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index 6e83faa..2780d9a 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -20,10 +20,11 @@
 
 #include <binder/Binder.h>
 #include <binder/BpBinder.h>
+#include <binder/TextOutput.h>
+
 #include <cutils/sched_policy.h>
 #include <utils/Debug.h>
 #include <utils/Log.h>
-#include <utils/TextOutput.h>
 #include <utils/threads.h>
 
 #include <private/binder/binder_module.h>
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 8f7f7e7..aa19d17 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -22,12 +22,13 @@
 #include <binder/IPCThreadState.h>
 #include <binder/Binder.h>
 #include <binder/BpBinder.h>
-#include <utils/Debug.h>
 #include <binder/ProcessState.h>
+#include <binder/TextOutput.h>
+
+#include <utils/Debug.h>
 #include <utils/Log.h>
 #include <utils/String8.h>
 #include <utils/String16.h>
-#include <utils/TextOutput.h>
 #include <utils/misc.h>
 #include <utils/Flattenable.h>
 #include <cutils/ashmem.h>
diff --git a/libs/binder/Static.cpp b/libs/binder/Static.cpp
index 12b0308..2062692 100644
--- a/libs/binder/Static.cpp
+++ b/libs/binder/Static.cpp
@@ -19,30 +19,76 @@
 
 #include <private/binder/Static.h>
 
+#include <binder/BufferedTextOutput.h>
 #include <binder/IPCThreadState.h>
 #include <utils/Log.h>
 
 namespace android {
 
+// ------------ Text output streams
+
+Vector<int32_t> gTextBuffers;
+
+class LogTextOutput : public BufferedTextOutput
+{
+public:
+    LogTextOutput() : BufferedTextOutput(MULTITHREADED) { }
+    virtual ~LogTextOutput() { };
+
+protected:
+    virtual status_t writeLines(const struct iovec& vec, size_t N)
+    {
+        //android_writevLog(&vec, N);       <-- this is now a no-op
+        if (N != 1) ALOGI("WARNING: writeLines N=%zu\n", N);
+        ALOGI("%.*s", (int)vec.iov_len, (const char*) vec.iov_base);
+        return NO_ERROR;
+    }
+};
+
+class FdTextOutput : public BufferedTextOutput
+{
+public:
+    FdTextOutput(int fd) : BufferedTextOutput(MULTITHREADED), mFD(fd) { }
+    virtual ~FdTextOutput() { };
+
+protected:
+    virtual status_t writeLines(const struct iovec& vec, size_t N)
+    {
+        writev(mFD, &vec, N);
+        return NO_ERROR;
+    }
+
+private:
+    int mFD;
+};
+
+static LogTextOutput gLogTextOutput;
+static FdTextOutput gStdoutTextOutput(STDOUT_FILENO);
+static FdTextOutput gStderrTextOutput(STDERR_FILENO);
+
+TextOutput& alog(gLogTextOutput);
+TextOutput& aout(gStdoutTextOutput);
+TextOutput& aerr(gStderrTextOutput);
+
 // ------------ ProcessState.cpp
 
 Mutex gProcessMutex;
 sp<ProcessState> gProcess;
 
-class LibUtilsIPCtStatics
+class LibBinderIPCtStatics
 {
 public:
-    LibUtilsIPCtStatics()
+    LibBinderIPCtStatics()
     {
     }
     
-    ~LibUtilsIPCtStatics()
+    ~LibBinderIPCtStatics()
     {
         IPCThreadState::shutdown();
     }
 };
 
-static LibUtilsIPCtStatics gIPCStatics;
+static LibBinderIPCtStatics gIPCStatics;
 
 // ------------ ServiceManager.cpp
 
diff --git a/libs/utils/TextOutput.cpp b/libs/binder/TextOutput.cpp
similarity index 98%
rename from libs/utils/TextOutput.cpp
rename to libs/binder/TextOutput.cpp
index e04823d..9637334 100644
--- a/libs/utils/TextOutput.cpp
+++ b/libs/binder/TextOutput.cpp
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-#include <utils/TextOutput.h>
+#include <binder/TextOutput.h>
 
-#include <utils/Debug.h>
+#include <binder/Debug.h>
 
 #include <stdio.h>
 #include <stdlib.h>
diff --git a/libs/gui/BufferItemConsumer.cpp b/libs/gui/BufferItemConsumer.cpp
index 7db1b84..ba04bdf 100644
--- a/libs/gui/BufferItemConsumer.cpp
+++ b/libs/gui/BufferItemConsumer.cpp
@@ -82,9 +82,9 @@
 
     Mutex::Autolock _l(mMutex);
 
-    err = addReleaseFenceLocked(item.mBuf, releaseFence);
+    err = addReleaseFenceLocked(item.mBuf, item.mGraphicBuffer, releaseFence);
 
-    err = releaseBufferLocked(item.mBuf, EGL_NO_DISPLAY,
+    err = releaseBufferLocked(item.mBuf, item.mGraphicBuffer, EGL_NO_DISPLAY,
             EGL_NO_SYNC_KHR);
     if (err != OK) {
         BI_LOGE("Failed to release buffer: %s (%d)",
diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp
index b4c7231..0dab864 100644
--- a/libs/gui/BufferQueue.cpp
+++ b/libs/gui/BufferQueue.cpp
@@ -178,12 +178,10 @@
         }
 
         // here we're guaranteed that the client doesn't have dequeued buffers
-        // and will release all of its buffer references.
-        //
-        // XXX: Should this use drainQueueAndFreeBuffersLocked instead?
+        // and will release all of its buffer references.  We don't clear the
+        // queue, however, so currently queued buffers still get displayed.
         freeAllBuffersLocked();
         mOverrideMaxBufferCount = bufferCount;
-        mBufferHasBeenQueued = false;
         mDequeueCondition.broadcast();
         listener = mConsumerListener;
     } // scope for lock
@@ -418,6 +416,7 @@
                 return NO_INIT;
             }
 
+            mSlots[*outBuf].mFrameNumber = ~0;
             mSlots[*outBuf].mGraphicBuffer = graphicBuffer;
         }
     }
@@ -435,7 +434,8 @@
         eglDestroySyncKHR(dpy, eglFence);
     }
 
-    ST_LOGV("dequeueBuffer: returning slot=%d buf=%p flags=%#x", *outBuf,
+    ST_LOGV("dequeueBuffer: returning slot=%d/%llu buf=%p flags=%#x", *outBuf,
+            mSlots[*outBuf].mFrameNumber,
             mSlots[*outBuf].mGraphicBuffer->handle, returnFlags);
 
     return returnFlags;
@@ -491,15 +491,22 @@
         return BAD_VALUE;
     }
 
-    ST_LOGV("queueBuffer: slot=%d time=%#llx crop=[%d,%d,%d,%d] tr=%#x "
-            "scale=%s",
-            buf, timestamp, crop.left, crop.top, crop.right, crop.bottom,
-            transform, scalingModeName(scalingMode));
+    switch (scalingMode) {
+        case NATIVE_WINDOW_SCALING_MODE_FREEZE:
+        case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
+        case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP:
+        case NATIVE_WINDOW_SCALING_MODE_NO_SCALE_CROP:
+            break;
+        default:
+            ST_LOGE("unknown scaling mode: %d", scalingMode);
+            return -EINVAL;
+    }
 
     sp<ConsumerListener> listener;
 
     { // scope for the lock
         Mutex::Autolock lock(mMutex);
+
         if (mAbandoned) {
             ST_LOGE("queueBuffer: BufferQueue has been abandoned!");
             return NO_INIT;
@@ -519,6 +526,12 @@
             return -EINVAL;
         }
 
+        ST_LOGV("queueBuffer: slot=%d/%llu time=%#llx crop=[%d,%d,%d,%d] "
+                "tr=%#x scale=%s",
+                buf, mFrameCounter + 1, timestamp,
+                crop.left, crop.top, crop.right, crop.bottom,
+                transform, scalingModeName(scalingMode));
+
         const sp<GraphicBuffer>& graphicBuffer(mSlots[buf].mGraphicBuffer);
         Rect bufferRect(graphicBuffer->getWidth(), graphicBuffer->getHeight());
         Rect croppedCrop;
@@ -529,9 +542,25 @@
             return -EINVAL;
         }
 
+        mSlots[buf].mFence = fence;
+        mSlots[buf].mBufferState = BufferSlot::QUEUED;
+        mFrameCounter++;
+        mSlots[buf].mFrameNumber = mFrameCounter;
+
+        BufferItem item;
+        item.mAcquireCalled = mSlots[buf].mAcquireCalled;
+        item.mGraphicBuffer = mSlots[buf].mGraphicBuffer;
+        item.mCrop = crop;
+        item.mTransform = transform;
+        item.mScalingMode = scalingMode;
+        item.mTimestamp = timestamp;
+        item.mFrameNumber = mFrameCounter;
+        item.mBuf = buf;
+        item.mFence = fence;
+
         if (mSynchronousMode) {
             // In synchronous mode we queue all buffers in a FIFO.
-            mQueue.push_back(buf);
+            mQueue.push_back(item);
 
             // Synchronous mode always signals that an additional frame should
             // be consumed.
@@ -539,7 +568,7 @@
         } else {
             // In asynchronous mode we only keep the most recent buffer.
             if (mQueue.empty()) {
-                mQueue.push_back(buf);
+                mQueue.push_back(item);
 
                 // Asynchronous mode only signals that a frame should be
                 // consumed if no previous frame was pending. If a frame were
@@ -547,34 +576,15 @@
                 listener = mConsumerListener;
             } else {
                 Fifo::iterator front(mQueue.begin());
-                // buffer currently queued is freed
-                mSlots[*front].mBufferState = BufferSlot::FREE;
+                // buffer slot currently queued is marked free if still tracked
+                if (stillTracking(front)) {
+                    mSlots[front->mBuf].mBufferState = BufferSlot::FREE;
+                }
                 // and we record the new buffer index in the queued list
-                *front = buf;
+                *front = item;
             }
         }
 
-        mSlots[buf].mTimestamp = timestamp;
-        mSlots[buf].mCrop = crop;
-        mSlots[buf].mTransform = transform;
-        mSlots[buf].mFence = fence;
-
-        switch (scalingMode) {
-            case NATIVE_WINDOW_SCALING_MODE_FREEZE:
-            case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
-            case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP:
-                break;
-            default:
-                ST_LOGE("unknown scaling mode: %d (ignoring)", scalingMode);
-                scalingMode = mSlots[buf].mScalingMode;
-                break;
-        }
-
-        mSlots[buf].mBufferState = BufferSlot::QUEUED;
-        mSlots[buf].mScalingMode = scalingMode;
-        mFrameCounter++;
-        mSlots[buf].mFrameNumber = mFrameCounter;
-
         mBufferHasBeenQueued = true;
         mDequeueCondition.broadcast();
 
@@ -707,36 +717,36 @@
     return err;
 }
 
-void BufferQueue::dump(String8& result) const
-{
-    char buffer[1024];
-    BufferQueue::dump(result, "", buffer, 1024);
+void BufferQueue::dump(String8& result) const {
+    BufferQueue::dump(result, "");
 }
 
-void BufferQueue::dump(String8& result, const char* prefix,
-        char* buffer, size_t SIZE) const
-{
+void BufferQueue::dump(String8& result, const char* prefix) const {
     Mutex::Autolock _l(mMutex);
 
     String8 fifo;
     int fifoSize = 0;
     Fifo::const_iterator i(mQueue.begin());
     while (i != mQueue.end()) {
-       snprintf(buffer, SIZE, "%02d ", *i++);
-       fifoSize++;
-       fifo.append(buffer);
+        fifo.appendFormat("%02d:%p crop=[%d,%d,%d,%d], "
+                "xform=0x%02x, time=%#llx, scale=%s\n",
+                i->mBuf, i->mGraphicBuffer.get(),
+                i->mCrop.left, i->mCrop.top, i->mCrop.right,
+                i->mCrop.bottom, i->mTransform, i->mTimestamp,
+                scalingModeName(i->mScalingMode)
+                );
+        i++;
+        fifoSize++;
     }
 
     int maxBufferCount = getMaxBufferCountLocked();
 
-    snprintf(buffer, SIZE,
+    result.appendFormat(
             "%s-BufferQueue maxBufferCount=%d, mSynchronousMode=%d, default-size=[%dx%d], "
             "default-format=%d, transform-hint=%02x, FIFO(%d)={%s}\n",
             prefix, maxBufferCount, mSynchronousMode, mDefaultWidth,
             mDefaultHeight, mDefaultBufferFormat, mTransformHint,
             fifoSize, fifo.string());
-    result.append(buffer);
-
 
     struct {
         const char * operator()(int state) const {
@@ -752,25 +762,19 @@
 
     for (int i=0 ; i<maxBufferCount ; i++) {
         const BufferSlot& slot(mSlots[i]);
-        snprintf(buffer, SIZE,
-                "%s%s[%02d] "
-                "state=%-8s, crop=[%d,%d,%d,%d], "
-                "xform=0x%02x, time=%#llx, scale=%s",
+        result.appendFormat(
+            "%s%s[%02d:%p] state=%-8s",
                 prefix, (slot.mBufferState == BufferSlot::ACQUIRED)?">":" ", i,
-                stateName(slot.mBufferState),
-                slot.mCrop.left, slot.mCrop.top, slot.mCrop.right,
-                slot.mCrop.bottom, slot.mTransform, slot.mTimestamp,
-                scalingModeName(slot.mScalingMode)
+                slot.mGraphicBuffer.get(),
+                stateName(slot.mBufferState)
         );
-        result.append(buffer);
 
         const sp<GraphicBuffer>& buf(slot.mGraphicBuffer);
         if (buf != NULL) {
-            snprintf(buffer, SIZE,
+            result.appendFormat(
                     ", %p [%4ux%4u:%4u,%3X]",
                     buf->handle, buf->width, buf->height, buf->stride,
                     buf->format);
-            result.append(buffer);
         }
         result.append("\n");
     }
@@ -795,9 +799,8 @@
 }
 
 void BufferQueue::freeAllBuffersLocked() {
-    ALOGW_IF(!mQueue.isEmpty(),
-            "freeAllBuffersLocked called but mQueue is not empty");
-    mQueue.clear();
+    ALOGD_IF(!mQueue.isEmpty(),
+            "freeAllBuffersLocked called with non-empty mQueue");
     mBufferHasBeenQueued = false;
     for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
         freeBufferLocked(i);
@@ -829,27 +832,27 @@
     // deep, while in synchronous mode we use the oldest buffer.
     if (!mQueue.empty()) {
         Fifo::iterator front(mQueue.begin());
-        int buf = *front;
-
+        int buf = front->mBuf;
+        *buffer = *front;
         ATRACE_BUFFER_INDEX(buf);
 
-        if (mSlots[buf].mAcquireCalled) {
-            buffer->mGraphicBuffer = NULL;
-        } else {
-            buffer->mGraphicBuffer = mSlots[buf].mGraphicBuffer;
+        ST_LOGV("acquireBuffer: acquiring { slot=%d/%llu, buffer=%p }",
+                front->mBuf, front->mFrameNumber,
+                front->mGraphicBuffer->handle);
+        // if front buffer still being tracked update slot state
+        if (stillTracking(front)) {
+            mSlots[buf].mAcquireCalled = true;
+            mSlots[buf].mNeedsCleanupOnRelease = false;
+            mSlots[buf].mBufferState = BufferSlot::ACQUIRED;
+            mSlots[buf].mFence = Fence::NO_FENCE;
         }
-        buffer->mCrop = mSlots[buf].mCrop;
-        buffer->mTransform = mSlots[buf].mTransform;
-        buffer->mScalingMode = mSlots[buf].mScalingMode;
-        buffer->mFrameNumber = mSlots[buf].mFrameNumber;
-        buffer->mTimestamp = mSlots[buf].mTimestamp;
-        buffer->mBuf = buf;
-        buffer->mFence = mSlots[buf].mFence;
 
-        mSlots[buf].mAcquireCalled = true;
-        mSlots[buf].mNeedsCleanupOnRelease = false;
-        mSlots[buf].mBufferState = BufferSlot::ACQUIRED;
-        mSlots[buf].mFence = Fence::NO_FENCE;
+        // If the buffer has previously been acquired by the consumer, set
+        // mGraphicBuffer to NULL to avoid unnecessarily remapping this
+        // buffer on the consumer side.
+        if (buffer->mAcquireCalled) {
+            buffer->mGraphicBuffer = NULL;
+        }
 
         mQueue.erase(front);
         mDequeueCondition.broadcast();
@@ -862,7 +865,8 @@
     return NO_ERROR;
 }
 
-status_t BufferQueue::releaseBuffer(int buf, EGLDisplay display,
+status_t BufferQueue::releaseBuffer(
+        int buf, uint64_t frameNumber, EGLDisplay display,
         EGLSyncKHR eglFence, const sp<Fence>& fence) {
     ATRACE_CALL();
     ATRACE_BUFFER_INDEX(buf);
@@ -873,12 +877,35 @@
         return BAD_VALUE;
     }
 
-    mSlots[buf].mEglDisplay = display;
-    mSlots[buf].mEglFence = eglFence;
-    mSlots[buf].mFence = fence;
+    // Check if this buffer slot is on the queue
+    bool slotQueued = false;
+    Fifo::iterator front(mQueue.begin());
+    while (front != mQueue.end() && !slotQueued) {
+        if (front->mBuf == buf)
+            slotQueued = true;
+        front++;
+    }
+
+    // If the frame number has changed because buffer has been reallocated,
+    // we can ignore this releaseBuffer for the old buffer.
+    if (frameNumber != mSlots[buf].mFrameNumber) {
+        // This should only occur if new buffer is still in the queue
+        ALOGE_IF(!slotQueued,
+                "received old buffer(#%lld) after new buffer(#%lld) on same "
+                "slot #%d already acquired", frameNumber,
+                mSlots[buf].mFrameNumber, buf);
+        return STALE_BUFFER_SLOT;
+    }
+    // this should never happen
+    ALOGE_IF(slotQueued,
+            "received new buffer(#%lld) on slot #%d that has not yet been "
+            "acquired", frameNumber, buf);
 
     // The buffer can now only be released if its in the acquired state
     if (mSlots[buf].mBufferState == BufferSlot::ACQUIRED) {
+        mSlots[buf].mEglDisplay = display;
+        mSlots[buf].mEglFence = eglFence;
+        mSlots[buf].mFence = fence;
         mSlots[buf].mBufferState = BufferSlot::FREE;
     } else if (mSlots[buf].mNeedsCleanupOnRelease) {
         ST_LOGV("releasing a stale buf %d its state was %d", buf, mSlots[buf].mBufferState);
@@ -943,6 +970,17 @@
             mask |= 1 << i;
         }
     }
+
+    // Remove buffers in flight (on the queue) from the mask where acquire has
+    // been called, as the consumer will not receive the buffer address, so
+    // it should not free these slots.
+    Fifo::iterator front(mQueue.begin());
+    while (front != mQueue.end()) {
+        if (front->mAcquireCalled)
+            mask &= ~(1 << front->mBuf);
+        front++;
+    }
+
     *slotMask = mask;
 
     ST_LOGV("getReleasedBuffers: returning mask %#x", mask);
@@ -985,20 +1023,6 @@
     return NO_ERROR;
 }
 
-void BufferQueue::freeAllBuffersExceptHeadLocked() {
-    int head = -1;
-    if (!mQueue.empty()) {
-        Fifo::iterator front(mQueue.begin());
-        head = *front;
-    }
-    mBufferHasBeenQueued = false;
-    for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
-        if (i != head) {
-            freeBufferLocked(i);
-        }
-    }
-}
-
 status_t BufferQueue::drainQueueLocked() {
     while (mSynchronousMode && mQueue.size() > 1) {
         mDequeueCondition.wait(mMutex);
@@ -1017,11 +1041,7 @@
 status_t BufferQueue::drainQueueAndFreeBuffersLocked() {
     status_t err = drainQueueLocked();
     if (err == NO_ERROR) {
-        if (mQueue.empty()) {
-            freeAllBuffersLocked();
-        } else {
-            freeAllBuffersExceptHeadLocked();
-        }
+        freeAllBuffersLocked();
     }
     return err;
 }
@@ -1061,6 +1081,22 @@
     return maxBufferCount;
 }
 
+bool BufferQueue::stillTracking(const BufferItem *item) const {
+    const BufferSlot &slot = mSlots[item->mBuf];
+
+    ST_LOGV("stillTracking?: item: { slot=%d/%llu, buffer=%p }, "
+            "slot: { slot=%d/%llu, buffer=%p }",
+            item->mBuf, item->mFrameNumber,
+            (item->mGraphicBuffer.get() ? item->mGraphicBuffer->handle : 0),
+            item->mBuf, slot.mFrameNumber,
+            (slot.mGraphicBuffer.get() ? slot.mGraphicBuffer->handle : 0));
+
+    // Compare item with its original buffer slot.  We can check the slot
+    // as the buffer would not be moved to a different slot by the producer.
+    return (slot.mGraphicBuffer != NULL &&
+            item->mGraphicBuffer->handle == slot.mGraphicBuffer->handle);
+}
+
 BufferQueue::ProxyConsumerListener::ProxyConsumerListener(
         const wp<BufferQueue::ConsumerListener>& consumerListener):
         mConsumerListener(consumerListener) {}
diff --git a/libs/gui/ConsumerBase.cpp b/libs/gui/ConsumerBase.cpp
index 4937b17..fd9d153 100644
--- a/libs/gui/ConsumerBase.cpp
+++ b/libs/gui/ConsumerBase.cpp
@@ -95,6 +95,7 @@
     CB_LOGV("freeBufferLocked: slotIndex=%d", slotIndex);
     mSlots[slotIndex].mGraphicBuffer = 0;
     mSlots[slotIndex].mFence = Fence::NO_FENCE;
+    mSlots[slotIndex].mFrameNumber = 0;
 }
 
 // Used for refactoring, should not be in final interface
@@ -165,23 +166,19 @@
 }
 
 void ConsumerBase::dump(String8& result) const {
-    char buffer[1024];
-    dump(result, "", buffer, 1024);
+    dump(result, "");
 }
 
-void ConsumerBase::dump(String8& result, const char* prefix,
-        char* buffer, size_t size) const {
+void ConsumerBase::dump(String8& result, const char* prefix) const {
     Mutex::Autolock _l(mMutex);
-    dumpLocked(result, prefix, buffer, size);
+    dumpLocked(result, prefix);
 }
 
-void ConsumerBase::dumpLocked(String8& result, const char* prefix,
-        char* buffer, size_t SIZE) const {
-    snprintf(buffer, SIZE, "%smAbandoned=%d\n", prefix, int(mAbandoned));
-    result.append(buffer);
+void ConsumerBase::dumpLocked(String8& result, const char* prefix) const {
+    result.appendFormat("%smAbandoned=%d\n", prefix, int(mAbandoned));
 
     if (!mAbandoned) {
-        mBufferQueue->dump(result, prefix, buffer, SIZE);
+        mBufferQueue->dump(result, prefix);
     }
 }
 
@@ -195,21 +192,31 @@
         mSlots[item->mBuf].mGraphicBuffer = item->mGraphicBuffer;
     }
 
+    mSlots[item->mBuf].mFrameNumber = item->mFrameNumber;
     mSlots[item->mBuf].mFence = item->mFence;
 
-    CB_LOGV("acquireBufferLocked: -> slot=%d", item->mBuf);
+    CB_LOGV("acquireBufferLocked: -> slot=%d/%llu",
+            item->mBuf, item->mFrameNumber);
 
     return OK;
 }
 
-status_t ConsumerBase::addReleaseFence(int slot, const sp<Fence>& fence) {
+status_t ConsumerBase::addReleaseFence(int slot,
+        const sp<GraphicBuffer> graphicBuffer, const sp<Fence>& fence) {
     Mutex::Autolock lock(mMutex);
-    return addReleaseFenceLocked(slot, fence);
+    return addReleaseFenceLocked(slot, graphicBuffer, fence);
 }
 
-status_t ConsumerBase::addReleaseFenceLocked(int slot, const sp<Fence>& fence) {
+status_t ConsumerBase::addReleaseFenceLocked(int slot,
+        const sp<GraphicBuffer> graphicBuffer, const sp<Fence>& fence) {
     CB_LOGV("addReleaseFenceLocked: slot=%d", slot);
 
+    // If consumer no longer tracks this graphicBuffer, we can safely
+    // drop this fence, as it will never be received by the producer.
+    if (!stillTracking(slot, graphicBuffer)) {
+        return OK;
+    }
+
     if (!mSlots[slot].mFence.get()) {
         mSlots[slot].mFence = fence;
     } else {
@@ -229,11 +236,20 @@
     return OK;
 }
 
-status_t ConsumerBase::releaseBufferLocked(int slot, EGLDisplay display,
-       EGLSyncKHR eglFence) {
-    CB_LOGV("releaseBufferLocked: slot=%d", slot);
-    status_t err = mBufferQueue->releaseBuffer(slot, display, eglFence,
-            mSlots[slot].mFence);
+status_t ConsumerBase::releaseBufferLocked(
+        int slot, const sp<GraphicBuffer> graphicBuffer,
+        EGLDisplay display, EGLSyncKHR eglFence) {
+    // If consumer no longer tracks this graphicBuffer (we received a new
+    // buffer on the same slot), the buffer producer is definitely no longer
+    // tracking it.
+    if (!stillTracking(slot, graphicBuffer)) {
+        return OK;
+    }
+
+    CB_LOGV("releaseBufferLocked: slot=%d/%llu",
+            slot, mSlots[slot].mFrameNumber);
+    status_t err = mBufferQueue->releaseBuffer(slot, mSlots[slot].mFrameNumber,
+            display, eglFence, mSlots[slot].mFence);
     if (err == BufferQueue::STALE_BUFFER_SLOT) {
         freeBufferLocked(slot);
     }
@@ -243,4 +259,13 @@
     return err;
 }
 
+bool ConsumerBase::stillTracking(int slot,
+        const sp<GraphicBuffer> graphicBuffer) {
+    if (slot < 0 || slot >= BufferQueue::NUM_BUFFER_SLOTS) {
+        return false;
+    }
+    return (mSlots[slot].mGraphicBuffer != NULL &&
+            mSlots[slot].mGraphicBuffer->handle == graphicBuffer->handle);
+}
+
 } // namespace android
diff --git a/libs/gui/CpuConsumer.cpp b/libs/gui/CpuConsumer.cpp
index 0543649..0834361 100644
--- a/libs/gui/CpuConsumer.cpp
+++ b/libs/gui/CpuConsumer.cpp
@@ -189,7 +189,9 @@
     // disconnected after this buffer was acquired.
     if (CC_LIKELY(mAcquiredBuffers[lockedIdx].mGraphicBuffer ==
             mSlots[buf].mGraphicBuffer)) {
-        releaseBufferLocked(buf, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR);
+        releaseBufferLocked(
+                buf, mAcquiredBuffers[lockedIdx].mGraphicBuffer,
+                EGL_NO_DISPLAY, EGL_NO_SYNC_KHR);
     }
 
     AcquiredBuffer &ab = mAcquiredBuffers.editItemAt(lockedIdx);
diff --git a/libs/gui/GLConsumer.cpp b/libs/gui/GLConsumer.cpp
index bec0f90..6d29edc 100644
--- a/libs/gui/GLConsumer.cpp
+++ b/libs/gui/GLConsumer.cpp
@@ -188,12 +188,16 @@
     return NO_ERROR;
 }
 
-status_t GLConsumer::releaseBufferLocked(int buf, EGLDisplay display,
-       EGLSyncKHR eglFence) {
-    status_t err = ConsumerBase::releaseBufferLocked(buf, display, eglFence);
-
+status_t GLConsumer::releaseBufferLocked(int buf,
+        sp<GraphicBuffer> graphicBuffer,
+        EGLDisplay display, EGLSyncKHR eglFence) {
+    // release the buffer if it hasn't already been discarded by the
+    // BufferQueue. This can happen, for example, when the producer of this
+    // buffer has reallocated the original buffer slot after this buffer
+    // was acquired.
+    status_t err = ConsumerBase::releaseBufferLocked(
+            buf, graphicBuffer, display, eglFence);
     mEglSlots[buf].mEglFence = EGL_NO_SYNC_KHR;
-
     return err;
 }
 
@@ -237,7 +241,10 @@
     if (err != NO_ERROR) {
         // Release the buffer we just acquired.  It's not safe to
         // release the old buffer, so instead we just drop the new frame.
-        releaseBufferLocked(buf, mEglDisplay, EGL_NO_SYNC_KHR);
+        // As we are still under lock since acquireBuffer, it is safe to
+        // release by slot.
+        releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer,
+                mEglDisplay, EGL_NO_SYNC_KHR);
         return err;
     }
 
@@ -248,7 +255,8 @@
 
     // release old buffer
     if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
-        status_t status = releaseBufferLocked(mCurrentTexture, mEglDisplay,
+        status_t status = releaseBufferLocked(
+                mCurrentTexture, mCurrentTextureBuf, mEglDisplay,
                 mEglSlots[mCurrentTexture].mEglFence);
         if (status != NO_ERROR && status != BufferQueue::STALE_BUFFER_SLOT) {
             ST_LOGE("releaseAndUpdate: failed to release buffer: %s (%d)",
@@ -334,7 +342,8 @@
 void GLConsumer::setReleaseFence(const sp<Fence>& fence) {
     if (fence->isValid() &&
             mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
-        status_t err = addReleaseFence(mCurrentTexture, fence);
+        status_t err = addReleaseFence(mCurrentTexture,
+                mCurrentTextureBuf, fence);
         if (err != OK) {
             ST_LOGE("setReleaseFence: failed to add the fence: %s (%d)",
                     strerror(-err), err);
@@ -503,7 +512,8 @@
                 return UNKNOWN_ERROR;
             }
             sp<Fence> fence(new Fence(fenceFd));
-            status_t err = addReleaseFenceLocked(mCurrentTexture, fence);
+            status_t err = addReleaseFenceLocked(mCurrentTexture,
+                    mCurrentTextureBuf, fence);
             if (err != OK) {
                 ST_LOGE("syncForReleaseLocked: error adding release fence: "
                         "%s (%d)", strerror(-err), err);
@@ -887,18 +897,16 @@
     return mBufferQueue->setSynchronousMode(enabled);
 }
 
-void GLConsumer::dumpLocked(String8& result, const char* prefix,
-        char* buffer, size_t size) const
+void GLConsumer::dumpLocked(String8& result, const char* prefix) const
 {
-    snprintf(buffer, size,
+    result.appendFormat(
        "%smTexName=%d mCurrentTexture=%d\n"
        "%smCurrentCrop=[%d,%d,%d,%d] mCurrentTransform=%#x\n",
        prefix, mTexName, mCurrentTexture, prefix, mCurrentCrop.left,
        mCurrentCrop.top, mCurrentCrop.right, mCurrentCrop.bottom,
        mCurrentTransform);
-    result.append(buffer);
 
-    ConsumerBase::dumpLocked(result, prefix, buffer, size);
+    ConsumerBase::dumpLocked(result, prefix);
 }
 
 static void mtxMul(float out[16], const float a[16], const float b[16]) {
diff --git a/libs/ui/Rect.cpp b/libs/ui/Rect.cpp
index c4dd55b..b480f3a 100644
--- a/libs/ui/Rect.cpp
+++ b/libs/ui/Rect.cpp
@@ -20,11 +20,11 @@
 namespace android {
 
 static inline int32_t min(int32_t a, int32_t b) {
-    return (a<b) ? a : b;
+    return (a < b) ? a : b;
 }
 
 static inline int32_t max(int32_t a, int32_t b) {
-    return (a>b) ? a : b;
+    return (a > b) ? a : b;
 }
 
 void Rect::makeInvalid() {
@@ -34,18 +34,17 @@
     bottom = -1;
 }
 
-bool Rect::operator < (const Rect& rhs) const
-{
-    if (top<rhs.top) {
+bool Rect::operator <(const Rect& rhs) const {
+    if (top < rhs.top) {
         return true;
     } else if (top == rhs.top) {
         if (left < rhs.left) {
             return true;
         } else if (left == rhs.left) {
-            if (bottom<rhs.bottom) {
+            if (bottom < rhs.bottom) {
                 return true;
             } else if (bottom == rhs.bottom) {
-                if (right<rhs.right) {
+                if (right < rhs.right) {
                     return true;
                 }
             }
@@ -54,8 +53,7 @@
     return false;
 }
 
-Rect& Rect::offsetTo(int32_t x, int32_t y)
-{
+Rect& Rect::offsetTo(int32_t x, int32_t y) {
     right -= left - x;
     bottom -= top - y;
     left = x;
@@ -63,45 +61,41 @@
     return *this;
 }
 
-Rect& Rect::offsetBy(int32_t x, int32_t y)
-{
+Rect& Rect::offsetBy(int32_t x, int32_t y) {
     left += x;
-    top  += y;
-    right+= x;
-    bottom+=y;
+    top += y;
+    right += x;
+    bottom += y;
     return *this;
 }
 
-const Rect Rect::operator + (const Point& rhs) const
-{
-    const Rect result(left+rhs.x, top+rhs.y, right+rhs.x, bottom+rhs.y);
+const Rect Rect::operator +(const Point& rhs) const {
+    const Rect result(left + rhs.x, top + rhs.y, right + rhs.x, bottom + rhs.y);
     return result;
 }
 
-const Rect Rect::operator - (const Point& rhs) const
-{
-    const Rect result(left-rhs.x, top-rhs.y, right-rhs.x, bottom-rhs.y);
+const Rect Rect::operator -(const Point& rhs) const {
+    const Rect result(left - rhs.x, top - rhs.y, right - rhs.x, bottom - rhs.y);
     return result;
 }
 
-bool Rect::intersect(const Rect& with, Rect* result) const
-{
-    result->left    = max(left, with.left);
-    result->top     = max(top, with.top);
-    result->right   = min(right, with.right);
-    result->bottom  = min(bottom, with.bottom);
+bool Rect::intersect(const Rect& with, Rect* result) const {
+    result->left = max(left, with.left);
+    result->top = max(top, with.top);
+    result->right = min(right, with.right);
+    result->bottom = min(bottom, with.bottom);
     return !(result->isEmpty());
 }
 
 Rect Rect::transform(uint32_t xform, int32_t width, int32_t height) const {
     Rect result(*this);
     if (xform & HAL_TRANSFORM_FLIP_H) {
-        result = Rect(width - result.right, result.top,
-                width - result.left, result.bottom);
+        result = Rect(width - result.right, result.top, width - result.left,
+                result.bottom);
     }
     if (xform & HAL_TRANSFORM_FLIP_V) {
-        result = Rect(result.left, height - result.bottom,
-                result.right, height - result.top);
+        result = Rect(result.left, height - result.bottom, result.right,
+                height - result.top);
     }
     if (xform & HAL_TRANSFORM_ROT_90) {
         int left = height - result.bottom;
@@ -113,4 +107,35 @@
     return result;
 }
 
+Rect Rect::reduce(const Rect& exclude) const {
+    Rect result;
+
+    uint32_t mask = 0;
+    mask |= (exclude.left   > left)   ? 1 : 0;
+    mask |= (exclude.top    > top)    ? 2 : 0;
+    mask |= (exclude.right  < right)  ? 4 : 0;
+    mask |= (exclude.bottom < bottom) ? 8 : 0;
+
+    if (mask == 0) {
+        // crop entirely covers us
+        result.clear();
+    } else {
+        result = *this;
+        if (!(mask & (mask - 1))) {
+            // power-of-2, i.e.: just one bit is set
+            if (mask & 1) {
+                result.right = exclude.left;
+            } else if (mask & 2) {
+                result.bottom = exclude.top;
+            } else if (mask & 4) {
+                result.left = exclude.right;
+            } else if (mask & 8) {
+                result.top = exclude.bottom;
+            }
+        }
+    }
+
+    return result;
+}
+
 }; // namespace android
diff --git a/libs/ui/Region.cpp b/libs/ui/Region.cpp
index bf01488..623f8ed 100644
--- a/libs/ui/Region.cpp
+++ b/libs/ui/Region.cpp
@@ -697,7 +697,7 @@
         size_t count = reg.mStorage.size();
         Rect* rects = reg.mStorage.editArray();
         while (count) {
-            rects->translate(dx, dy);
+            rects->offsetBy(dx, dy);
             rects++;
             count--;
         }
diff --git a/libs/utils/Android.mk b/libs/utils/Android.mk
index cbfe7bd..42e1c7e 100644
--- a/libs/utils/Android.mk
+++ b/libs/utils/Android.mk
@@ -20,9 +20,7 @@
 commonSources:= \
 	BasicHashtable.cpp \
 	BlobCache.cpp \
-	BufferedTextOutput.cpp \
 	CallStack.cpp \
-	Debug.cpp \
 	FileMap.cpp \
 	Flattenable.cpp \
 	JenkinsHash.cpp \
@@ -36,18 +34,12 @@
 	StopWatch.cpp \
 	String8.cpp \
 	String16.cpp \
-	StringArray.cpp \
 	SystemClock.cpp \
-	TextOutput.cpp \
 	Threads.cpp \
 	Timers.cpp \
 	Tokenizer.cpp \
 	Unicode.cpp \
 	VectorImpl.cpp \
-	WorkQueue.cpp \
-	ZipFileCRO.cpp \
-	ZipFileRO.cpp \
-	ZipUtils.cpp \
 	misc.cpp
 
 host_commonCflags := -DLIBUTILS_NATIVE=1 $(TOOL_CFLAGS)
@@ -74,9 +66,6 @@
 LOCAL_SRC_FILES += Looper.cpp
 endif
 LOCAL_MODULE:= libutils
-LOCAL_STATIC_LIBRARIES := libz
-LOCAL_C_INCLUDES := \
-	external/zlib
 LOCAL_CFLAGS += $(host_commonCflags)
 LOCAL_LDLIBS += $(host_commonLdlibs)
 include $(BUILD_HOST_STATIC_LIBRARY)
@@ -90,15 +79,12 @@
 LOCAL_SRC_FILES += Looper.cpp
 endif
 LOCAL_MODULE:= lib64utils
-LOCAL_STATIC_LIBRARIES := libz
-LOCAL_C_INCLUDES := \
-	external/zlib
 LOCAL_CFLAGS += $(host_commonCflags) -m64
 LOCAL_LDLIBS += $(host_commonLdlibs)
 include $(BUILD_HOST_STATIC_LIBRARY)
 
 
-# For the device
+# For the device, static
 # =====================================================
 include $(CLEAR_VARS)
 
@@ -123,14 +109,28 @@
 
 LOCAL_LDLIBS += -lpthread
 
+LOCAL_STATIC_LIBRARIES := \
+	libcutils
+
 LOCAL_SHARED_LIBRARIES := \
-	liblog \
-	libcutils \
-	libdl \
-	libcorkscrew \
-	libz
+        libcorkscrew \
+        liblog \
+        libdl
 
 LOCAL_MODULE:= libutils
+include $(BUILD_STATIC_LIBRARY)
+
+# For the device, shared
+# =====================================================
+include $(CLEAR_VARS)
+LOCAL_MODULE:= libutils
+LOCAL_WHOLE_STATIC_LIBRARIES := libutils
+LOCAL_SHARED_LIBRARIES := \
+        liblog \
+        libcutils \
+        libdl \
+        libcorkscrew
+
 include $(BUILD_SHARED_LIBRARY)
 
 # Include subdirectory makefiles
diff --git a/libs/utils/Looper.cpp b/libs/utils/Looper.cpp
index a5e6645..c51df2d 100644
--- a/libs/utils/Looper.cpp
+++ b/libs/utils/Looper.cpp
@@ -84,6 +84,8 @@
     LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake write pipe non-blocking.  errno=%d",
             errno);
 
+    mIdling = false;
+
     // Allocate the epoll instance and register the wake pipe.
     mEpollFd = epoll_create(EPOLL_SIZE_HINT);
     LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance.  errno=%d", errno);
@@ -214,9 +216,15 @@
     mResponses.clear();
     mResponseIndex = 0;
 
+    // We are about to idle.
+    mIdling = true;
+
     struct epoll_event eventItems[EPOLL_MAX_EVENTS];
     int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis);
 
+    // No longer idling.
+    mIdling = false;
+
     // Acquire lock.
     mLock.lock();
 
@@ -558,4 +566,8 @@
     } // release lock
 }
 
+bool Looper::isIdling() const {
+    return mIdling;
+}
+
 } // namespace android
diff --git a/libs/utils/RefBase.cpp b/libs/utils/RefBase.cpp
index e538f68..f398a82 100644
--- a/libs/utils/RefBase.cpp
+++ b/libs/utils/RefBase.cpp
@@ -23,7 +23,6 @@
 #include <utils/CallStack.h>
 #include <utils/Log.h>
 #include <utils/threads.h>
-#include <utils/TextOutput.h>
 
 #include <stdlib.h>
 #include <stdio.h>
@@ -648,19 +647,4 @@
     ref->mRefs->renameWeakRefId(old_id, new_id);
 }
 
-// ---------------------------------------------------------------------------
-
-TextOutput& printStrongPointer(TextOutput& to, const void* val)
-{
-    to << "sp<>(" << val << ")";
-    return to;
-}
-
-TextOutput& printWeakPointer(TextOutput& to, const void* val)
-{
-    to << "wp<>(" << val << ")";
-    return to;
-}
-
-
 }; // namespace android
diff --git a/libs/utils/Static.cpp b/libs/utils/Static.cpp
index 624e917..3ed07a1 100644
--- a/libs/utils/Static.cpp
+++ b/libs/utils/Static.cpp
@@ -17,13 +17,16 @@
 // All static variables go here, to control initialization and
 // destruction order in the library.
 
-#include <private/utils/Static.h>
-
-#include <utils/BufferedTextOutput.h>
-#include <utils/Log.h>
-
 namespace android {
 
+// For String8.cpp
+extern void initialize_string8();
+extern void terminate_string8();
+
+// For String16.cpp
+extern void initialize_string16();
+extern void terminate_string16();
+
 class LibUtilsFirstStatics
 {
 public:
@@ -43,49 +46,4 @@
 static LibUtilsFirstStatics gFirstStatics;
 int gDarwinCantLoadAllObjects = 1;
 
-// ------------ Text output streams
-
-Vector<int32_t> gTextBuffers;
-
-class LogTextOutput : public BufferedTextOutput
-{
-public:
-    LogTextOutput() : BufferedTextOutput(MULTITHREADED) { }
-    virtual ~LogTextOutput() { };
-
-protected:
-    virtual status_t writeLines(const struct iovec& vec, size_t N)
-    {
-        //android_writevLog(&vec, N);       <-- this is now a no-op
-        if (N != 1) ALOGI("WARNING: writeLines N=%zu\n", N);
-        ALOGI("%.*s", (int)vec.iov_len, (const char*) vec.iov_base);
-        return NO_ERROR;
-    }
-};
-
-class FdTextOutput : public BufferedTextOutput
-{
-public:
-    FdTextOutput(int fd) : BufferedTextOutput(MULTITHREADED), mFD(fd) { }
-    virtual ~FdTextOutput() { };
-
-protected:
-    virtual status_t writeLines(const struct iovec& vec, size_t N)
-    {
-        writev(mFD, &vec, N);
-        return NO_ERROR;
-    }
-
-private:
-    int mFD;
-};
-
-static LogTextOutput gLogTextOutput;
-static FdTextOutput gStdoutTextOutput(STDOUT_FILENO);
-static FdTextOutput gStderrTextOutput(STDERR_FILENO);
-
-TextOutput& alog(gLogTextOutput);
-TextOutput& aout(gStdoutTextOutput);
-TextOutput& aerr(gStderrTextOutput);
-
 }   // namespace android
diff --git a/libs/utils/String16.cpp b/libs/utils/String16.cpp
index 94e072f..b09b728 100644
--- a/libs/utils/String16.cpp
+++ b/libs/utils/String16.cpp
@@ -20,11 +20,8 @@
 #include <utils/Log.h>
 #include <utils/Unicode.h>
 #include <utils/String8.h>
-#include <utils/TextOutput.h>
 #include <utils/threads.h>
 
-#include <private/utils/Static.h>
-
 #include <memory.h>
 #include <stdio.h>
 #include <ctype.h>
@@ -96,6 +93,19 @@
 {
 }
 
+String16::String16(StaticLinkage)
+    : mString(0)
+{
+    // this constructor is used when we can't rely on the static-initializers
+    // having run. In this case we always allocate an empty string. It's less
+    // efficient than using getEmptyString(), but we assume it's uncommon.
+
+    char16_t* data = static_cast<char16_t*>(
+            SharedBuffer::alloc(sizeof(char16_t))->data());
+    data[0] = 0;
+    mString = data;
+}
+
 String16::String16(const String16& o)
     : mString(o.mString)
 {
@@ -409,10 +419,4 @@
     return NO_MEMORY;
 }
 
-TextOutput& operator<<(TextOutput& to, const String16& val)
-{
-    to << String8(val).string();
-    return to;
-}
-
 }; // namespace android
diff --git a/libs/utils/String8.cpp b/libs/utils/String8.cpp
index 562f026..e852d77 100644
--- a/libs/utils/String8.cpp
+++ b/libs/utils/String8.cpp
@@ -20,11 +20,8 @@
 #include <utils/Unicode.h>
 #include <utils/SharedBuffer.h>
 #include <utils/String16.h>
-#include <utils/TextOutput.h>
 #include <utils/threads.h>
 
-#include <private/utils/Static.h>
-
 #include <ctype.h>
 
 /*
@@ -46,6 +43,8 @@
 extern int gDarwinCantLoadAllObjects;
 int gDarwinIsReallyAnnoying;
 
+void initialize_string8();
+
 static inline char* getEmptyString()
 {
     gEmptyStringBuf->acquire();
@@ -143,6 +142,19 @@
 {
 }
 
+String8::String8(StaticLinkage)
+    : mString(0)
+{
+    // this constructor is used when we can't rely on the static-initializers
+    // having run. In this case we always allocate an empty string. It's less
+    // efficient than using getEmptyString(), but we assume it's uncommon.
+
+    char* data = static_cast<char*>(
+            SharedBuffer::alloc(sizeof(char))->data());
+    data[0] = 0;
+    mString = data;
+}
+
 String8::String8(const String8& o)
     : mString(o.mString)
 {
@@ -450,12 +462,6 @@
     utf8_to_utf32(mString, length(), dst);
 }
 
-TextOutput& operator<<(TextOutput& to, const String8& val)
-{
-    to << val.string();
-    return to;
-}
-
 // ---------------------------------------------------------------------------
 // Path functions
 
diff --git a/libs/utils/StringArray.cpp b/libs/utils/StringArray.cpp
deleted file mode 100644
index aa42d68..0000000
--- a/libs/utils/StringArray.cpp
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * 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.
- */
-
-//
-// Sortable array of strings.  STL-ish, but STL-free.
-//  
-
-#include <stdlib.h>
-#include <string.h>
-
-#include <utils/StringArray.h>
-
-namespace android {
-
-//
-// An expanding array of strings.  Add, get, sort, delete.
-//
-StringArray::StringArray()
-    : mMax(0), mCurrent(0), mArray(NULL)
-{
-}
-
-StringArray:: ~StringArray() {
-    for (int i = 0; i < mCurrent; i++)
-        delete[] mArray[i];
-    delete[] mArray;
-}
-
-//
-// Add a string.  A copy of the string is made.
-//
-bool StringArray::push_back(const char* str) {
-    if (mCurrent >= mMax) {
-        char** tmp;
-
-        if (mMax == 0)
-            mMax = 16;      // initial storage
-        else
-            mMax *= 2;
-
-        tmp = new char*[mMax];
-        if (tmp == NULL)
-            return false;
-
-        memcpy(tmp, mArray, mCurrent * sizeof(char*));
-        delete[] mArray;
-        mArray = tmp;
-    }
-
-    int len = strlen(str);
-    mArray[mCurrent] = new char[len+1];
-    memcpy(mArray[mCurrent], str, len+1);
-    mCurrent++;
-
-    return true;
-}
-
-//
-// Delete an entry.
-//
-void StringArray::erase(int idx) {
-    if (idx < 0 || idx >= mCurrent)
-        return;
-    delete[] mArray[idx];
-    if (idx < mCurrent-1) {
-        memmove(&mArray[idx], &mArray[idx+1],
-                (mCurrent-1 - idx) * sizeof(char*));
-    }
-    mCurrent--;
-}
-
-//
-// Sort the array.
-//
-void StringArray::sort(int (*compare)(const void*, const void*)) {
-    qsort(mArray, mCurrent, sizeof(char*), compare);
-}
-
-//
-// Pass this to the sort routine to do an ascending alphabetical sort.
-//
-int StringArray::cmpAscendingAlpha(const void* pstr1, const void* pstr2) {
-    return strcmp(*(const char**)pstr1, *(const char**)pstr2);
-}
-
-//
-// Set entry N to specified string.
-// [should use operator[] here]
-//
-void StringArray::setEntry(int idx, const char* str) {
-    if (idx < 0 || idx >= mCurrent)
-        return;
-    delete[] mArray[idx];
-    int len = strlen(str);
-    mArray[idx] = new char[len+1];
-    memcpy(mArray[idx], str, len+1);
-}
-
-
-}; // namespace android
diff --git a/libs/utils/SystemClock.cpp b/libs/utils/SystemClock.cpp
index ec2d82e..4b74889 100644
--- a/libs/utils/SystemClock.cpp
+++ b/libs/utils/SystemClock.cpp
@@ -36,63 +36,11 @@
 #include <utils/Timers.h>
 
 #define LOG_TAG "SystemClock"
-#include "utils/Log.h"
+#include <utils/Log.h>
 
 namespace android {
 
 /*
- * Set the current time.  This only works when running as root.
- */
-int setCurrentTimeMillis(int64_t millis)
-{
-#if WIN32
-    // not implemented
-    return -1;
-#else
-    struct timeval tv;
-#ifdef HAVE_ANDROID_OS
-    struct timespec ts;
-    int fd;
-    int res;
-#endif
-    int ret = 0;
-
-    if (millis <= 0 || millis / 1000LL >= INT_MAX) {
-        return -1;
-    }
-
-    tv.tv_sec = (time_t) (millis / 1000LL);
-    tv.tv_usec = (suseconds_t) ((millis % 1000LL) * 1000LL);
-
-    ALOGD("Setting time of day to sec=%d\n", (int) tv.tv_sec);
-
-#ifdef HAVE_ANDROID_OS
-    fd = open("/dev/alarm", O_RDWR);
-    if(fd < 0) {
-        ALOGW("Unable to open alarm driver: %s\n", strerror(errno));
-        return -1;
-    }
-    ts.tv_sec = tv.tv_sec;
-    ts.tv_nsec = tv.tv_usec * 1000;
-    res = ioctl(fd, ANDROID_ALARM_SET_RTC, &ts);
-    if(res < 0) {
-        ALOGW("Unable to set rtc to %ld: %s\n", tv.tv_sec, strerror(errno));
-        ret = -1;
-    }
-    close(fd);
-#else
-    if (settimeofday(&tv, NULL) != 0) {
-        ALOGW("Unable to set clock to %d.%d: %s\n",
-            (int) tv.tv_sec, (int) tv.tv_usec, strerror(errno));
-        ret = -1;
-    }
-#endif
-
-    return ret;
-#endif // WIN32
-}
-
-/*
  * native public static long uptimeMillis();
  */
 int64_t uptimeMillis()
diff --git a/libs/utils/Threads.cpp b/libs/utils/Threads.cpp
index 7b877e0..ff74914 100644
--- a/libs/utils/Threads.cpp
+++ b/libs/utils/Threads.cpp
@@ -21,7 +21,6 @@
 #include <utils/Log.h>
 
 #include <cutils/sched_policy.h>
-#include <cutils/properties.h>
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -68,20 +67,6 @@
 
 typedef void* (*android_pthread_entry)(void*);
 
-static pthread_once_t gDoSchedulingGroupOnce = PTHREAD_ONCE_INIT;
-static bool gDoSchedulingGroup = true;
-
-static void checkDoSchedulingGroup(void) {
-    char buf[PROPERTY_VALUE_MAX];
-    int len = property_get("debug.sys.noschedgroups", buf, "");
-    if (len > 0) {
-        int temp;
-        if (sscanf(buf, "%d", &temp) == 1) {
-            gDoSchedulingGroup = temp == 0;
-        }
-    }
-}
-
 struct thread_data_t {
     thread_func_t   entryFunction;
     void*           userData;
@@ -97,15 +82,10 @@
         char * name = t->threadName;
         delete t;
         setpriority(PRIO_PROCESS, 0, prio);
-        pthread_once(&gDoSchedulingGroupOnce, checkDoSchedulingGroup);
-        if (gDoSchedulingGroup) {
-            if (prio >= ANDROID_PRIORITY_BACKGROUND) {
-                set_sched_policy(androidGetTid(), SP_BACKGROUND);
-            } else if (prio > ANDROID_PRIORITY_AUDIO) {
-                set_sched_policy(androidGetTid(), SP_FOREGROUND);
-            } else {
-                // defaults to that of parent, or as set by requestPriority()
-            }
+        if (prio >= ANDROID_PRIORITY_BACKGROUND) {
+            set_sched_policy(0, SP_BACKGROUND);
+        } else {
+            set_sched_policy(0, SP_FOREGROUND);
         }
         
         if (name) {
@@ -337,20 +317,10 @@
 #if defined(HAVE_PTHREADS)
     int lasterr = 0;
 
-    pthread_once(&gDoSchedulingGroupOnce, checkDoSchedulingGroup);
-    if (gDoSchedulingGroup) {
-        // set_sched_policy does not support tid == 0
-        int policy_tid;
-        if (tid == 0) {
-            policy_tid = androidGetTid();
-        } else {
-            policy_tid = tid;
-        }
-        if (pri >= ANDROID_PRIORITY_BACKGROUND) {
-            rc = set_sched_policy(policy_tid, SP_BACKGROUND);
-        } else if (getpriority(PRIO_PROCESS, tid) >= ANDROID_PRIORITY_BACKGROUND) {
-            rc = set_sched_policy(policy_tid, SP_FOREGROUND);
-        }
+    if (pri >= ANDROID_PRIORITY_BACKGROUND) {
+        rc = set_sched_policy(tid, SP_BACKGROUND);
+    } else if (getpriority(PRIO_PROCESS, tid) >= ANDROID_PRIORITY_BACKGROUND) {
+        rc = set_sched_policy(tid, SP_FOREGROUND);
     }
 
     if (rc) {
diff --git a/libs/utils/Timers.cpp b/libs/utils/Timers.cpp
index d4f8516..5293cd2 100644
--- a/libs/utils/Timers.cpp
+++ b/libs/utils/Timers.cpp
@@ -70,65 +70,3 @@
     }
     return timeoutDelayMillis;
 }
-
-
-/*
- * ===========================================================================
- *      DurationTimer
- * ===========================================================================
- */
-
-using namespace android;
-
-// Start the timer.
-void DurationTimer::start(void)
-{
-    gettimeofday(&mStartWhen, NULL);
-}
-
-// Stop the timer.
-void DurationTimer::stop(void)
-{
-    gettimeofday(&mStopWhen, NULL);
-}
-
-// Get the duration in microseconds.
-long long DurationTimer::durationUsecs(void) const
-{
-    return (long) subtractTimevals(&mStopWhen, &mStartWhen);
-}
-
-// Subtract two timevals.  Returns the difference (ptv1-ptv2) in
-// microseconds.
-/*static*/ long long DurationTimer::subtractTimevals(const struct timeval* ptv1,
-    const struct timeval* ptv2)
-{
-    long long stop  = ((long long) ptv1->tv_sec) * 1000000LL +
-                      ((long long) ptv1->tv_usec);
-    long long start = ((long long) ptv2->tv_sec) * 1000000LL +
-                      ((long long) ptv2->tv_usec);
-    return stop - start;
-}
-
-// Add the specified amount of time to the timeval.
-/*static*/ void DurationTimer::addToTimeval(struct timeval* ptv, long usec)
-{
-    if (usec < 0) {
-        ALOG(LOG_WARN, "", "Negative values not supported in addToTimeval\n");
-        return;
-    }
-
-    // normalize tv_usec if necessary
-    if (ptv->tv_usec >= 1000000) {
-        ptv->tv_sec += ptv->tv_usec / 1000000;
-        ptv->tv_usec %= 1000000;
-    }
-
-    ptv->tv_usec += usec % 1000000;
-    if (ptv->tv_usec >= 1000000) {
-        ptv->tv_usec -= 1000000;
-        ptv->tv_sec++;
-    }
-    ptv->tv_sec += usec / 1000000;
-}
-
diff --git a/libs/utils/VectorImpl.cpp b/libs/utils/VectorImpl.cpp
index 70f49de..5a79647 100644
--- a/libs/utils/VectorImpl.cpp
+++ b/libs/utils/VectorImpl.cpp
@@ -504,15 +504,6 @@
     do_move_backward(dest, from, num);
 }
 
-void VectorImpl::reservedVectorImpl1() { }
-void VectorImpl::reservedVectorImpl2() { }
-void VectorImpl::reservedVectorImpl3() { }
-void VectorImpl::reservedVectorImpl4() { }
-void VectorImpl::reservedVectorImpl5() { }
-void VectorImpl::reservedVectorImpl6() { }
-void VectorImpl::reservedVectorImpl7() { }
-void VectorImpl::reservedVectorImpl8() { }
-
 /*****************************************************************************/
 
 SortedVectorImpl::SortedVectorImpl(size_t itemSize, uint32_t flags)
@@ -628,16 +619,6 @@
     return i;
 }
 
-void SortedVectorImpl::reservedSortedVectorImpl1() { };
-void SortedVectorImpl::reservedSortedVectorImpl2() { };
-void SortedVectorImpl::reservedSortedVectorImpl3() { };
-void SortedVectorImpl::reservedSortedVectorImpl4() { };
-void SortedVectorImpl::reservedSortedVectorImpl5() { };
-void SortedVectorImpl::reservedSortedVectorImpl6() { };
-void SortedVectorImpl::reservedSortedVectorImpl7() { };
-void SortedVectorImpl::reservedSortedVectorImpl8() { };
-
-
 /*****************************************************************************/
 
 }; // namespace android
diff --git a/libs/utils/WorkQueue.cpp b/libs/utils/WorkQueue.cpp
deleted file mode 100644
index 3bb99a1..0000000
--- a/libs/utils/WorkQueue.cpp
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright (C) 2012 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 "WorkQueue"
-
-#include <utils/Log.h>
-#include <utils/WorkQueue.h>
-
-namespace android {
-
-// --- WorkQueue ---
-
-WorkQueue::WorkQueue(size_t maxThreads, bool canCallJava) :
-        mMaxThreads(maxThreads), mCanCallJava(canCallJava),
-        mCanceled(false), mFinished(false), mIdleThreads(0) {
-}
-
-WorkQueue::~WorkQueue() {
-    if (!cancel()) {
-        finish();
-    }
-}
-
-status_t WorkQueue::schedule(WorkUnit* workUnit, size_t backlog) {
-    AutoMutex _l(mLock);
-
-    if (mFinished || mCanceled) {
-        return INVALID_OPERATION;
-    }
-
-    if (mWorkThreads.size() < mMaxThreads
-            && mIdleThreads < mWorkUnits.size() + 1) {
-        sp<WorkThread> workThread = new WorkThread(this, mCanCallJava);
-        status_t status = workThread->run("WorkQueue::WorkThread");
-        if (status) {
-            return status;
-        }
-        mWorkThreads.add(workThread);
-        mIdleThreads += 1;
-    } else if (backlog) {
-        while (mWorkUnits.size() >= mMaxThreads * backlog) {
-            mWorkDequeuedCondition.wait(mLock);
-            if (mFinished || mCanceled) {
-                return INVALID_OPERATION;
-            }
-        }
-    }
-
-    mWorkUnits.add(workUnit);
-    mWorkChangedCondition.broadcast();
-    return OK;
-}
-
-status_t WorkQueue::cancel() {
-    AutoMutex _l(mLock);
-
-    return cancelLocked();
-}
-
-status_t WorkQueue::cancelLocked() {
-    if (mFinished) {
-        return INVALID_OPERATION;
-    }
-
-    if (!mCanceled) {
-        mCanceled = true;
-
-        size_t count = mWorkUnits.size();
-        for (size_t i = 0; i < count; i++) {
-            delete mWorkUnits.itemAt(i);
-        }
-        mWorkUnits.clear();
-        mWorkChangedCondition.broadcast();
-        mWorkDequeuedCondition.broadcast();
-    }
-    return OK;
-}
-
-status_t WorkQueue::finish() {
-    { // acquire lock
-        AutoMutex _l(mLock);
-
-        if (mFinished) {
-            return INVALID_OPERATION;
-        }
-
-        mFinished = true;
-        mWorkChangedCondition.broadcast();
-    } // release lock
-
-    // It is not possible for the list of work threads to change once the mFinished
-    // flag has been set, so we can access mWorkThreads outside of the lock here.
-    size_t count = mWorkThreads.size();
-    for (size_t i = 0; i < count; i++) {
-        mWorkThreads.itemAt(i)->join();
-    }
-    mWorkThreads.clear();
-    return OK;
-}
-
-bool WorkQueue::threadLoop() {
-    WorkUnit* workUnit;
-    { // acquire lock
-        AutoMutex _l(mLock);
-
-        for (;;) {
-            if (mCanceled) {
-                return false;
-            }
-
-            if (!mWorkUnits.isEmpty()) {
-                workUnit = mWorkUnits.itemAt(0);
-                mWorkUnits.removeAt(0);
-                mIdleThreads -= 1;
-                mWorkDequeuedCondition.broadcast();
-                break;
-            }
-
-            if (mFinished) {
-                return false;
-            }
-
-            mWorkChangedCondition.wait(mLock);
-        }
-    } // release lock
-
-    bool shouldContinue = workUnit->run();
-    delete workUnit;
-
-    { // acquire lock
-        AutoMutex _l(mLock);
-
-        mIdleThreads += 1;
-
-        if (!shouldContinue) {
-            cancelLocked();
-            return false;
-        }
-    } // release lock
-
-    return true;
-}
-
-// --- WorkQueue::WorkThread ---
-
-WorkQueue::WorkThread::WorkThread(WorkQueue* workQueue, bool canCallJava) :
-        Thread(canCallJava), mWorkQueue(workQueue) {
-}
-
-WorkQueue::WorkThread::~WorkThread() {
-}
-
-bool WorkQueue::WorkThread::threadLoop() {
-    return mWorkQueue->threadLoop();
-}
-
-};  // namespace android
diff --git a/libs/utils/ZipFileCRO.cpp b/libs/utils/ZipFileCRO.cpp
deleted file mode 100644
index 55dfd9f..0000000
--- a/libs/utils/ZipFileCRO.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * 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 <utils/ZipFileCRO.h>
-#include <utils/ZipFileRO.h>
-
-using namespace android;
-
-ZipFileCRO ZipFileXRO_open(const char* path) {
-    ZipFileRO* zip = new ZipFileRO();
-    if (zip->open(path) == NO_ERROR) {
-        return (ZipFileCRO)zip;
-    }
-    return NULL;
-}
-
-void ZipFileCRO_destroy(ZipFileCRO zipToken) {
-    ZipFileRO* zip = (ZipFileRO*)zipToken;
-    delete zip;
-}
-
-ZipEntryCRO ZipFileCRO_findEntryByName(ZipFileCRO zipToken,
-        const char* fileName) {
-    ZipFileRO* zip = (ZipFileRO*)zipToken;
-    return (ZipEntryCRO)zip->findEntryByName(fileName);
-}
-
-bool ZipFileCRO_getEntryInfo(ZipFileCRO zipToken, ZipEntryRO entryToken,
-        int* pMethod, size_t* pUncompLen,
-        size_t* pCompLen, off64_t* pOffset, long* pModWhen, long* pCrc32) {
-    ZipFileRO* zip = (ZipFileRO*)zipToken;
-    ZipEntryRO entry = (ZipEntryRO)entryToken;
-    return zip->getEntryInfo(entry, pMethod, pUncompLen, pCompLen, pOffset,
-            pModWhen, pCrc32);
-}
-
-bool ZipFileCRO_uncompressEntry(ZipFileCRO zipToken, ZipEntryRO entryToken, int fd) {
-    ZipFileRO* zip = (ZipFileRO*)zipToken;
-    ZipEntryRO entry = (ZipEntryRO)entryToken;
-    return zip->uncompressEntry(entry, fd);
-}
diff --git a/libs/utils/ZipFileRO.cpp b/libs/utils/ZipFileRO.cpp
deleted file mode 100644
index a1bfedb..0000000
--- a/libs/utils/ZipFileRO.cpp
+++ /dev/null
@@ -1,931 +0,0 @@
-/*
- * 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.
- */
-
-//
-// Read-only access to Zip archives, with minimal heap allocation.
-//
-#define LOG_TAG "zipro"
-//#define LOG_NDEBUG 0
-#include <utils/Log.h>
-#include <utils/Compat.h>
-#include <utils/ZipFileRO.h>
-#include <utils/misc.h>
-#include <utils/threads.h>
-
-#include <zlib.h>
-
-#include <string.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <assert.h>
-#include <unistd.h>
-
-/*
- * We must open binary files using open(path, ... | O_BINARY) under Windows.
- * Otherwise strange read errors will happen.
- */
-#ifndef O_BINARY
-#  define O_BINARY  0
-#endif
-
-using namespace android;
-
-/*
- * Zip file constants.
- */
-#define kEOCDSignature      0x06054b50
-#define kEOCDLen            22
-#define kEOCDNumEntries     8               // offset to #of entries in file
-#define kEOCDSize           12              // size of the central directory
-#define kEOCDFileOffset     16              // offset to central directory
-
-#define kMaxCommentLen      65535           // longest possible in ushort
-#define kMaxEOCDSearch      (kMaxCommentLen + kEOCDLen)
-
-#define kLFHSignature       0x04034b50
-#define kLFHLen             30              // excluding variable-len fields
-#define kLFHNameLen         26              // offset to filename length
-#define kLFHExtraLen        28              // offset to extra length
-
-#define kCDESignature       0x02014b50
-#define kCDELen             46              // excluding variable-len fields
-#define kCDEMethod          10              // offset to compression method
-#define kCDEModWhen         12              // offset to modification timestamp
-#define kCDECRC             16              // offset to entry CRC
-#define kCDECompLen         20              // offset to compressed length
-#define kCDEUncompLen       24              // offset to uncompressed length
-#define kCDENameLen         28              // offset to filename length
-#define kCDEExtraLen        30              // offset to extra length
-#define kCDECommentLen      32              // offset to comment length
-#define kCDELocalOffset     42              // offset to local hdr
-
-/*
- * The values we return for ZipEntryRO use 0 as an invalid value, so we
- * want to adjust the hash table index by a fixed amount.  Using a large
- * value helps insure that people don't mix & match arguments, e.g. to
- * findEntryByIndex().
- */
-#define kZipEntryAdj        10000
-
-ZipFileRO::~ZipFileRO() {
-    free(mHashTable);
-    if (mDirectoryMap)
-        mDirectoryMap->release();
-    if (mFd >= 0)
-        TEMP_FAILURE_RETRY(close(mFd));
-    if (mFileName)
-        free(mFileName);
-}
-
-/*
- * Convert a ZipEntryRO to a hash table index, verifying that it's in a
- * valid range.
- */
-int ZipFileRO::entryToIndex(const ZipEntryRO entry) const
-{
-    long ent = ((intptr_t) entry) - kZipEntryAdj;
-    if (ent < 0 || ent >= mHashTableSize || mHashTable[ent].name == NULL) {
-        ALOGW("Invalid ZipEntryRO %p (%ld)\n", entry, ent);
-        return -1;
-    }
-    return ent;
-}
-
-
-/*
- * Open the specified file read-only.  We memory-map the entire thing and
- * close the file before returning.
- */
-status_t ZipFileRO::open(const char* zipFileName)
-{
-    int fd = -1;
-
-    assert(mDirectoryMap == NULL);
-
-    /*
-     * Open and map the specified file.
-     */
-    fd = TEMP_FAILURE_RETRY(::open(zipFileName, O_RDONLY | O_BINARY));
-    if (fd < 0) {
-        ALOGW("Unable to open zip '%s': %s\n", zipFileName, strerror(errno));
-        return NAME_NOT_FOUND;
-    }
-
-    mFileLength = lseek64(fd, 0, SEEK_END);
-    if (mFileLength < kEOCDLen) {
-        TEMP_FAILURE_RETRY(close(fd));
-        return UNKNOWN_ERROR;
-    }
-
-    if (mFileName != NULL) {
-        free(mFileName);
-    }
-    mFileName = strdup(zipFileName);
-
-    mFd = fd;
-
-    /*
-     * Find the Central Directory and store its size and number of entries.
-     */
-    if (!mapCentralDirectory()) {
-        goto bail;
-    }
-
-    /*
-     * Verify Central Directory and create data structures for fast access.
-     */
-    if (!parseZipArchive()) {
-        goto bail;
-    }
-
-    return OK;
-
-bail:
-    free(mFileName);
-    mFileName = NULL;
-    TEMP_FAILURE_RETRY(close(fd));
-    return UNKNOWN_ERROR;
-}
-
-/*
- * Parse the Zip archive, verifying its contents and initializing internal
- * data structures.
- */
-bool ZipFileRO::mapCentralDirectory(void)
-{
-    ssize_t readAmount = kMaxEOCDSearch;
-    if (readAmount > (ssize_t) mFileLength)
-        readAmount = mFileLength;
-
-    unsigned char* scanBuf = (unsigned char*) malloc(readAmount);
-    if (scanBuf == NULL) {
-        ALOGW("couldn't allocate scanBuf: %s", strerror(errno));
-        free(scanBuf);
-        return false;
-    }
-
-    /*
-     * Make sure this is a Zip archive.
-     */
-    if (lseek64(mFd, 0, SEEK_SET) != 0) {
-        ALOGW("seek to start failed: %s", strerror(errno));
-        free(scanBuf);
-        return false;
-    }
-
-    ssize_t actual = TEMP_FAILURE_RETRY(read(mFd, scanBuf, sizeof(int32_t)));
-    if (actual != (ssize_t) sizeof(int32_t)) {
-        ALOGI("couldn't read first signature from zip archive: %s", strerror(errno));
-        free(scanBuf);
-        return false;
-    }
-
-    {
-        unsigned int header = get4LE(scanBuf);
-        if (header == kEOCDSignature) {
-            ALOGI("Found Zip archive, but it looks empty\n");
-            free(scanBuf);
-            return false;
-        } else if (header != kLFHSignature) {
-            ALOGV("Not a Zip archive (found 0x%08x)\n", header);
-            free(scanBuf);
-            return false;
-        }
-    }
-
-    /*
-     * Perform the traditional EOCD snipe hunt.
-     *
-     * We're searching for the End of Central Directory magic number,
-     * which appears at the start of the EOCD block.  It's followed by
-     * 18 bytes of EOCD stuff and up to 64KB of archive comment.  We
-     * need to read the last part of the file into a buffer, dig through
-     * it to find the magic number, parse some values out, and use those
-     * to determine the extent of the CD.
-     *
-     * We start by pulling in the last part of the file.
-     */
-    off64_t searchStart = mFileLength - readAmount;
-
-    if (lseek64(mFd, searchStart, SEEK_SET) != searchStart) {
-        ALOGW("seek %ld failed: %s\n",  (long) searchStart, strerror(errno));
-        free(scanBuf);
-        return false;
-    }
-    actual = TEMP_FAILURE_RETRY(read(mFd, scanBuf, readAmount));
-    if (actual != (ssize_t) readAmount) {
-        ALOGW("Zip: read " ZD ", expected " ZD ". Failed: %s\n",
-            (ZD_TYPE) actual, (ZD_TYPE) readAmount, strerror(errno));
-        free(scanBuf);
-        return false;
-    }
-
-    /*
-     * Scan backward for the EOCD magic.  In an archive without a trailing
-     * comment, we'll find it on the first try.  (We may want to consider
-     * doing an initial minimal read; if we don't find it, retry with a
-     * second read as above.)
-     */
-    int i;
-    for (i = readAmount - kEOCDLen; i >= 0; i--) {
-        if (scanBuf[i] == 0x50 && get4LE(&scanBuf[i]) == kEOCDSignature) {
-            ALOGV("+++ Found EOCD at buf+%d\n", i);
-            break;
-        }
-    }
-    if (i < 0) {
-        ALOGD("Zip: EOCD not found, %s is not zip\n", mFileName);
-        free(scanBuf);
-        return false;
-    }
-
-    off64_t eocdOffset = searchStart + i;
-    const unsigned char* eocdPtr = scanBuf + i;
-
-    assert(eocdOffset < mFileLength);
-
-    /*
-     * Grab the CD offset and size, and the number of entries in the
-     * archive. After that, we can release our EOCD hunt buffer.
-     */
-    unsigned int numEntries = get2LE(eocdPtr + kEOCDNumEntries);
-    unsigned int dirSize = get4LE(eocdPtr + kEOCDSize);
-    unsigned int dirOffset = get4LE(eocdPtr + kEOCDFileOffset);
-    free(scanBuf);
-
-    // Verify that they look reasonable.
-    if ((long long) dirOffset + (long long) dirSize > (long long) eocdOffset) {
-        ALOGW("bad offsets (dir %ld, size %u, eocd %ld)\n",
-            (long) dirOffset, dirSize, (long) eocdOffset);
-        return false;
-    }
-    if (numEntries == 0) {
-        ALOGW("empty archive?\n");
-        return false;
-    }
-
-    ALOGV("+++ numEntries=%d dirSize=%d dirOffset=%d\n",
-        numEntries, dirSize, dirOffset);
-
-    mDirectoryMap = new FileMap();
-    if (mDirectoryMap == NULL) {
-        ALOGW("Unable to create directory map: %s", strerror(errno));
-        return false;
-    }
-
-    if (!mDirectoryMap->create(mFileName, mFd, dirOffset, dirSize, true)) {
-        ALOGW("Unable to map '%s' (" ZD " to " ZD "): %s\n", mFileName,
-                (ZD_TYPE) dirOffset, (ZD_TYPE) (dirOffset + dirSize), strerror(errno));
-        return false;
-    }
-
-    mNumEntries = numEntries;
-    mDirectoryOffset = dirOffset;
-
-    return true;
-}
-
-
-/*
- * Round up to the next highest power of 2.
- *
- * Found on http://graphics.stanford.edu/~seander/bithacks.html.
- */
-static unsigned int roundUpPower2(unsigned int val)
-{
-    val--;
-    val |= val >> 1;
-    val |= val >> 2;
-    val |= val >> 4;
-    val |= val >> 8;
-    val |= val >> 16;
-    val++;
-
-    return val;
-}
-
-bool ZipFileRO::parseZipArchive(void)
-{
-    bool result = false;
-    const unsigned char* cdPtr = (const unsigned char*) mDirectoryMap->getDataPtr();
-    size_t cdLength = mDirectoryMap->getDataLength();
-    int numEntries = mNumEntries;
-
-    /*
-     * Create hash table.  We have a minimum 75% load factor, possibly as
-     * low as 50% after we round off to a power of 2.
-     */
-    mHashTableSize = roundUpPower2(1 + (numEntries * 4) / 3);
-    mHashTable = (HashEntry*) calloc(mHashTableSize, sizeof(HashEntry));
-
-    /*
-     * Walk through the central directory, adding entries to the hash
-     * table.
-     */
-    const unsigned char* ptr = cdPtr;
-    for (int i = 0; i < numEntries; i++) {
-        if (get4LE(ptr) != kCDESignature) {
-            ALOGW("Missed a central dir sig (at %d)\n", i);
-            goto bail;
-        }
-        if (ptr + kCDELen > cdPtr + cdLength) {
-            ALOGW("Ran off the end (at %d)\n", i);
-            goto bail;
-        }
-
-        long localHdrOffset = (long) get4LE(ptr + kCDELocalOffset);
-        if (localHdrOffset >= mDirectoryOffset) {
-            ALOGW("bad LFH offset %ld at entry %d\n", localHdrOffset, i);
-            goto bail;
-        }
-
-        unsigned int fileNameLen, extraLen, commentLen, hash;
-
-        fileNameLen = get2LE(ptr + kCDENameLen);
-        extraLen = get2LE(ptr + kCDEExtraLen);
-        commentLen = get2LE(ptr + kCDECommentLen);
-
-        /* add the CDE filename to the hash table */
-        hash = computeHash((const char*)ptr + kCDELen, fileNameLen);
-        addToHash((const char*)ptr + kCDELen, fileNameLen, hash);
-
-        ptr += kCDELen + fileNameLen + extraLen + commentLen;
-        if ((size_t)(ptr - cdPtr) > cdLength) {
-            ALOGW("bad CD advance (%d vs " ZD ") at entry %d\n",
-                (int) (ptr - cdPtr), (ZD_TYPE) cdLength, i);
-            goto bail;
-        }
-    }
-    ALOGV("+++ zip good scan %d entries\n", numEntries);
-    result = true;
-
-bail:
-    return result;
-}
-
-/*
- * Simple string hash function for non-null-terminated strings.
- */
-/*static*/ unsigned int ZipFileRO::computeHash(const char* str, int len)
-{
-    unsigned int hash = 0;
-
-    while (len--)
-        hash = hash * 31 + *str++;
-
-    return hash;
-}
-
-/*
- * Add a new entry to the hash table.
- */
-void ZipFileRO::addToHash(const char* str, int strLen, unsigned int hash)
-{
-    int ent = hash & (mHashTableSize-1);
-
-    /*
-     * We over-allocate the table, so we're guaranteed to find an empty slot.
-     */
-    while (mHashTable[ent].name != NULL)
-        ent = (ent + 1) & (mHashTableSize-1);
-
-    mHashTable[ent].name = str;
-    mHashTable[ent].nameLen = strLen;
-}
-
-/*
- * Find a matching entry.
- *
- * Returns NULL if not found.
- */
-ZipEntryRO ZipFileRO::findEntryByName(const char* fileName) const
-{
-    /*
-     * If the ZipFileRO instance is not initialized, the entry number will
-     * end up being garbage since mHashTableSize is -1.
-     */
-    if (mHashTableSize <= 0) {
-        return NULL;
-    }
-
-    int nameLen = strlen(fileName);
-    unsigned int hash = computeHash(fileName, nameLen);
-    int ent = hash & (mHashTableSize-1);
-
-    while (mHashTable[ent].name != NULL) {
-        if (mHashTable[ent].nameLen == nameLen &&
-            memcmp(mHashTable[ent].name, fileName, nameLen) == 0)
-        {
-            /* match */
-            return (ZipEntryRO)(long)(ent + kZipEntryAdj);
-        }
-
-        ent = (ent + 1) & (mHashTableSize-1);
-    }
-
-    return NULL;
-}
-
-/*
- * Find the Nth entry.
- *
- * This currently involves walking through the sparse hash table, counting
- * non-empty entries.  If we need to speed this up we can either allocate
- * a parallel lookup table or (perhaps better) provide an iterator interface.
- */
-ZipEntryRO ZipFileRO::findEntryByIndex(int idx) const
-{
-    if (idx < 0 || idx >= mNumEntries) {
-        ALOGW("Invalid index %d\n", idx);
-        return NULL;
-    }
-
-    for (int ent = 0; ent < mHashTableSize; ent++) {
-        if (mHashTable[ent].name != NULL) {
-            if (idx-- == 0)
-                return (ZipEntryRO) (intptr_t)(ent + kZipEntryAdj);
-        }
-    }
-
-    return NULL;
-}
-
-/*
- * Get the useful fields from the zip entry.
- *
- * Returns "false" if the offsets to the fields or the contents of the fields
- * appear to be bogus.
- */
-bool ZipFileRO::getEntryInfo(ZipEntryRO entry, int* pMethod, size_t* pUncompLen,
-    size_t* pCompLen, off64_t* pOffset, long* pModWhen, long* pCrc32) const
-{
-    bool ret = false;
-
-    const int ent = entryToIndex(entry);
-    if (ent < 0)
-        return false;
-
-    HashEntry hashEntry = mHashTable[ent];
-
-    /*
-     * Recover the start of the central directory entry from the filename
-     * pointer.  The filename is the first entry past the fixed-size data,
-     * so we can just subtract back from that.
-     */
-    const unsigned char* ptr = (const unsigned char*) hashEntry.name;
-    off64_t cdOffset = mDirectoryOffset;
-
-    ptr -= kCDELen;
-
-    int method = get2LE(ptr + kCDEMethod);
-    if (pMethod != NULL)
-        *pMethod = method;
-
-    if (pModWhen != NULL)
-        *pModWhen = get4LE(ptr + kCDEModWhen);
-    if (pCrc32 != NULL)
-        *pCrc32 = get4LE(ptr + kCDECRC);
-
-    size_t compLen = get4LE(ptr + kCDECompLen);
-    if (pCompLen != NULL)
-        *pCompLen = compLen;
-    size_t uncompLen = get4LE(ptr + kCDEUncompLen);
-    if (pUncompLen != NULL)
-        *pUncompLen = uncompLen;
-
-    /*
-     * If requested, determine the offset of the start of the data.  All we
-     * have is the offset to the Local File Header, which is variable size,
-     * so we have to read the contents of the struct to figure out where
-     * the actual data starts.
-     *
-     * We also need to make sure that the lengths are not so large that
-     * somebody trying to map the compressed or uncompressed data runs
-     * off the end of the mapped region.
-     *
-     * Note we don't verify compLen/uncompLen if they don't request the
-     * dataOffset, because dataOffset is expensive to determine.  However,
-     * if they don't have the file offset, they're not likely to be doing
-     * anything with the contents.
-     */
-    if (pOffset != NULL) {
-        long localHdrOffset = get4LE(ptr + kCDELocalOffset);
-        if (localHdrOffset + kLFHLen >= cdOffset) {
-            ALOGE("ERROR: bad local hdr offset in zip\n");
-            return false;
-        }
-
-        unsigned char lfhBuf[kLFHLen];
-
-#ifdef HAVE_PREAD
-        /*
-         * This file descriptor might be from zygote's preloaded assets,
-         * so we need to do an pread64() instead of a lseek64() + read() to
-         * guarantee atomicity across the processes with the shared file
-         * descriptors.
-         */
-        ssize_t actual =
-                TEMP_FAILURE_RETRY(pread64(mFd, lfhBuf, sizeof(lfhBuf), localHdrOffset));
-
-        if (actual != sizeof(lfhBuf)) {
-            ALOGW("failed reading lfh from offset %ld\n", localHdrOffset);
-            return false;
-        }
-
-        if (get4LE(lfhBuf) != kLFHSignature) {
-            ALOGW("didn't find signature at start of lfh; wanted: offset=%ld data=0x%08x; "
-                    "got: data=0x%08lx\n",
-                    localHdrOffset, kLFHSignature, get4LE(lfhBuf));
-            return false;
-        }
-#else /* HAVE_PREAD */
-        /*
-         * For hosts don't have pread64() we cannot guarantee atomic reads from
-         * an offset in a file. Android should never run on those platforms.
-         * File descriptors inherited from a fork() share file offsets and
-         * there would be nothing to protect from two different processes
-         * calling lseek64() concurrently.
-         */
-
-        {
-            AutoMutex _l(mFdLock);
-
-            if (lseek64(mFd, localHdrOffset, SEEK_SET) != localHdrOffset) {
-                ALOGW("failed seeking to lfh at offset %ld\n", localHdrOffset);
-                return false;
-            }
-
-            ssize_t actual =
-                    TEMP_FAILURE_RETRY(read(mFd, lfhBuf, sizeof(lfhBuf)));
-            if (actual != sizeof(lfhBuf)) {
-                ALOGW("failed reading lfh from offset %ld\n", localHdrOffset);
-                return false;
-            }
-
-            if (get4LE(lfhBuf) != kLFHSignature) {
-                off64_t actualOffset = lseek64(mFd, 0, SEEK_CUR);
-                ALOGW("didn't find signature at start of lfh; wanted: offset=%ld data=0x%08x; "
-                        "got: offset=" ZD " data=0x%08lx\n",
-                        localHdrOffset, kLFHSignature, (ZD_TYPE) actualOffset, get4LE(lfhBuf));
-                return false;
-            }
-        }
-#endif /* HAVE_PREAD */
-
-        off64_t dataOffset = localHdrOffset + kLFHLen
-            + get2LE(lfhBuf + kLFHNameLen) + get2LE(lfhBuf + kLFHExtraLen);
-        if (dataOffset >= cdOffset) {
-            ALOGW("bad data offset %ld in zip\n", (long) dataOffset);
-            return false;
-        }
-
-        /* check lengths */
-        if ((off64_t)(dataOffset + compLen) > cdOffset) {
-            ALOGW("bad compressed length in zip (%ld + " ZD " > %ld)\n",
-                (long) dataOffset, (ZD_TYPE) compLen, (long) cdOffset);
-            return false;
-        }
-
-        if (method == kCompressStored &&
-            (off64_t)(dataOffset + uncompLen) > cdOffset)
-        {
-            ALOGE("ERROR: bad uncompressed length in zip (%ld + " ZD " > %ld)\n",
-                (long) dataOffset, (ZD_TYPE) uncompLen, (long) cdOffset);
-            return false;
-        }
-
-        *pOffset = dataOffset;
-    }
-
-    return true;
-}
-
-/*
- * Copy the entry's filename to the buffer.
- */
-int ZipFileRO::getEntryFileName(ZipEntryRO entry, char* buffer, int bufLen)
-    const
-{
-    int ent = entryToIndex(entry);
-    if (ent < 0)
-        return -1;
-
-    int nameLen = mHashTable[ent].nameLen;
-    if (bufLen < nameLen+1)
-        return nameLen+1;
-
-    memcpy(buffer, mHashTable[ent].name, nameLen);
-    buffer[nameLen] = '\0';
-    return 0;
-}
-
-/*
- * Create a new FileMap object that spans the data in "entry".
- */
-FileMap* ZipFileRO::createEntryFileMap(ZipEntryRO entry) const
-{
-    /*
-     * TODO: the efficient way to do this is to modify FileMap to allow
-     * sub-regions of a file to be mapped.  A reference-counting scheme
-     * can manage the base memory mapping.  For now, we just create a brand
-     * new mapping off of the Zip archive file descriptor.
-     */
-
-    FileMap* newMap;
-    size_t compLen;
-    off64_t offset;
-
-    if (!getEntryInfo(entry, NULL, NULL, &compLen, &offset, NULL, NULL))
-        return NULL;
-
-    newMap = new FileMap();
-    if (!newMap->create(mFileName, mFd, offset, compLen, true)) {
-        newMap->release();
-        return NULL;
-    }
-
-    return newMap;
-}
-
-/*
- * Uncompress an entry, in its entirety, into the provided output buffer.
- *
- * This doesn't verify the data's CRC, which might be useful for
- * uncompressed data.  The caller should be able to manage it.
- */
-bool ZipFileRO::uncompressEntry(ZipEntryRO entry, void* buffer) const
-{
-    const size_t kSequentialMin = 32768;
-    bool result = false;
-    int ent = entryToIndex(entry);
-    if (ent < 0)
-        return -1;
-
-    int method;
-    size_t uncompLen, compLen;
-    off64_t offset;
-    const unsigned char* ptr;
-
-    getEntryInfo(entry, &method, &uncompLen, &compLen, &offset, NULL, NULL);
-
-    FileMap* file = createEntryFileMap(entry);
-    if (file == NULL) {
-        goto bail;
-    }
-
-    ptr = (const unsigned char*) file->getDataPtr();
-
-    /*
-     * Experiment with madvise hint.  When we want to uncompress a file,
-     * we pull some stuff out of the central dir entry and then hit a
-     * bunch of compressed or uncompressed data sequentially.  The CDE
-     * visit will cause a limited amount of read-ahead because it's at
-     * the end of the file.  We could end up doing lots of extra disk
-     * access if the file we're prying open is small.  Bottom line is we
-     * probably don't want to turn MADV_SEQUENTIAL on and leave it on.
-     *
-     * So, if the compressed size of the file is above a certain minimum
-     * size, temporarily boost the read-ahead in the hope that the extra
-     * pair of system calls are negated by a reduction in page faults.
-     */
-    if (compLen > kSequentialMin)
-        file->advise(FileMap::SEQUENTIAL);
-
-    if (method == kCompressStored) {
-        memcpy(buffer, ptr, uncompLen);
-    } else {
-        if (!inflateBuffer(buffer, ptr, uncompLen, compLen))
-            goto unmap;
-    }
-
-    if (compLen > kSequentialMin)
-        file->advise(FileMap::NORMAL);
-
-    result = true;
-
-unmap:
-    file->release();
-bail:
-    return result;
-}
-
-/*
- * Uncompress an entry, in its entirety, to an open file descriptor.
- *
- * This doesn't verify the data's CRC, but probably should.
- */
-bool ZipFileRO::uncompressEntry(ZipEntryRO entry, int fd) const
-{
-    bool result = false;
-    int ent = entryToIndex(entry);
-    if (ent < 0)
-        return -1;
-
-    int method;
-    size_t uncompLen, compLen;
-    off64_t offset;
-    const unsigned char* ptr;
-
-    getEntryInfo(entry, &method, &uncompLen, &compLen, &offset, NULL, NULL);
-
-    FileMap* file = createEntryFileMap(entry);
-    if (file == NULL) {
-        goto bail;
-    }
-
-    ptr = (const unsigned char*) file->getDataPtr();
-
-    if (method == kCompressStored) {
-        ssize_t actual = TEMP_FAILURE_RETRY(write(fd, ptr, uncompLen));
-        if (actual < 0) {
-            ALOGE("Write failed: %s\n", strerror(errno));
-            goto unmap;
-        } else if ((size_t) actual != uncompLen) {
-            ALOGE("Partial write during uncompress (" ZD " of " ZD ")\n",
-                (ZD_TYPE) actual, (ZD_TYPE) uncompLen);
-            goto unmap;
-        } else {
-            ALOGI("+++ successful write\n");
-        }
-    } else {
-        if (!inflateBuffer(fd, ptr, uncompLen, compLen))
-            goto unmap;
-    }
-
-    result = true;
-
-unmap:
-    file->release();
-bail:
-    return result;
-}
-
-/*
- * Uncompress "deflate" data from one buffer to another.
- */
-/*static*/ bool ZipFileRO::inflateBuffer(void* outBuf, const void* inBuf,
-    size_t uncompLen, size_t compLen)
-{
-    bool result = false;
-    z_stream zstream;
-    int zerr;
-
-    /*
-     * Initialize the zlib stream struct.
-     */
-    memset(&zstream, 0, sizeof(zstream));
-    zstream.zalloc = Z_NULL;
-    zstream.zfree = Z_NULL;
-    zstream.opaque = Z_NULL;
-    zstream.next_in = (Bytef*)inBuf;
-    zstream.avail_in = compLen;
-    zstream.next_out = (Bytef*) outBuf;
-    zstream.avail_out = uncompLen;
-    zstream.data_type = Z_UNKNOWN;
-
-    /*
-     * Use the undocumented "negative window bits" feature to tell zlib
-     * that there's no zlib header waiting for it.
-     */
-    zerr = inflateInit2(&zstream, -MAX_WBITS);
-    if (zerr != Z_OK) {
-        if (zerr == Z_VERSION_ERROR) {
-            ALOGE("Installed zlib is not compatible with linked version (%s)\n",
-                ZLIB_VERSION);
-        } else {
-            ALOGE("Call to inflateInit2 failed (zerr=%d)\n", zerr);
-        }
-        goto bail;
-    }
-
-    /*
-     * Expand data.
-     */
-    zerr = inflate(&zstream, Z_FINISH);
-    if (zerr != Z_STREAM_END) {
-        ALOGW("Zip inflate failed, zerr=%d (nIn=%p aIn=%u nOut=%p aOut=%u)\n",
-            zerr, zstream.next_in, zstream.avail_in,
-            zstream.next_out, zstream.avail_out);
-        goto z_bail;
-    }
-
-    /* paranoia */
-    if (zstream.total_out != uncompLen) {
-        ALOGW("Size mismatch on inflated file (%ld vs " ZD ")\n",
-            zstream.total_out, (ZD_TYPE) uncompLen);
-        goto z_bail;
-    }
-
-    result = true;
-
-z_bail:
-    inflateEnd(&zstream);        /* free up any allocated structures */
-
-bail:
-    return result;
-}
-
-/*
- * Uncompress "deflate" data from one buffer to an open file descriptor.
- */
-/*static*/ bool ZipFileRO::inflateBuffer(int fd, const void* inBuf,
-    size_t uncompLen, size_t compLen)
-{
-    bool result = false;
-    const size_t kWriteBufSize = 32768;
-    unsigned char writeBuf[kWriteBufSize];
-    z_stream zstream;
-    int zerr;
-
-    /*
-     * Initialize the zlib stream struct.
-     */
-    memset(&zstream, 0, sizeof(zstream));
-    zstream.zalloc = Z_NULL;
-    zstream.zfree = Z_NULL;
-    zstream.opaque = Z_NULL;
-    zstream.next_in = (Bytef*)inBuf;
-    zstream.avail_in = compLen;
-    zstream.next_out = (Bytef*) writeBuf;
-    zstream.avail_out = sizeof(writeBuf);
-    zstream.data_type = Z_UNKNOWN;
-
-    /*
-     * Use the undocumented "negative window bits" feature to tell zlib
-     * that there's no zlib header waiting for it.
-     */
-    zerr = inflateInit2(&zstream, -MAX_WBITS);
-    if (zerr != Z_OK) {
-        if (zerr == Z_VERSION_ERROR) {
-            ALOGE("Installed zlib is not compatible with linked version (%s)\n",
-                ZLIB_VERSION);
-        } else {
-            ALOGE("Call to inflateInit2 failed (zerr=%d)\n", zerr);
-        }
-        goto bail;
-    }
-
-    /*
-     * Loop while we have more to do.
-     */
-    do {
-        /*
-         * Expand data.
-         */
-        zerr = inflate(&zstream, Z_NO_FLUSH);
-        if (zerr != Z_OK && zerr != Z_STREAM_END) {
-            ALOGW("zlib inflate: zerr=%d (nIn=%p aIn=%u nOut=%p aOut=%u)\n",
-                zerr, zstream.next_in, zstream.avail_in,
-                zstream.next_out, zstream.avail_out);
-            goto z_bail;
-        }
-
-        /* write when we're full or when we're done */
-        if (zstream.avail_out == 0 ||
-            (zerr == Z_STREAM_END && zstream.avail_out != sizeof(writeBuf)))
-        {
-            long writeSize = zstream.next_out - writeBuf;
-            int cc = TEMP_FAILURE_RETRY(write(fd, writeBuf, writeSize));
-            if (cc < 0) {
-                ALOGW("write failed in inflate: %s", strerror(errno));
-                goto z_bail;
-            } else if (cc != (int) writeSize) {
-                ALOGW("write failed in inflate (%d vs %ld)", cc, writeSize);
-                goto z_bail;
-            }
-
-            zstream.next_out = writeBuf;
-            zstream.avail_out = sizeof(writeBuf);
-        }
-    } while (zerr == Z_OK);
-
-    assert(zerr == Z_STREAM_END);       /* other errors should've been caught */
-
-    /* paranoia */
-    if (zstream.total_out != uncompLen) {
-        ALOGW("Size mismatch on inflated file (%ld vs " ZD ")\n",
-            zstream.total_out, (ZD_TYPE) uncompLen);
-        goto z_bail;
-    }
-
-    result = true;
-
-z_bail:
-    inflateEnd(&zstream);        /* free up any allocated structures */
-
-bail:
-    return result;
-}
diff --git a/libs/utils/ZipUtils.cpp b/libs/utils/ZipUtils.cpp
deleted file mode 100644
index a43bbb0..0000000
--- a/libs/utils/ZipUtils.cpp
+++ /dev/null
@@ -1,345 +0,0 @@
-/*
- * 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.
- */
-
-//
-// Misc zip/gzip utility functions.
-//
-
-#define LOG_TAG "ziputil"
-
-#include <utils/Log.h>
-#include <utils/Compat.h>
-#include <utils/ZipUtils.h>
-#include <utils/ZipFileRO.h>
-
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-
-#include <zlib.h>
-
-using namespace android;
-
-/*
- * Utility function that expands zip/gzip "deflate" compressed data
- * into a buffer.
- *
- * "fd" is an open file positioned at the start of the "deflate" data
- * "buf" must hold at least "uncompressedLen" bytes.
- */
-/*static*/ bool ZipUtils::inflateToBuffer(int fd, void* buf,
-    long uncompressedLen, long compressedLen)
-{
-    bool result = false;
-	const unsigned long kReadBufSize = 32768;
-	unsigned char* readBuf = NULL;
-    z_stream zstream;
-    int zerr;
-    unsigned long compRemaining;
-
-    assert(uncompressedLen >= 0);
-    assert(compressedLen >= 0);
-
-	readBuf = new unsigned char[kReadBufSize];
-	if (readBuf == NULL)
-        goto bail;
-    compRemaining = compressedLen;
-
-    /*
-     * Initialize the zlib stream.
-     */
-	memset(&zstream, 0, sizeof(zstream));
-    zstream.zalloc = Z_NULL;
-    zstream.zfree = Z_NULL;
-    zstream.opaque = Z_NULL;
-    zstream.next_in = NULL;
-    zstream.avail_in = 0;
-    zstream.next_out = (Bytef*) buf;
-    zstream.avail_out = uncompressedLen;
-    zstream.data_type = Z_UNKNOWN;
-
-	/*
-	 * Use the undocumented "negative window bits" feature to tell zlib
-	 * that there's no zlib header waiting for it.
-	 */
-    zerr = inflateInit2(&zstream, -MAX_WBITS);
-    if (zerr != Z_OK) {
-        if (zerr == Z_VERSION_ERROR) {
-            ALOGE("Installed zlib is not compatible with linked version (%s)\n",
-                ZLIB_VERSION);
-        } else {
-            ALOGE("Call to inflateInit2 failed (zerr=%d)\n", zerr);
-        }
-        goto bail;
-    }
-
-    /*
-     * Loop while we have data.
-     */
-    do {
-        unsigned long getSize;
-
-        /* read as much as we can */
-        if (zstream.avail_in == 0) {
-            getSize = (compRemaining > kReadBufSize) ?
-                        kReadBufSize : compRemaining;
-            ALOGV("+++ reading %ld bytes (%ld left)\n",
-                getSize, compRemaining);
-
-            int cc = TEMP_FAILURE_RETRY(read(fd, readBuf, getSize));
-            if (cc < 0) {
-                ALOGW("inflate read failed: %s", strerror(errno));
-            } else if (cc != (int) getSize) {
-                ALOGW("inflate read failed (%d vs %ld)", cc, getSize);
-                goto z_bail;
-            }
-
-            compRemaining -= getSize;
-
-            zstream.next_in = readBuf;
-            zstream.avail_in = getSize;
-        }
-
-        /* uncompress the data */
-        zerr = inflate(&zstream, Z_NO_FLUSH);
-        if (zerr != Z_OK && zerr != Z_STREAM_END) {
-            ALOGD("zlib inflate call failed (zerr=%d)\n", zerr);
-            goto z_bail;
-        }
-
-		/* output buffer holds all, so no need to write the output */
-    } while (zerr == Z_OK);
-
-    assert(zerr == Z_STREAM_END);       /* other errors should've been caught */
-
-    if ((long) zstream.total_out != uncompressedLen) {
-        ALOGW("Size mismatch on inflated file (%ld vs %ld)\n",
-            zstream.total_out, uncompressedLen);
-        goto z_bail;
-    }
-
-    // success!
-    result = true;
-
-z_bail:
-    inflateEnd(&zstream);        /* free up any allocated structures */
-
-bail:
-	delete[] readBuf;
-    return result;
-}
-
-/*
- * Utility function that expands zip/gzip "deflate" compressed data
- * into a buffer.
- *
- * (This is a clone of the previous function, but it takes a FILE* instead
- * of an fd.  We could pass fileno(fd) to the above, but we can run into
- * trouble when "fp" has a different notion of what fd's file position is.)
- *
- * "fp" is an open file positioned at the start of the "deflate" data
- * "buf" must hold at least "uncompressedLen" bytes.
- */
-/*static*/ bool ZipUtils::inflateToBuffer(FILE* fp, void* buf,
-    long uncompressedLen, long compressedLen)
-{
-    bool result = false;
-	const unsigned long kReadBufSize = 32768;
-	unsigned char* readBuf = NULL;
-    z_stream zstream;
-    int zerr;
-    unsigned long compRemaining;
-
-    assert(uncompressedLen >= 0);
-    assert(compressedLen >= 0);
-
-	readBuf = new unsigned char[kReadBufSize];
-	if (readBuf == NULL)
-        goto bail;
-    compRemaining = compressedLen;
-
-    /*
-     * Initialize the zlib stream.
-     */
-	memset(&zstream, 0, sizeof(zstream));
-    zstream.zalloc = Z_NULL;
-    zstream.zfree = Z_NULL;
-    zstream.opaque = Z_NULL;
-    zstream.next_in = NULL;
-    zstream.avail_in = 0;
-    zstream.next_out = (Bytef*) buf;
-    zstream.avail_out = uncompressedLen;
-    zstream.data_type = Z_UNKNOWN;
-
-	/*
-	 * Use the undocumented "negative window bits" feature to tell zlib
-	 * that there's no zlib header waiting for it.
-	 */
-    zerr = inflateInit2(&zstream, -MAX_WBITS);
-    if (zerr != Z_OK) {
-        if (zerr == Z_VERSION_ERROR) {
-            ALOGE("Installed zlib is not compatible with linked version (%s)\n",
-                ZLIB_VERSION);
-        } else {
-            ALOGE("Call to inflateInit2 failed (zerr=%d)\n", zerr);
-        }
-        goto bail;
-    }
-
-    /*
-     * Loop while we have data.
-     */
-    do {
-        unsigned long getSize;
-
-        /* read as much as we can */
-        if (zstream.avail_in == 0) {
-            getSize = (compRemaining > kReadBufSize) ?
-                        kReadBufSize : compRemaining;
-            ALOGV("+++ reading %ld bytes (%ld left)\n",
-                getSize, compRemaining);
-
-            int cc = fread(readBuf, 1, getSize, fp);
-            if (cc != (int) getSize) {
-                ALOGD("inflate read failed (%d vs %ld)\n",
-                    cc, getSize);
-                goto z_bail;
-            }
-
-            compRemaining -= getSize;
-
-            zstream.next_in = readBuf;
-            zstream.avail_in = getSize;
-        }
-
-        /* uncompress the data */
-        zerr = inflate(&zstream, Z_NO_FLUSH);
-        if (zerr != Z_OK && zerr != Z_STREAM_END) {
-            ALOGD("zlib inflate call failed (zerr=%d)\n", zerr);
-            goto z_bail;
-        }
-
-		/* output buffer holds all, so no need to write the output */
-    } while (zerr == Z_OK);
-
-    assert(zerr == Z_STREAM_END);       /* other errors should've been caught */
-
-    if ((long) zstream.total_out != uncompressedLen) {
-        ALOGW("Size mismatch on inflated file (%ld vs %ld)\n",
-            zstream.total_out, uncompressedLen);
-        goto z_bail;
-    }
-
-    // success!
-    result = true;
-
-z_bail:
-    inflateEnd(&zstream);        /* free up any allocated structures */
-
-bail:
-	delete[] readBuf;
-    return result;
-}
-
-/*
- * Look at the contents of a gzip archive.  We want to know where the
- * data starts, and how long it will be after it is uncompressed.
- *
- * We expect to find the CRC and length as the last 8 bytes on the file.
- * This is a pretty reasonable thing to expect for locally-compressed
- * files, but there's a small chance that some extra padding got thrown
- * on (the man page talks about compressed data written to tape).  We
- * don't currently deal with that here.  If "gzip -l" whines, we're going
- * to fail too.
- *
- * On exit, "fp" is pointing at the start of the compressed data.
- */
-/*static*/ bool ZipUtils::examineGzip(FILE* fp, int* pCompressionMethod,
-    long* pUncompressedLen, long* pCompressedLen, unsigned long* pCRC32)
-{
-    enum {  // flags
-        FTEXT       = 0x01,
-        FHCRC       = 0x02,
-        FEXTRA      = 0x04,
-        FNAME       = 0x08,
-        FCOMMENT    = 0x10,
-    };
-    int ic;
-    int method, flags;
-    int i;
-
-    ic = getc(fp);
-    if (ic != 0x1f || getc(fp) != 0x8b)
-        return false;       // not gzip
-    method = getc(fp);
-    flags = getc(fp);
-
-    /* quick sanity checks */
-    if (method == EOF || flags == EOF)
-        return false;
-    if (method != ZipFileRO::kCompressDeflated)
-        return false;
-
-    /* skip over 4 bytes of mod time, 1 byte XFL, 1 byte OS */
-    for (i = 0; i < 6; i++)
-        (void) getc(fp);
-    /* consume "extra" field, if present */
-    if ((flags & FEXTRA) != 0) {
-        int len;
-
-        len = getc(fp);
-        len |= getc(fp) << 8;
-        while (len-- && getc(fp) != EOF)
-            ;
-    }
-    /* consume filename, if present */
-    if ((flags & FNAME) != 0) {
-        do {
-            ic = getc(fp);
-        } while (ic != 0 && ic != EOF);
-    }
-    /* consume comment, if present */
-    if ((flags & FCOMMENT) != 0) {
-        do {
-            ic = getc(fp);
-        } while (ic != 0 && ic != EOF);
-    }
-    /* consume 16-bit header CRC, if present */
-    if ((flags & FHCRC) != 0) {
-        (void) getc(fp);
-        (void) getc(fp);
-    }
-
-    if (feof(fp) || ferror(fp))
-        return false;
-
-    /* seek to the end; CRC and length are in the last 8 bytes */
-    long curPosn = ftell(fp);
-    unsigned char buf[8];
-    fseek(fp, -8, SEEK_END);
-    *pCompressedLen = ftell(fp) - curPosn;
-
-    if (fread(buf, 1, 8, fp) != 8)
-        return false;
-    /* seek back to start of compressed data */
-    fseek(fp, curPosn, SEEK_SET);
-
-    *pCompressionMethod = method;
-    *pCRC32 = ZipFileRO::get4LE(&buf[0]);
-    *pUncompressedLen = ZipFileRO::get4LE(&buf[4]);
-
-    return true;
-}
diff --git a/libs/utils/misc.cpp b/libs/utils/misc.cpp
index 445a23a..58eb499 100644
--- a/libs/utils/misc.cpp
+++ b/libs/utils/misc.cpp
@@ -25,7 +25,6 @@
 #include <sys/stat.h>
 #include <string.h>
 #include <errno.h>
-#include <assert.h>
 #include <stdio.h>
 
 #if defined(HAVE_PTHREADS)
@@ -38,56 +37,6 @@
 
 namespace android {
 
-/*
- * Get a file's type.
- */
-FileType getFileType(const char* fileName)
-{
-    struct stat sb;
-
-    if (stat(fileName, &sb) < 0) {
-        if (errno == ENOENT || errno == ENOTDIR)
-            return kFileTypeNonexistent;
-        else {
-            fprintf(stderr, "getFileType got errno=%d on '%s'\n",
-                errno, fileName);
-            return kFileTypeUnknown;
-        }
-    } else {
-        if (S_ISREG(sb.st_mode))
-            return kFileTypeRegular;
-        else if (S_ISDIR(sb.st_mode))
-            return kFileTypeDirectory;
-        else if (S_ISCHR(sb.st_mode))
-            return kFileTypeCharDev;
-        else if (S_ISBLK(sb.st_mode))
-            return kFileTypeBlockDev;
-        else if (S_ISFIFO(sb.st_mode))
-            return kFileTypeFifo;
-#ifdef HAVE_SYMLINKS            
-        else if (S_ISLNK(sb.st_mode))
-            return kFileTypeSymlink;
-        else if (S_ISSOCK(sb.st_mode))
-            return kFileTypeSocket;
-#endif            
-        else
-            return kFileTypeUnknown;
-    }
-}
-
-/*
- * Get a file's modification date.
- */
-time_t getFileModDate(const char* fileName)
-{
-    struct stat sb;
-
-    if (stat(fileName, &sb) < 0)
-        return (time_t) -1;
-
-    return sb.st_mtime;
-}
-
 struct sysprop_change_callback_info {
     sysprop_change_callback callback;
     int priority;
diff --git a/libs/utils/tests/Android.mk b/libs/utils/tests/Android.mk
index a2ca9c8..a6d9cbe 100644
--- a/libs/utils/tests/Android.mk
+++ b/libs/utils/tests/Android.mk
@@ -10,8 +10,7 @@
     LruCache_test.cpp \
     String8_test.cpp \
     Unicode_test.cpp \
-    Vector_test.cpp \
-    ZipFileRO_test.cpp
+    Vector_test.cpp
 
 shared_libraries := \
     libz \
diff --git a/libs/utils/tests/ZipFileRO_test.cpp b/libs/utils/tests/ZipFileRO_test.cpp
deleted file mode 100644
index 7a1d0bd..0000000
--- a/libs/utils/tests/ZipFileRO_test.cpp
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "ZipFileRO_test"
-#include <utils/Log.h>
-#include <utils/ZipFileRO.h>
-
-#include <gtest/gtest.h>
-
-#include <fcntl.h>
-#include <string.h>
-
-namespace android {
-
-class ZipFileROTest : public testing::Test {
-protected:
-    virtual void SetUp() {
-    }
-
-    virtual void TearDown() {
-    }
-};
-
-TEST_F(ZipFileROTest, ZipTimeConvertSuccess) {
-    struct tm t;
-
-    // 2011-06-29 14:40:40
-    long when = 0x3EDD7514;
-
-    ZipFileRO::zipTimeToTimespec(when, &t);
-
-    EXPECT_EQ(2011, t.tm_year + 1900)
-            << "Year was improperly converted.";
-
-    EXPECT_EQ(6, t.tm_mon)
-            << "Month was improperly converted.";
-
-    EXPECT_EQ(29, t.tm_mday)
-            << "Day was improperly converted.";
-
-    EXPECT_EQ(14, t.tm_hour)
-            << "Hour was improperly converted.";
-
-    EXPECT_EQ(40, t.tm_min)
-            << "Minute was improperly converted.";
-
-    EXPECT_EQ(40, t.tm_sec)
-            << "Second was improperly converted.";
-}
-
-}
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index 00bfa5a..c02a85f 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -21,6 +21,7 @@
 #include <errno.h>
 #include <dlfcn.h>
 #include <limits.h>
+#include <dirent.h>
 
 #include <cutils/log.h>
 #include <cutils/properties.h>
@@ -38,9 +39,25 @@
 
 
 /*
- * EGL drivers are called
+ * EGL userspace drivers must be provided either:
+ * - as a single library:
+ *      /vendor/lib/egl/libGLES.so
+ *
+ * - as separate libraries:
+ *      /vendor/lib/egl/libEGL.so
+ *      /vendor/lib/egl/libGLESv1_CM.so
+ *      /vendor/lib/egl/libGLESv2.so
+ *
+ * The software renderer for the emulator must be provided as a single
+ * library at:
+ *
+ *      /system/lib/egl/libGLES_android.so
+ *
+ *
+ * For backward compatibility and to facilitate the transition to
+ * this new naming scheme, the loader will additionally look for:
  * 
- * /system/lib/egl/lib{[EGL|GLESv1_CM|GLESv2] | GLES}_$TAG.so 
+ *      /{vendor|system}/lib/egl/lib{GLES | [EGL|GLESv1_CM|GLESv2]}_*.so
  * 
  */
 
@@ -137,41 +154,10 @@
 // ----------------------------------------------------------------------------
 
 Loader::Loader()
-{
-    char line[256];
-    char tag[256];
-
-    /* Special case for GLES emulation */
-    if (checkGlesEmulationStatus() == 0) {
-        ALOGD("Emulator without GPU support detected. "
-              "Fallback to software renderer.");
-        mDriverTag.setTo("android");
-        return;
-    }
-
-    /* Otherwise, use egl.cfg */
-    FILE* cfg = fopen("/system/lib/egl/egl.cfg", "r");
-    if (cfg == NULL) {
-        // default config
-        ALOGD("egl.cfg not found, using default config");
-        mDriverTag.setTo("android");
-    } else {
-        while (fgets(line, 256, cfg)) {
-            int dpy, impl;
-            if (sscanf(line, "%u %u %s", &dpy, &impl, tag) == 3) {
-                //ALOGD(">>> %u %u %s", dpy, impl, tag);
-                // We only load the h/w accelerated implementation
-                if (tag != String8("android")) {
-                    mDriverTag = tag;
-                }
-            }
-        }
-        fclose(cfg);
-    }
+    : getProcAddress(NULL) {
 }
 
-Loader::~Loader()
-{
+Loader::~Loader() {
     GLTrace_stop();
 }
 
@@ -180,26 +166,20 @@
     void* dso;
     driver_t* hnd = 0;
     
-    char const* tag = mDriverTag.string();
-    if (tag) {
-        dso = load_driver("GLES", tag, cnx, EGL | GLESv1_CM | GLESv2);
+    dso = load_driver("GLES", cnx, EGL | GLESv1_CM | GLESv2);
+    if (dso) {
+        hnd = new driver_t(dso);
+    } else {
+        // Always load EGL first
+        dso = load_driver("EGL", cnx, EGL);
         if (dso) {
             hnd = new driver_t(dso);
-        } else {
-            // Always load EGL first
-            dso = load_driver("EGL", tag, cnx, EGL);
-            if (dso) {
-                hnd = new driver_t(dso);
-                // TODO: make this more automated
-                hnd->set( load_driver("GLESv1_CM", tag, cnx, GLESv1_CM), GLESv1_CM );
-                hnd->set( load_driver("GLESv2",    tag, cnx, GLESv2),    GLESv2 );
-            }
+            hnd->set( load_driver("GLESv1_CM", cnx, GLESv1_CM), GLESv1_CM );
+            hnd->set( load_driver("GLESv2",    cnx, GLESv2),    GLESv2 );
         }
     }
 
-    LOG_FATAL_IF(!index && !hnd,
-            "couldn't find the default OpenGL ES implementation "
-            "for default display");
+    LOG_ALWAYS_FATAL_IF(!hnd, "couldn't find an OpenGL ES implementation");
     
     return (void*)hnd;
 }
@@ -267,21 +247,106 @@
     }
 }
 
-void *Loader::load_driver(const char* kind, const char *tag,
+void *Loader::load_driver(const char* kind,
         egl_connection_t* cnx, uint32_t mask)
 {
-    char driver_absolute_path[PATH_MAX];
-    const char* const search1 = "/vendor/lib/egl/lib%s_%s.so";
-    const char* const search2 = "/system/lib/egl/lib%s_%s.so";
+    class MatchFile {
+    public:
+        static String8 find(const char* kind) {
+            String8 result;
+            String8 pattern;
+            pattern.appendFormat("lib%s", kind);
+            const char* const searchPaths[] = {
+                    "/vendor/lib/egl",
+                    "/system/lib/egl"
+            };
 
-    snprintf(driver_absolute_path, PATH_MAX, search1, kind, tag);
-    if (access(driver_absolute_path, R_OK)) {
-        snprintf(driver_absolute_path, PATH_MAX, search2, kind, tag);
-        if (access(driver_absolute_path, R_OK)) {
-            // this happens often, we don't want to log an error
-            return 0;
+            // first, we search for the exact name of the GLES userspace
+            // driver in both locations.
+            // i.e.:
+            //      libGLES.so, or:
+            //      libEGL.so, libGLESv1_CM.so, libGLESv2.so
+
+            for (size_t i=0 ; i<NELEM(searchPaths) ; i++) {
+                if (find(result, pattern, searchPaths[i], true)) {
+                    return result;
+                }
+            }
+
+            // for compatibility with the old "egl.cfg" naming convention
+            // we look for files that match:
+            //      libGLES_*.so, or:
+            //      libEGL_*.so, libGLESv1_CM_*.so, libGLESv2_*.so
+
+            pattern.append("_");
+            for (size_t i=0 ; i<NELEM(searchPaths) ; i++) {
+                if (find(result, pattern, searchPaths[i], false)) {
+                    return result;
+                }
+            }
+
+            // we didn't find the driver. gah.
+            result.clear();
+            return result;
         }
+
+    private:
+        static bool find(String8& result,
+                const String8& pattern, const char* const search, bool exact) {
+
+            // in the emulator case, we just return the hardcoded name
+            // of the software renderer.
+            if (checkGlesEmulationStatus() == 0) {
+                ALOGD("Emulator without GPU support detected. "
+                      "Fallback to software renderer.");
+                result.setTo("/system/lib/egl/libGLES_android.so");
+                return true;
+            }
+
+            if (exact) {
+                String8 absolutePath;
+                absolutePath.appendFormat("%s/%s.so", search, pattern.string());
+                if (!access(absolutePath.string(), R_OK)) {
+                    result = absolutePath;
+                    return true;
+                }
+                return false;
+            }
+
+            DIR* d = opendir(search);
+            if (d != NULL) {
+                struct dirent cur;
+                struct dirent* e;
+                while (readdir_r(d, &cur, &e) == 0 && e) {
+                    if (e->d_type == DT_DIR) {
+                        continue;
+                    }
+                    if (!strcmp(e->d_name, "libGLES_android.so")) {
+                        // always skip the software renderer
+                        continue;
+                    }
+                    if (strstr(e->d_name, pattern.string()) == e->d_name) {
+                        if (!strcmp(e->d_name + strlen(e->d_name) - 3, ".so")) {
+                            result.clear();
+                            result.appendFormat("%s/%s", search, e->d_name);
+                            closedir(d);
+                            return true;
+                        }
+                    }
+                }
+                closedir(d);
+            }
+            return false;
+        }
+    };
+
+
+    String8 absolutePath = MatchFile::find(kind);
+    if (absolutePath.isEmpty()) {
+        // this happens often, we don't want to log an error
+        return 0;
     }
+    const char* const driver_absolute_path = absolutePath.string();
 
     void* dso = dlopen(driver_absolute_path, RTLD_NOW | RTLD_LOCAL);
     if (dso == 0) {
diff --git a/opengl/libs/EGL/Loader.h b/opengl/libs/EGL/Loader.h
index 30773cb..8cefe32 100644
--- a/opengl/libs/EGL/Loader.h
+++ b/opengl/libs/EGL/Loader.h
@@ -52,7 +52,6 @@
         void* dso[3];
     };
     
-    String8 mDriverTag;
     getProcAddressType getProcAddress;
     
 public:
@@ -63,7 +62,7 @@
     
 private:
     Loader();
-    void *load_driver(const char* kind, const char *tag, egl_connection_t* cnx, uint32_t mask);
+    void *load_driver(const char* kind, egl_connection_t* cnx, uint32_t mask);
 
     static __attribute__((noinline))
     void init_api(void* dso, 
diff --git a/opengl/tools/glgen/stubs/gles11/common.cpp b/opengl/tools/glgen/stubs/gles11/common.cpp
index 579d573..75b75cb 100644
--- a/opengl/tools/glgen/stubs/gles11/common.cpp
+++ b/opengl/tools/glgen/stubs/gles11/common.cpp
@@ -272,6 +272,7 @@
     int _needed = 0;
 
     params = (CTYPE *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    _remaining /= sizeof(CTYPE);    // convert from bytes to item count
     _needed = getNeededCount(pname);
     // if we didn't find this pname, we just assume the user passed
     // an array of the right size -- this might happen with extensions
diff --git a/services/powermanager/IPowerManager.cpp b/services/powermanager/IPowerManager.cpp
index 0265df3..3f5b81e 100644
--- a/services/powermanager/IPowerManager.cpp
+++ b/services/powermanager/IPowerManager.cpp
@@ -41,7 +41,8 @@
     {
     }
 
-    virtual status_t acquireWakeLock(int flags, const sp<IBinder>& lock, const String16& tag)
+    virtual status_t acquireWakeLock(int flags, const sp<IBinder>& lock, const String16& tag,
+            const String16& packageName)
     {
         Parcel data, reply;
         data.writeInterfaceToken(IPowerManager::getInterfaceDescriptor());
@@ -49,6 +50,7 @@
         data.writeStrongBinder(lock);
         data.writeInt32(flags);
         data.writeString16(tag);
+        data.writeString16(packageName);
         data.writeInt32(0); // no WorkSource
         return remote()->transact(ACQUIRE_WAKE_LOCK, data, &reply);
     }
diff --git a/services/sensorservice/Android.mk b/services/sensorservice/Android.mk
index dd698c5..14a4e55 100644
--- a/services/sensorservice/Android.mk
+++ b/services/sensorservice/Android.mk
@@ -12,11 +12,12 @@
     SensorDevice.cpp \
     SensorFusion.cpp \
     SensorInterface.cpp \
-    SensorService.cpp \
-
+    SensorService.cpp
 
 LOCAL_CFLAGS:= -DLOG_TAG=\"SensorService\"
 
+LOCAL_CFLAGS += -fvisibility=hidden
+
 LOCAL_SHARED_LIBRARIES := \
 	libcutils \
 	libhardware \
@@ -27,8 +28,6 @@
 	libui \
 	libgui
 
-
-
 LOCAL_MODULE:= libsensorservice
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/services/sensorservice/CorrectedGyroSensor.cpp b/services/sensorservice/CorrectedGyroSensor.cpp
index 1857443..09f60a9 100644
--- a/services/sensorservice/CorrectedGyroSensor.cpp
+++ b/services/sensorservice/CorrectedGyroSensor.cpp
@@ -69,7 +69,7 @@
 Sensor CorrectedGyroSensor::getSensor() const {
     sensor_t hwSensor;
     hwSensor.name       = "Corrected Gyroscope Sensor";
-    hwSensor.vendor     = "Google Inc.";
+    hwSensor.vendor     = "AOSP";
     hwSensor.version    = 1;
     hwSensor.handle     = '_cgy';
     hwSensor.type       = SENSOR_TYPE_GYROSCOPE;
diff --git a/services/sensorservice/GravitySensor.cpp b/services/sensorservice/GravitySensor.cpp
index c57715f..0bf20db 100644
--- a/services/sensorservice/GravitySensor.cpp
+++ b/services/sensorservice/GravitySensor.cpp
@@ -77,7 +77,7 @@
 Sensor GravitySensor::getSensor() const {
     sensor_t hwSensor;
     hwSensor.name       = "Gravity Sensor";
-    hwSensor.vendor     = "Google Inc.";
+    hwSensor.vendor     = "AOSP";
     hwSensor.version    = 3;
     hwSensor.handle     = '_grv';
     hwSensor.type       = SENSOR_TYPE_GRAVITY;
diff --git a/services/sensorservice/LinearAccelerationSensor.cpp b/services/sensorservice/LinearAccelerationSensor.cpp
index f0054f2..25ae473 100644
--- a/services/sensorservice/LinearAccelerationSensor.cpp
+++ b/services/sensorservice/LinearAccelerationSensor.cpp
@@ -62,7 +62,7 @@
     Sensor gsensor(mGravitySensor.getSensor());
     sensor_t hwSensor;
     hwSensor.name       = "Linear Acceleration Sensor";
-    hwSensor.vendor     = "Google Inc.";
+    hwSensor.vendor     = "AOSP";
     hwSensor.version    = gsensor.getVersion();
     hwSensor.handle     = '_lin';
     hwSensor.type       = SENSOR_TYPE_LINEAR_ACCELERATION;
diff --git a/services/sensorservice/OrientationSensor.cpp b/services/sensorservice/OrientationSensor.cpp
index 037adaa..b146332 100644
--- a/services/sensorservice/OrientationSensor.cpp
+++ b/services/sensorservice/OrientationSensor.cpp
@@ -33,6 +33,9 @@
     : mSensorDevice(SensorDevice::getInstance()),
       mSensorFusion(SensorFusion::getInstance())
 {
+    // FIXME: instead of using the SensorFusion code, we should use
+    // the SENSOR_TYPE_ROTATION_VECTOR instead. This way we could use the
+    // HAL's implementation.
 }
 
 bool OrientationSensor::process(sensors_event_t* outEvent,
@@ -73,7 +76,7 @@
 Sensor OrientationSensor::getSensor() const {
     sensor_t hwSensor;
     hwSensor.name       = "Orientation Sensor";
-    hwSensor.vendor     = "Google Inc.";
+    hwSensor.vendor     = "AOSP";
     hwSensor.version    = 1;
     hwSensor.handle     = '_ypr';
     hwSensor.type       = SENSOR_TYPE_ORIENTATION;
diff --git a/services/sensorservice/RotationVectorSensor.cpp b/services/sensorservice/RotationVectorSensor.cpp
index 5ea9568..725deb4 100644
--- a/services/sensorservice/RotationVectorSensor.cpp
+++ b/services/sensorservice/RotationVectorSensor.cpp
@@ -63,7 +63,7 @@
 Sensor RotationVectorSensor::getSensor() const {
     sensor_t hwSensor;
     hwSensor.name       = "Rotation Vector Sensor";
-    hwSensor.vendor     = "Google Inc.";
+    hwSensor.vendor     = "AOSP";
     hwSensor.version    = 3;
     hwSensor.handle     = '_rov';
     hwSensor.type       = SENSOR_TYPE_ROTATION_VECTOR;
@@ -112,7 +112,7 @@
 Sensor GyroDriftSensor::getSensor() const {
     sensor_t hwSensor;
     hwSensor.name       = "Gyroscope Bias (debug)";
-    hwSensor.vendor     = "Google Inc.";
+    hwSensor.vendor     = "AOSP";
     hwSensor.version    = 1;
     hwSensor.handle     = '_gbs';
     hwSensor.type       = SENSOR_TYPE_ACCELEROMETER;
diff --git a/services/sensorservice/SensorFusion.cpp b/services/sensorservice/SensorFusion.cpp
index d23906d..4837b97 100644
--- a/services/sensorservice/SensorFusion.cpp
+++ b/services/sensorservice/SensorFusion.cpp
@@ -28,6 +28,7 @@
       mEnabled(false), mGyroTime(0)
 {
     sensor_t const* list;
+    Sensor uncalibratedGyro;
     ssize_t count = mSensorDevice.getSensorList(&list);
     if (count > 0) {
         for (size_t i=0 ; i<size_t(count) ; i++) {
@@ -39,18 +40,27 @@
             }
             if (list[i].type == SENSOR_TYPE_GYROSCOPE) {
                 mGyro = Sensor(list + i);
-                // 200 Hz for gyro events is a good compromise between precision
-                // and power/cpu usage.
-                mGyroRate = 200;
-                mTargetDelayNs = 1000000000LL/mGyroRate;
+            }
+            if (list[i].type == SENSOR_TYPE_GYROSCOPE_UNCALIBRATED) {
+                uncalibratedGyro = Sensor(list + i);
             }
         }
+
+        // Use the uncalibrated gyroscope for sensor fusion when available
+        if (uncalibratedGyro.getType() == SENSOR_TYPE_GYROSCOPE_UNCALIBRATED) {
+            mGyro = uncalibratedGyro;
+        }
+
+        // 200 Hz for gyro events is a good compromise between precision
+        // and power/cpu usage.
+        mGyroRate = 200;
+        mTargetDelayNs = 1000000000LL/mGyroRate;
         mFusion.init();
     }
 }
 
 void SensorFusion::process(const sensors_event_t& event) {
-    if (event.type == SENSOR_TYPE_GYROSCOPE) {
+    if (event.type == mGyro.getType()) {
         if (mGyroTime != 0) {
             const float dT = (event.timestamp - mGyroTime) / 1000000000.0f;
             const float freq = 1 / dT;
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index ebf5cf0..4718447 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -93,6 +93,7 @@
                         orientationIndex = i;
                         break;
                     case SENSOR_TYPE_GYROSCOPE:
+                    case SENSOR_TYPE_GYROSCOPE_UNCALIBRATED:
                         hasGyro = true;
                         break;
                     case SENSOR_TYPE_GRAVITY:
@@ -108,54 +109,44 @@
             // registered)
             const SensorFusion& fusion(SensorFusion::getInstance());
 
-            if (hasGyro) {
-                // Always instantiate Android's virtual sensors. Since they are
-                // instantiated behind sensors from the HAL, they won't
-                // interfere with applications, unless they looks specifically
-                // for them (by name).
-
-                registerVirtualSensor( new RotationVectorSensor() );
-                registerVirtualSensor( new GravitySensor(list, count) );
-                registerVirtualSensor( new LinearAccelerationSensor(list, count) );
-
-                // these are optional
-                registerVirtualSensor( new OrientationSensor() );
-                registerVirtualSensor( new CorrectedGyroSensor(list, count) );
-            }
-
             // build the sensor list returned to users
             mUserSensorList = mSensorList;
 
             if (hasGyro) {
+                Sensor aSensor;
+
+                // Add Android virtual sensors if they're not already
+                // available in the HAL
+
+                aSensor = registerVirtualSensor( new RotationVectorSensor() );
+                if (virtualSensorsNeeds & (1<<SENSOR_TYPE_ROTATION_VECTOR)) {
+                    mUserSensorList.add(aSensor);
+                }
+
+                aSensor = registerVirtualSensor( new GravitySensor(list, count) );
+                if (virtualSensorsNeeds & (1<<SENSOR_TYPE_GRAVITY)) {
+                    mUserSensorList.add(aSensor);
+                }
+
+                aSensor = registerVirtualSensor( new LinearAccelerationSensor(list, count) );
+                if (virtualSensorsNeeds & (1<<SENSOR_TYPE_LINEAR_ACCELERATION)) {
+                    mUserSensorList.add(aSensor);
+                }
+
+                aSensor = registerVirtualSensor( new OrientationSensor() );
+                if (virtualSensorsNeeds & (1<<SENSOR_TYPE_ROTATION_VECTOR)) {
+                    // if we are doing our own rotation-vector, also add
+                    // the orientation sensor and remove the HAL provided one.
+                    mUserSensorList.replaceAt(aSensor, orientationIndex);
+                }
+
                 // virtual debugging sensors are not added to mUserSensorList
+                registerVirtualSensor( new CorrectedGyroSensor(list, count) );
                 registerVirtualSensor( new GyroDriftSensor() );
             }
 
-            if (hasGyro &&
-                    (virtualSensorsNeeds & (1<<SENSOR_TYPE_ROTATION_VECTOR))) {
-                // if we have the fancy sensor fusion, and it's not provided by the
-                // HAL, use our own (fused) orientation sensor by removing the
-                // HAL supplied one form the user list.
-                if (orientationIndex >= 0) {
-                    mUserSensorList.removeItemsAt(orientationIndex);
-                }
-            }
-
             // debugging sensor list
-            for (size_t i=0 ; i<mSensorList.size() ; i++) {
-                switch (mSensorList[i].getType()) {
-                    case SENSOR_TYPE_GRAVITY:
-                    case SENSOR_TYPE_LINEAR_ACCELERATION:
-                    case SENSOR_TYPE_ROTATION_VECTOR:
-                        if (strstr(mSensorList[i].getVendor().string(), "Google")) {
-                            mUserSensorListDebug.add(mSensorList[i]);
-                        }
-                        break;
-                    default:
-                        mUserSensorListDebug.add(mSensorList[i]);
-                        break;
-                }
-            }
+            mUserSensorListDebug = mSensorList;
 
             run("SensorService", PRIORITY_URGENT_DISPLAY);
             mInitCheck = NO_ERROR;
@@ -163,7 +154,7 @@
     }
 }
 
-void SensorService::registerSensor(SensorInterface* s)
+Sensor SensorService::registerSensor(SensorInterface* s)
 {
     sensors_event_t event;
     memset(&event, 0, sizeof(event));
@@ -175,12 +166,15 @@
     mSensorMap.add(sensor.getHandle(), s);
     // create an entry in the mLastEventSeen array
     mLastEventSeen.add(sensor.getHandle(), event);
+
+    return sensor;
 }
 
-void SensorService::registerVirtualSensor(SensorInterface* s)
+Sensor SensorService::registerVirtualSensor(SensorInterface* s)
 {
-    registerSensor(s);
+    Sensor sensor = registerSensor(s);
     mVirtualSensorList.add( s );
+    return sensor;
 }
 
 SensorService::~SensorService()
diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h
index 25e5f76..67489cc 100644
--- a/services/sensorservice/SensorService.h
+++ b/services/sensorservice/SensorService.h
@@ -50,12 +50,13 @@
         public BnSensorServer,
         protected Thread
 {
-   friend class BinderService<SensorService>;
+    friend class BinderService<SensorService>;
 
-   static const nsecs_t MINIMUM_EVENTS_PERIOD =   1000000; // 1000 Hz
-   static const char* WAKE_LOCK_NAME;
+    static const nsecs_t MINIMUM_EVENTS_PERIOD =   1000000; // 1000 Hz
+    static const char* WAKE_LOCK_NAME;
 
-            SensorService();
+    static char const* getServiceName() ANDROID_API { return "sensorservice"; }
+    SensorService() ANDROID_API;
     virtual ~SensorService();
 
     virtual void onFirstRef();
@@ -113,12 +114,12 @@
     int getSensorType(int handle) const;
     void recordLastValue(sensors_event_t const * buffer, size_t count);
     static void sortEventBuffer(sensors_event_t* buffer, size_t count);
-    void registerSensor(SensorInterface* sensor);
-    void registerVirtualSensor(SensorInterface* sensor);
+    Sensor registerSensor(SensorInterface* sensor);
+    Sensor registerVirtualSensor(SensorInterface* sensor);
     status_t cleanupWithoutDisable(const sp<SensorEventConnection>& connection,
-        int handle);
+            int handle);
     void cleanupAutoDisabledSensor(const sp<SensorEventConnection>& connection,
-        sensors_event_t const* buffer, const int count);
+            sensors_event_t const* buffer, const int count);
 
     // constants
     Vector<Sensor> mSensorList;
@@ -138,8 +139,6 @@
     KeyedVector<int32_t, sensors_event_t> mLastEventSeen;
 
 public:
-    static char const* getServiceName() { return "sensorservice"; }
-
     void cleanupConnection(SensorEventConnection* connection);
     status_t enable(const sp<SensorEventConnection>& connection, int handle);
     status_t disable(const sp<SensorEventConnection>& connection, int handle);
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index ec296d3..71b235a 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -41,6 +41,8 @@
   LOCAL_CFLAGS += -DNUM_FRAMEBUFFER_SURFACE_BUFFERS=$(NUM_FRAMEBUFFER_SURFACE_BUFFERS)
 endif
 
+LOCAL_CFLAGS += -fvisibility=hidden
+
 LOCAL_SHARED_LIBRARIES := \
 	libcutils \
 	liblog \
diff --git a/services/surfaceflinger/Colorizer.h b/services/surfaceflinger/Colorizer.h
new file mode 100644
index 0000000..6524481
--- /dev/null
+++ b/services/surfaceflinger/Colorizer.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_SURFACE_FLINGER_COLORIZER_H
+#define ANDROID_SURFACE_FLINGER_COLORIZER_H
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+class Colorizer {
+    bool mEnabled;
+public:
+    enum color {
+        RED     = 31,
+        GREEN   = 32,
+        YELLOW  = 33,
+        BLUE    = 34,
+        MAGENTA = 35,
+        CYAN    = 36,
+        WHITE   = 37
+    };
+
+    Colorizer(bool enabled)
+        : mEnabled(enabled) {
+    }
+
+    void colorize(String8& out, color c) {
+        if (mEnabled) {
+            out.appendFormat("\e[%dm", c);
+        }
+    }
+
+    void bold(String8& out) {
+        if (mEnabled) {
+            out.append("\e[1m");
+        }
+    }
+
+    void reset(String8& out) {
+        if (mEnabled) {
+            out.append("\e[0m");
+        }
+    }
+};
+
+// ---------------------------------------------------------------------------
+
+}; // namespace android
+
+
+#endif /* ANDROID_SURFACE_FLINGER_COLORIZER_H */
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 68b0b7f..b001bdb 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -416,7 +416,7 @@
 
     mScissor = mGlobalTransform.transform(viewport);
     if (mScissor.isEmpty()) {
-        mScissor.set(getBounds());
+        mScissor = getBounds();
     }
 
     mOrientation = orientation;
@@ -424,9 +424,9 @@
     mFrame = frame;
 }
 
-void DisplayDevice::dump(String8& result, char* buffer, size_t SIZE) const {
+void DisplayDevice::dump(String8& result) const {
     const Transform& tr(mGlobalTransform);
-    snprintf(buffer, SIZE,
+    result.appendFormat(
         "+ DisplayDevice: %s\n"
         "   type=%x, hwcId=%d, layerStack=%u, (%4dx%4d), ANativeWindow=%p, orient=%2d (type=%08x), "
         "flips=%u, isSecure=%d, secureVis=%d, acquired=%d, numLayers=%u\n"
@@ -443,8 +443,6 @@
         tr[0][1], tr[1][1], tr[2][1],
         tr[0][2], tr[1][2], tr[2][2]);
 
-    result.append(buffer);
-
     String8 surfaceDump;
     mDisplaySurface->dump(surfaceDump);
     result.append(surfaceDump);
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index 377d924..047eecd 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -153,7 +153,7 @@
      * Debugging
      */
     uint32_t getPageFlipCount() const;
-    void dump(String8& result, char* buffer, size_t SIZE) const;
+    void dump(String8& result) const;
 
 private:
     /*
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
index 54a3ce8..10bca38 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
@@ -103,8 +103,8 @@
     if (mCurrentBufferSlot != BufferQueue::INVALID_BUFFER_SLOT &&
         item.mBuf != mCurrentBufferSlot) {
         // Release the previous buffer.
-        err = releaseBufferLocked(mCurrentBufferSlot, EGL_NO_DISPLAY,
-                EGL_NO_SYNC_KHR);
+        err = releaseBufferLocked(mCurrentBufferSlot, mCurrentBuffer,
+                EGL_NO_DISPLAY, EGL_NO_SYNC_KHR);
         if (err != NO_ERROR && err != BufferQueue::STALE_BUFFER_SLOT) {
             ALOGE("error releasing buffer: %s (%d)", strerror(-err), err);
             return err;
@@ -144,7 +144,8 @@
     sp<Fence> fence = mHwc.getAndResetReleaseFence(mDisplayType);
     if (fence->isValid() &&
             mCurrentBufferSlot != BufferQueue::INVALID_BUFFER_SLOT) {
-        status_t err = addReleaseFence(mCurrentBufferSlot, fence);
+        status_t err = addReleaseFence(mCurrentBufferSlot,
+                mCurrentBuffer, fence);
         ALOGE_IF(err, "setReleaseFenceFd: failed to add the fence: %s (%d)",
                 strerror(-err), err);
     }
@@ -175,11 +176,10 @@
     ConsumerBase::dump(result);
 }
 
-void FramebufferSurface::dumpLocked(String8& result, const char* prefix,
-            char* buffer, size_t SIZE) const
+void FramebufferSurface::dumpLocked(String8& result, const char* prefix) const
 {
     mHwc.fbDump(result);
-    ConsumerBase::dumpLocked(result, prefix, buffer, SIZE);
+    ConsumerBase::dumpLocked(result, prefix);
 }
 
 // ----------------------------------------------------------------------------
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
index 2fde789..c86e9ae 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
@@ -55,8 +55,7 @@
     virtual void onFrameAvailable();
     virtual void freeBufferLocked(int slotIndex);
 
-    virtual void dumpLocked(String8& result, const char* prefix,
-            char* buffer, size_t SIZE) const;
+    virtual void dumpLocked(String8& result, const char* prefix) const;
 
     // nextBuffer waits for and then latches the next buffer from the
     // BufferQueue and releases the previously latched buffer to the
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index a9afbe5..5082192 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -550,9 +550,6 @@
         // triggers a Surface::queueBuffer()  on some
         // devices (!?) -- log and ignore.
         ALOGE("HWComposer: framebufferTarget is null");
-//        CallStack stack;
-//        stack.update();
-//        stack.dump("");
         return NO_ERROR;
     }
 
@@ -962,7 +959,7 @@
     return getLayerIterator(id, numLayers);
 }
 
-void HWComposer::dump(String8& result, char* buffer, size_t SIZE) const {
+void HWComposer::dump(String8& result) const {
     if (mHwc) {
         result.appendFormat("Hardware Composer state (version %8x):\n", hwcApiVersion(mHwc));
         result.appendFormat("  mDebugForceFakeVSync=%d\n", mDebugForceFakeVSync);
@@ -1030,6 +1027,8 @@
     }
 
     if (mHwc && mHwc->dump) {
+        const size_t SIZE = 4096;
+        char buffer[SIZE];
         mHwc->dump(mHwc, buffer, SIZE);
         result.append(buffer);
     }
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 604de38..a20da08 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -275,7 +275,7 @@
     friend class VSyncThread;
 
     // for debugging ----------------------------------------------------------
-    void dump(String8& out, char* scratch, size_t SIZE) const;
+    void dump(String8& out) const;
 
 private:
     void loadHwcModule();
diff --git a/services/surfaceflinger/EventThread.cpp b/services/surfaceflinger/EventThread.cpp
index 4d0fc79..4126c8a 100644
--- a/services/surfaceflinger/EventThread.cpp
+++ b/services/surfaceflinger/EventThread.cpp
@@ -320,7 +320,7 @@
     mDebugVsyncEnabled = false;
 }
 
-void EventThread::dump(String8& result, char* buffer, size_t SIZE) const {
+void EventThread::dump(String8& result) const {
     Mutex::Autolock _l(mLock);
     result.appendFormat("VSYNC state: %s\n",
             mDebugVsyncEnabled?"enabled":"disabled");
diff --git a/services/surfaceflinger/EventThread.h b/services/surfaceflinger/EventThread.h
index 1934f98..f6bd676 100644
--- a/services/surfaceflinger/EventThread.h
+++ b/services/surfaceflinger/EventThread.h
@@ -84,7 +84,7 @@
     Vector< sp<EventThread::Connection> > waitForEvent(
             DisplayEventReceiver::Event* event);
 
-    void dump(String8& result, char* buffer, size_t SIZE) const;
+    void dump(String8& result) const;
 
 private:
     virtual bool        threadLoop();
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 4779804..ee69222 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -36,6 +36,7 @@
 #include <gui/Surface.h>
 
 #include "clz.h"
+#include "Colorizer.h"
 #include "DisplayDevice.h"
 #include "GLExtensions.h"
 #include "Layer.h"
@@ -269,13 +270,24 @@
     return mCurrentTransform;
 }
 
+static Rect reduce(const Rect& win, const Region& exclude) {
+    if (CC_LIKELY(exclude.isEmpty())) {
+        return win;
+    }
+    if (exclude.isRect()) {
+        return win.reduce(exclude.getBounds());
+    }
+    return Region(win).subtract(exclude).getBounds();
+}
+
 Rect Layer::computeBounds() const {
     const Layer::State& s(drawingState());
     Rect win(s.active.w, s.active.h);
     if (!s.active.crop.isEmpty()) {
         win.intersect(s.active.crop, &win);
     }
-    return win;
+    // subtract the transparent region and snap to the bounds
+    return reduce(win, s.activeTransparentRegion);
 }
 
 Rect Layer::computeCrop(const sp<const DisplayDevice>& hw) const {
@@ -309,6 +321,9 @@
     // window's bounds
     activeCrop.intersect(Rect(s.active.w, s.active.h), &activeCrop);
 
+    // subtract the transparent region and snap to the bounds
+    activeCrop = reduce(activeCrop, s.activeTransparentRegion);
+
     if (!activeCrop.isEmpty()) {
         // Transform the window crop to match the buffer coordinate system,
         // which means using the inverse of the current transform set on the
@@ -544,31 +559,88 @@
     clearWithOpenGL(hw, clip, 0,0,0,0);
 }
 
+static void setupOpenGL10(bool premultipliedAlpha, bool opaque, int alpha) {
+    // OpenGL ES 1.0 doesn't support texture combiners.
+    // This path doesn't properly handle opaque layers that have non-opaque
+    // alpha values. The alpha channel will be copied into the framebuffer or
+    // screenshot, so if the framebuffer or screenshot is blended on top of
+    // something else,  whatever is below the window will incorrectly show
+    // through.
+    if (CC_UNLIKELY(alpha < 0xFF)) {
+        GLfloat floatAlpha = alpha * (1.0f / 255.0f);
+        if (premultipliedAlpha) {
+            glColor4f(floatAlpha, floatAlpha, floatAlpha, floatAlpha);
+        } else {
+            glColor4f(1.0f, 1.0f, 1.0f, floatAlpha);
+        }
+        glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+    } else {
+        glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+    }
+}
+
+static void setupOpenGL11(bool premultipliedAlpha, bool opaque, int alpha) {
+    GLenum combineRGB;
+    GLenum combineAlpha;
+    GLenum src0Alpha;
+    GLfloat envColor[4];
+
+    if (CC_UNLIKELY(alpha < 0xFF)) {
+        // Cv = premultiplied ? Cs*alpha : Cs
+        // Av = !opaque       ? alpha*As : 1.0
+        combineRGB   = premultipliedAlpha ? GL_MODULATE : GL_REPLACE;
+        combineAlpha = !opaque            ? GL_MODULATE : GL_REPLACE;
+        src0Alpha    = GL_CONSTANT;
+        envColor[0]  = alpha * (1.0f / 255.0f);
+    } else {
+        // Cv = Cs
+        // Av = opaque ? 1.0 : As
+        combineRGB   = GL_REPLACE;
+        combineAlpha = GL_REPLACE;
+        src0Alpha    = opaque ? GL_CONSTANT : GL_TEXTURE;
+        envColor[0]  = 1.0f;
+    }
+
+    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
+    glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, combineRGB);
+    glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE);
+    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
+    if (combineRGB == GL_MODULATE) {
+        glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_CONSTANT);
+        glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
+    }
+    glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, combineAlpha);
+    glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, src0Alpha);
+    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
+    if (combineAlpha == GL_MODULATE) {
+        glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_TEXTURE);
+        glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
+    }
+    if (combineRGB == GL_MODULATE || src0Alpha == GL_CONSTANT) {
+        envColor[1] = envColor[0];
+        envColor[2] = envColor[0];
+        envColor[3] = envColor[0];
+        glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, envColor);
+    }
+}
+
 void Layer::drawWithOpenGL(
         const sp<const DisplayDevice>& hw, const Region& clip) const {
     const uint32_t fbHeight = hw->getHeight();
     const State& s(drawingState());
 
-    GLenum src = mPremultipliedAlpha ? GL_ONE : GL_SRC_ALPHA;
-    if (CC_UNLIKELY(s.alpha < 0xFF)) {
-        const GLfloat alpha = s.alpha * (1.0f/255.0f);
-        if (mPremultipliedAlpha) {
-            glColor4f(alpha, alpha, alpha, alpha);
-        } else {
-            glColor4f(1, 1, 1, alpha);
-        }
-        glEnable(GL_BLEND);
-        glBlendFunc(src, GL_ONE_MINUS_SRC_ALPHA);
-        glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+    if (mFlinger->getGlesVersion() == GLES_VERSION_1_0) {
+        setupOpenGL10(mPremultipliedAlpha, isOpaque(), s.alpha);
     } else {
-        glColor4f(1, 1, 1, 1);
-        glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
-        if (!isOpaque()) {
-            glEnable(GL_BLEND);
-            glBlendFunc(src, GL_ONE_MINUS_SRC_ALPHA);
-        } else {
-            glDisable(GL_BLEND);
-        }
+        setupOpenGL11(mPremultipliedAlpha, isOpaque(), s.alpha);
+    }
+
+    if (s.alpha < 0xFF || !isOpaque()) {
+        glEnable(GL_BLEND);
+        glBlendFunc(mPremultipliedAlpha ? GL_ONE : GL_SRC_ALPHA,
+                    GL_ONE_MINUS_SRC_ALPHA);
+    } else {
+        glDisable(GL_BLEND);
     }
 
     LayerMesh mesh;
@@ -665,6 +737,8 @@
     if (!s.active.crop.isEmpty()) {
         win.intersect(s.active.crop, &win);
     }
+    // subtract the transparent region and snap to the bounds
+    win = reduce(win, s.activeTransparentRegion);
     if (mesh) {
         tr.transform(mesh->mVertices[0], win.left,  win.top);
         tr.transform(mesh->mVertices[1], win.left,  win.bottom);
@@ -1178,21 +1252,21 @@
 // debugging
 // ----------------------------------------------------------------------------
 
-void Layer::dump(String8& result, char* buffer, size_t SIZE) const
+void Layer::dump(String8& result, Colorizer& colorizer) const
 {
     const Layer::State& s(drawingState());
 
-    snprintf(buffer, SIZE,
+    colorizer.colorize(result, Colorizer::GREEN);
+    result.appendFormat(
             "+ %s %p (%s)\n",
             getTypeId(), this, getName().string());
-    result.append(buffer);
+    colorizer.reset(result);
 
     s.activeTransparentRegion.dump(result, "transparentRegion");
     visibleRegion.dump(result, "visibleRegion");
     sp<Client> client(mClientRef.promote());
 
-    snprintf(buffer, SIZE,
-            "      "
+    result.appendFormat(            "      "
             "layerStack=%4d, z=%9d, pos=(%g,%g), size=(%4d,%4d), crop=(%4d,%4d,%4d,%4d), "
             "isOpaque=%1d, invalidate=%1d, "
             "alpha=0x%02x, flags=0x%08x, tr=[%.2f, %.2f][%.2f, %.2f]\n"
@@ -1205,7 +1279,6 @@
             s.transform[0][0], s.transform[0][1],
             s.transform[1][0], s.transform[1][1],
             client.get());
-    result.append(buffer);
 
     sp<const GraphicBuffer> buf0(mActiveBuffer);
     uint32_t w0=0, h0=0, s0=0, f0=0;
@@ -1215,26 +1288,19 @@
         s0 = buf0->getStride();
         f0 = buf0->format;
     }
-    snprintf(buffer, SIZE,
+    result.appendFormat(
             "      "
             "format=%2d, activeBuffer=[%4ux%4u:%4u,%3X],"
             " queued-frames=%d, mRefreshPending=%d\n",
             mFormat, w0, h0, s0,f0,
             mQueuedFrames, mRefreshPending);
 
-    result.append(buffer);
-
     if (mSurfaceFlingerConsumer != 0) {
-        mSurfaceFlingerConsumer->dump(result, "            ", buffer, SIZE);
+        mSurfaceFlingerConsumer->dump(result, "            ");
     }
 }
 
-
-void Layer::shortDump(String8& result, char* scratch, size_t size) const {
-    Layer::dump(result, scratch, size);
-}
-
-void Layer::dumpStats(String8& result, char* buffer, size_t SIZE) const {
+void Layer::dumpStats(String8& result) const {
     mFrameTracker.dump(result);
 }
 
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 2765db1..11fdbb5 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -51,6 +51,7 @@
 // ---------------------------------------------------------------------------
 
 class Client;
+class Colorizer;
 class DisplayDevice;
 class GraphicBuffer;
 class SurfaceFlinger;
@@ -304,9 +305,8 @@
 
 
     /* always call base class first */
-    virtual void dump(String8& result, char* scratch, size_t size) const;
-    virtual void shortDump(String8& result, char* scratch, size_t size) const;
-    virtual void dumpStats(String8& result, char* buffer, size_t SIZE) const;
+    virtual void dump(String8& result, Colorizer& colorizer) const;
+    virtual void dumpStats(String8& result) const;
     virtual void clearStats();
 
 protected:
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index ef0d521..fbd9f25 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -55,10 +55,11 @@
 #include <private/android_filesystem_config.h>
 #include <private/gui/SyncFeatures.h>
 
+#include "Client.h"
 #include "clz.h"
+#include "Colorizer.h"
 #include "DdmConnection.h"
 #include "DisplayDevice.h"
-#include "Client.h"
 #include "EventThread.h"
 #include "GLExtensions.h"
 #include "Layer.h"
@@ -413,6 +414,22 @@
     return ctxt;
 }
 
+static GlesVersion parseGlesVersion(const char* str) {
+    int major, minor;
+    if (sscanf(str, "OpenGL ES-CM %d.%d", &major, &minor) != 2) {
+        ALOGW("Unable to parse GL_VERSION string: \"%s\"", str);
+        return GLES_VERSION_1_0;
+    }
+
+    if (major == 1 && minor == 0) return GLES_VERSION_1_0;
+    if (major == 1 && minor >= 1) return GLES_VERSION_1_1;
+    if (major == 2 && minor >= 0) return GLES_VERSION_2_0;
+    if (major == 3 && minor >= 0) return GLES_VERSION_3_0;
+
+    ALOGW("Unrecognized OpenGL ES version: %d.%d", major, minor);
+    return GLES_VERSION_1_0;
+}
+
 void SurfaceFlinger::initializeGL(EGLDisplay display) {
     GLExtensions& extensions(GLExtensions::getInstance());
     extensions.initWithGLStrings(
@@ -424,6 +441,8 @@
             eglQueryString(display, EGL_VERSION),
             eglQueryString(display, EGL_EXTENSIONS));
 
+    mGlesVersion = parseGlesVersion(extensions.getVersion());
+
     glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
     glGetIntegerv(GL_MAX_VIEWPORT_DIMS, mMaxViewportDims);
 
@@ -2145,19 +2164,15 @@
 
 status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args)
 {
-    const size_t SIZE = 4096;
-    char buffer[SIZE];
     String8 result;
 
-
     IPCThreadState* ipc = IPCThreadState::self();
     const int pid = ipc->getCallingPid();
     const int uid = ipc->getCallingUid();
     if ((uid != AID_SHELL) &&
             !PermissionCache::checkPermission(sDump, pid, uid)) {
-        snprintf(buffer, SIZE, "Permission Denial: "
+        result.appendFormat("Permission Denial: "
                 "can't dump SurfaceFlinger from pid=%d, uid=%d\n", pid, uid);
-        result.append(buffer);
     } else {
         // Try to get the main lock, but don't insist if we can't
         // (this would indicate SF is stuck, but we want to be able to
@@ -2168,10 +2183,9 @@
         }
         const bool locked(retry >= 0);
         if (!locked) {
-            snprintf(buffer, SIZE,
+            result.append(
                     "SurfaceFlinger appears to be unresponsive, "
                     "dumping anyways (no locks held)\n");
-            result.append(buffer);
         }
 
         bool dumpAll = true;
@@ -2181,27 +2195,27 @@
             if ((index < numArgs) &&
                     (args[index] == String16("--list"))) {
                 index++;
-                listLayersLocked(args, index, result, buffer, SIZE);
+                listLayersLocked(args, index, result);
                 dumpAll = false;
             }
 
             if ((index < numArgs) &&
                     (args[index] == String16("--latency"))) {
                 index++;
-                dumpStatsLocked(args, index, result, buffer, SIZE);
+                dumpStatsLocked(args, index, result);
                 dumpAll = false;
             }
 
             if ((index < numArgs) &&
                     (args[index] == String16("--latency-clear"))) {
                 index++;
-                clearStatsLocked(args, index, result, buffer, SIZE);
+                clearStatsLocked(args, index, result);
                 dumpAll = false;
             }
         }
 
         if (dumpAll) {
-            dumpAllLocked(result, buffer, SIZE);
+            dumpAllLocked(args, index, result);
         }
 
         if (locked) {
@@ -2213,19 +2227,18 @@
 }
 
 void SurfaceFlinger::listLayersLocked(const Vector<String16>& args, size_t& index,
-        String8& result, char* buffer, size_t SIZE) const
+        String8& result) const
 {
     const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
     const size_t count = currentLayers.size();
     for (size_t i=0 ; i<count ; i++) {
         const sp<Layer>& layer(currentLayers[i]);
-        snprintf(buffer, SIZE, "%s\n", layer->getName().string());
-        result.append(buffer);
+        result.appendFormat("%s\n", layer->getName().string());
     }
 }
 
 void SurfaceFlinger::dumpStatsLocked(const Vector<String16>& args, size_t& index,
-        String8& result, char* buffer, size_t SIZE) const
+        String8& result) const
 {
     String8 name;
     if (index < args.size()) {
@@ -2245,14 +2258,14 @@
         for (size_t i=0 ; i<count ; i++) {
             const sp<Layer>& layer(currentLayers[i]);
             if (name == layer->getName()) {
-                layer->dumpStats(result, buffer, SIZE);
+                layer->dumpStats(result);
             }
         }
     }
 }
 
 void SurfaceFlinger::clearStatsLocked(const Vector<String16>& args, size_t& index,
-        String8& result, char* buffer, size_t SIZE)
+        String8& result)
 {
     String8 name;
     if (index < args.size()) {
@@ -2292,9 +2305,18 @@
     result.append(config);
 }
 
-void SurfaceFlinger::dumpAllLocked(
-        String8& result, char* buffer, size_t SIZE) const
+void SurfaceFlinger::dumpAllLocked(const Vector<String16>& args, size_t& index,
+        String8& result) const
 {
+    bool colorize = false;
+    if (index < args.size()
+            && (args[index] == String16("--color"))) {
+        colorize = true;
+        index++;
+    }
+
+    Colorizer colorizer(colorize);
+
     // figure out if we're stuck somewhere
     const nsecs_t now = systemTime();
     const nsecs_t inSwapBuffers(mDebugInSwapBuffers);
@@ -2305,13 +2327,18 @@
     /*
      * Dump library configuration.
      */
+
+    colorizer.bold(result);
     result.append("Build configuration:");
+    colorizer.reset(result);
     appendSfConfigString(result);
     appendUiConfigString(result);
     appendGuiConfigString(result);
     result.append("\n");
 
+    colorizer.bold(result);
     result.append("Sync configuration: ");
+    colorizer.reset(result);
     result.append(SyncFeatures::getInstance().toString());
     result.append("\n");
 
@@ -2320,56 +2347,57 @@
      */
     const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
     const size_t count = currentLayers.size();
-    snprintf(buffer, SIZE, "Visible layers (count = %d)\n", count);
-    result.append(buffer);
+    colorizer.bold(result);
+    result.appendFormat("Visible layers (count = %d)\n", count);
+    colorizer.reset(result);
     for (size_t i=0 ; i<count ; i++) {
         const sp<Layer>& layer(currentLayers[i]);
-        layer->dump(result, buffer, SIZE);
+        layer->dump(result, colorizer);
     }
 
     /*
      * Dump Display state
      */
 
-    snprintf(buffer, SIZE, "Displays (%d entries)\n", mDisplays.size());
-    result.append(buffer);
+    colorizer.bold(result);
+    result.appendFormat("Displays (%d entries)\n", mDisplays.size());
+    colorizer.reset(result);
     for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
         const sp<const DisplayDevice>& hw(mDisplays[dpy]);
-        hw->dump(result, buffer, SIZE);
+        hw->dump(result);
     }
 
     /*
      * Dump SurfaceFlinger global state
      */
 
-    snprintf(buffer, SIZE, "SurfaceFlinger global state:\n");
-    result.append(buffer);
+    colorizer.bold(result);
+    result.append("SurfaceFlinger global state:\n");
+    colorizer.reset(result);
 
     HWComposer& hwc(getHwComposer());
     sp<const DisplayDevice> hw(getDefaultDisplayDevice());
     const GLExtensions& extensions(GLExtensions::getInstance());
 
-    snprintf(buffer, SIZE, "EGL implementation : %s\n",
+    colorizer.bold(result);
+    result.appendFormat("EGL implementation : %s\n",
             eglQueryStringImplementationANDROID(mEGLDisplay, EGL_VERSION));
-    result.append(buffer);
-    snprintf(buffer, SIZE, "%s\n",
+    colorizer.reset(result);
+    result.appendFormat("%s\n",
             eglQueryStringImplementationANDROID(mEGLDisplay, EGL_EXTENSIONS));
-    result.append(buffer);
 
-    snprintf(buffer, SIZE, "GLES: %s, %s, %s\n",
+    colorizer.bold(result);
+    result.appendFormat("GLES: %s, %s, %s\n",
             extensions.getVendor(),
             extensions.getRenderer(),
             extensions.getVersion());
-    result.append(buffer);
-    snprintf(buffer, SIZE, "%s\n", extensions.getExtension());
-    result.append(buffer);
+    colorizer.reset(result);
+    result.appendFormat("%s\n", extensions.getExtension());
 
     hw->undefinedRegion.dump(result, "undefinedRegion");
-    snprintf(buffer, SIZE,
-            "  orientation=%d, canDraw=%d\n",
+    result.appendFormat("  orientation=%d, canDraw=%d\n",
             hw->getOrientation(), hw->canDraw());
-    result.append(buffer);
-    snprintf(buffer, SIZE,
+    result.appendFormat(
             "  last eglSwapBuffers() time: %f us\n"
             "  last transaction time     : %f us\n"
             "  transaction-flags         : %08x\n"
@@ -2387,31 +2415,28 @@
             hwc.getDpiY(HWC_DISPLAY_PRIMARY),
             mEGLNativeVisualId,
             !mGpuToCpuSupported);
-    result.append(buffer);
 
-    snprintf(buffer, SIZE, "  eglSwapBuffers time: %f us\n",
+    result.appendFormat("  eglSwapBuffers time: %f us\n",
             inSwapBuffersDuration/1000.0);
-    result.append(buffer);
 
-    snprintf(buffer, SIZE, "  transaction time: %f us\n",
+    result.appendFormat("  transaction time: %f us\n",
             inTransactionDuration/1000.0);
-    result.append(buffer);
 
     /*
      * VSYNC state
      */
-    mEventThread->dump(result, buffer, SIZE);
+    mEventThread->dump(result);
 
     /*
      * Dump HWComposer state
      */
-    snprintf(buffer, SIZE, "h/w composer state:\n");
-    result.append(buffer);
-    snprintf(buffer, SIZE, "  h/w composer %s and %s\n",
+    colorizer.bold(result);
+    result.append("h/w composer state:\n");
+    colorizer.reset(result);
+    result.appendFormat("  h/w composer %s and %s\n",
             hwc.initCheck()==NO_ERROR ? "present" : "not present",
                     (mDebugDisableHWC || mDebugRegion) ? "disabled" : "enabled");
-    result.append(buffer);
-    hwc.dump(result, buffer, SIZE);
+    hwc.dump(result);
 
     /*
      * Dump gralloc state
@@ -2571,86 +2596,6 @@
 // Capture screen into an IGraphiBufferProducer
 // ---------------------------------------------------------------------------
 
-/* The code below is here to handle b/8734824
- *
- * We create a IGraphicBufferProducer wrapper that forwards all calls
- * to the calling binder thread, where they are executed. This allows
- * the calling thread to be reused (on the other side) and not
- * depend on having "enough" binder threads to handle the requests.
- *
- */
-
-class GraphicProducerWrapper : public BBinder, public MessageHandler {
-    sp<IGraphicBufferProducer> impl;
-    sp<Looper> looper;
-    status_t result;
-    bool exitPending;
-    bool exitRequested;
-    mutable Barrier barrier;
-    volatile int32_t memoryBarrier;
-    uint32_t code;
-    Parcel const* data;
-    Parcel* reply;
-
-    enum {
-        MSG_API_CALL,
-        MSG_EXIT
-    };
-
-    /*
-     * this is called by our "fake" BpGraphicBufferProducer. We package the
-     * data and reply Parcel and forward them to the calling thread.
-     */
-    virtual status_t transact(uint32_t code,
-            const Parcel& data, Parcel* reply, uint32_t flags) {
-        this->code = code;
-        this->data = &data;
-        this->reply = reply;
-        android_atomic_acquire_store(0, &memoryBarrier);
-        if (exitPending) {
-            // if we've exited, we run the message synchronously right here
-            handleMessage(Message(MSG_API_CALL));
-        } else {
-            barrier.close();
-            looper->sendMessage(this, Message(MSG_API_CALL));
-            barrier.wait();
-        }
-        return NO_ERROR;
-    }
-
-    /*
-     * here we run on the binder calling thread. All we've got to do is
-     * call the real BpGraphicBufferProducer.
-     */
-    virtual void handleMessage(const Message& message) {
-        android_atomic_release_load(&memoryBarrier);
-        if (message.what == MSG_API_CALL) {
-            impl->asBinder()->transact(code, data[0], reply);
-            barrier.open();
-        } else if (message.what == MSG_EXIT) {
-            exitRequested = true;
-        }
-    }
-
-public:
-    GraphicProducerWrapper(const sp<IGraphicBufferProducer>& impl) :
-        impl(impl), looper(new Looper(true)), result(NO_ERROR),
-        exitPending(false), exitRequested(false) {
-    }
-
-    status_t waitForResponse() {
-        do {
-            looper->pollOnce(-1);
-        } while (!exitRequested);
-        return result;
-    }
-
-    void exit(status_t result) {
-        exitPending = true;
-        looper->sendMessage(this, Message(MSG_EXIT));
-    }
-};
-
 status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display,
         const sp<IGraphicBufferProducer>& producer,
         uint32_t reqWidth, uint32_t reqHeight,
@@ -2663,25 +2608,24 @@
     if (CC_UNLIKELY(producer == 0))
         return BAD_VALUE;
 
-
     class MessageCaptureScreen : public MessageBase {
         SurfaceFlinger* flinger;
         sp<IBinder> display;
         sp<IGraphicBufferProducer> producer;
         uint32_t reqWidth, reqHeight;
         uint32_t minLayerZ,maxLayerZ;
-        bool useReadPixels;
+        bool isCpuConsumer;
         status_t result;
     public:
         MessageCaptureScreen(SurfaceFlinger* flinger,
                 const sp<IBinder>& display,
                 const sp<IGraphicBufferProducer>& producer,
                 uint32_t reqWidth, uint32_t reqHeight,
-                uint32_t minLayerZ, uint32_t maxLayerZ, bool useReadPixels)
+                uint32_t minLayerZ, uint32_t maxLayerZ, bool isCpuConsumer)
             : flinger(flinger), display(display), producer(producer),
               reqWidth(reqWidth), reqHeight(reqHeight),
               minLayerZ(minLayerZ), maxLayerZ(maxLayerZ),
-              useReadPixels(useReadPixels),
+              isCpuConsumer(isCpuConsumer),
               result(PERMISSION_DENIED)
         {
         }
@@ -2691,14 +2635,11 @@
         virtual bool handler() {
             Mutex::Autolock _l(flinger->mStateLock);
             sp<const DisplayDevice> hw(flinger->getDisplayDevice(display));
-            if (!useReadPixels) {
-                result = flinger->captureScreenImplLocked(hw,
-                        producer, reqWidth, reqHeight, minLayerZ, maxLayerZ);
-            } else {
-                result = flinger->captureScreenImplCpuConsumerLocked(hw,
-                        producer, reqWidth, reqHeight, minLayerZ, maxLayerZ);
-            }
-            static_cast<GraphicProducerWrapper*>(producer->asBinder().get())->exit(result);
+            bool useReadPixels = isCpuConsumer && !flinger->mGpuToCpuSupported;
+            result = flinger->captureScreenImplLocked(hw,
+                    producer, reqWidth, reqHeight, minLayerZ, maxLayerZ,
+                    useReadPixels);
+
             return true;
         }
     };
@@ -2710,40 +2651,12 @@
     // scheduled at this time, this will end-up being a no-op as well.
     mEventQueue.invalidateTransactionNow();
 
-    bool useReadPixels = false;
-    if (isCpuConsumer) {
-        bool formatSupportedBytBitmap =
-                (mEGLNativeVisualId == HAL_PIXEL_FORMAT_RGBA_8888) ||
-                (mEGLNativeVisualId == HAL_PIXEL_FORMAT_RGBX_8888);
-        if (formatSupportedBytBitmap == false) {
-            // the pixel format we have is not compatible with
-            // Bitmap.java, which is the likely client of this API,
-            // so we just revert to glReadPixels() in that case.
-            useReadPixels = true;
-        }
-        if (mGpuToCpuSupported == false) {
-            // When we know the GL->CPU path works, we can call
-            // captureScreenImplLocked() directly, instead of using the
-            // glReadPixels() workaround.
-            useReadPixels = true;
-        }
-    }
-
-    // this creates a "fake" BBinder which will serve as a "fake" remote
-    // binder to receive the marshaled calls and forward them to the
-    // real remote (a BpGraphicBufferProducer)
-    sp<GraphicProducerWrapper> wrapper = new GraphicProducerWrapper(producer);
-
-    // the asInterface() call below creates our "fake" BpGraphicBufferProducer
-    // which does the marshaling work forwards to our "fake remote" above.
     sp<MessageBase> msg = new MessageCaptureScreen(this,
-            display, IGraphicBufferProducer::asInterface( wrapper ),
-            reqWidth, reqHeight, minLayerZ, maxLayerZ,
-            useReadPixels);
-
-    status_t res = postMessageAsync(msg);
+            display, producer, reqWidth, reqHeight, minLayerZ, maxLayerZ,
+            isCpuConsumer);
+    status_t res = postMessageSync(msg);
     if (res == NO_ERROR) {
-        res = wrapper->waitForResponse();
+        res = static_cast<MessageCaptureScreen*>( msg.get() )->getResult();
     }
     return res;
 }
@@ -2807,73 +2720,8 @@
         const sp<const DisplayDevice>& hw,
         const sp<IGraphicBufferProducer>& producer,
         uint32_t reqWidth, uint32_t reqHeight,
-        uint32_t minLayerZ, uint32_t maxLayerZ)
-{
-    ATRACE_CALL();
-
-    // get screen geometry
-    const uint32_t hw_w = hw->getWidth();
-    const uint32_t hw_h = hw->getHeight();
-
-    // if we have secure windows on this display, never allow the screen capture
-    if (hw->getSecureLayerVisible()) {
-        ALOGW("FB is protected: PERMISSION_DENIED");
-        return PERMISSION_DENIED;
-    }
-
-    if ((reqWidth > hw_w) || (reqHeight > hw_h)) {
-        ALOGE("size mismatch (%d, %d) > (%d, %d)",
-                reqWidth, reqHeight, hw_w, hw_h);
-        return BAD_VALUE;
-    }
-
-    reqWidth = (!reqWidth) ? hw_w : reqWidth;
-    reqHeight = (!reqHeight) ? hw_h : reqHeight;
-
-    // Create a surface to render into
-    sp<Surface> surface = new Surface(producer);
-    ANativeWindow* const window = surface.get();
-
-    // set the buffer size to what the user requested
-    native_window_set_buffers_user_dimensions(window, reqWidth, reqHeight);
-
-    // and create the corresponding EGLSurface
-    EGLSurface eglSurface = eglCreateWindowSurface(
-            mEGLDisplay, mEGLConfig, window, NULL);
-    if (eglSurface == EGL_NO_SURFACE) {
-        ALOGE("captureScreenImplLocked: eglCreateWindowSurface() failed 0x%4x",
-                eglGetError());
-        return BAD_VALUE;
-    }
-
-    if (!eglMakeCurrent(mEGLDisplay, eglSurface, eglSurface, mEGLContext)) {
-        ALOGE("captureScreenImplLocked: eglMakeCurrent() failed 0x%4x",
-                eglGetError());
-        eglDestroySurface(mEGLDisplay, eglSurface);
-        return BAD_VALUE;
-    }
-
-    renderScreenImplLocked(hw, reqWidth, reqHeight, minLayerZ, maxLayerZ, false);
-
-    // and finishing things up...
-    if (eglSwapBuffers(mEGLDisplay, eglSurface) != EGL_TRUE) {
-        ALOGE("captureScreenImplLocked: eglSwapBuffers() failed 0x%4x",
-                eglGetError());
-        eglDestroySurface(mEGLDisplay, eglSurface);
-        return BAD_VALUE;
-    }
-
-    eglDestroySurface(mEGLDisplay, eglSurface);
-
-    return NO_ERROR;
-}
-
-
-status_t SurfaceFlinger::captureScreenImplCpuConsumerLocked(
-        const sp<const DisplayDevice>& hw,
-        const sp<IGraphicBufferProducer>& producer,
-        uint32_t reqWidth, uint32_t reqHeight,
-        uint32_t minLayerZ, uint32_t maxLayerZ)
+        uint32_t minLayerZ, uint32_t maxLayerZ,
+        bool useReadPixels)
 {
     ATRACE_CALL();
 
@@ -2900,66 +2748,102 @@
     reqWidth  = (!reqWidth)  ? hw_w : reqWidth;
     reqHeight = (!reqHeight) ? hw_h : reqHeight;
 
-    GLuint tname;
-    glGenRenderbuffersOES(1, &tname);
-    glBindRenderbufferOES(GL_RENDERBUFFER_OES, tname);
-    glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_RGBA8_OES, reqWidth, reqHeight);
-
-    // create a FBO
-    GLuint name;
-    glGenFramebuffersOES(1, &name);
-    glBindFramebufferOES(GL_FRAMEBUFFER_OES, name);
-    glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES,
-            GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, tname);
-
-    GLenum status = glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES);
+    // create a surface (because we're a producer, and we need to
+    // dequeue/queue a buffer)
+    sp<Surface> sur = new Surface(producer);
+    ANativeWindow* window = sur.get();
 
     status_t result = NO_ERROR;
-    if (status == GL_FRAMEBUFFER_COMPLETE_OES) {
-
-        renderScreenImplLocked(hw, reqWidth, reqHeight, minLayerZ, maxLayerZ, true);
-
-        // Below we render the screenshot into the
-        // CpuConsumer using glReadPixels from our FBO.
-        // Some older drivers don't support the GL->CPU path so we
-        // have to wrap it with a CPU->CPU path, which is what
-        // glReadPixels essentially is.
-
-        sp<Surface> sur = new Surface(producer);
-        ANativeWindow* window = sur.get();
-
-        if (native_window_api_connect(window, NATIVE_WINDOW_API_CPU) == NO_ERROR) {
-            int err = 0;
-            err = native_window_set_buffers_dimensions(window, reqWidth, reqHeight);
-            err |= native_window_set_buffers_format(window, HAL_PIXEL_FORMAT_RGBA_8888);
-            err |= native_window_set_usage(window,
-                    GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
-
-            if (err == NO_ERROR) {
-                ANativeWindowBuffer* buffer;
-                if (native_window_dequeue_buffer_and_wait(window,  &buffer) == NO_ERROR) {
-                    sp<GraphicBuffer> buf = static_cast<GraphicBuffer*>(buffer);
-                    void* vaddr;
-                    if (buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, &vaddr) == NO_ERROR) {
-                        glReadPixels(0, 0, buffer->stride, reqHeight,
-                                GL_RGBA, GL_UNSIGNED_BYTE, vaddr);
-                        buf->unlock();
-                    }
-                    window->queueBuffer(window, buffer, -1);
-                }
-            }
-            native_window_api_disconnect(window, NATIVE_WINDOW_API_CPU);
+    if (native_window_api_connect(window, NATIVE_WINDOW_API_EGL) == NO_ERROR) {
+        uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN;
+        if (!useReadPixels) {
+            usage = GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE;
         }
 
-    } else {
-        ALOGE("got GL_FRAMEBUFFER_COMPLETE_OES while taking screenshot");
-        result = INVALID_OPERATION;
-    }
+        int err = 0;
+        err = native_window_set_buffers_dimensions(window, reqWidth, reqHeight);
+        err |= native_window_set_buffers_format(window, HAL_PIXEL_FORMAT_RGBA_8888);
+        err |= native_window_set_usage(window, usage);
 
-    // back to main framebuffer
-    glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
-    glDeleteRenderbuffersOES(1, &tname);
-    glDeleteFramebuffersOES(1, &name);
+        if (err == NO_ERROR) {
+            ANativeWindowBuffer* buffer;
+            /* TODO: Once we have the sync framework everywhere this can use
+             * server-side waits on the fence that dequeueBuffer returns.
+             */
+            result = native_window_dequeue_buffer_and_wait(window,  &buffer);
+            if (result == NO_ERROR) {
+                // create an EGLImage from the buffer so we can later
+                // turn it into a texture
+                EGLImageKHR image = eglCreateImageKHR(mEGLDisplay, EGL_NO_CONTEXT,
+                        EGL_NATIVE_BUFFER_ANDROID, buffer, NULL);
+                if (image != EGL_NO_IMAGE_KHR) {
+                    GLuint tname, name;
+                    if (!useReadPixels) {
+                        // turn our EGLImage into a texture
+                        glGenTextures(1, &tname);
+                        glBindTexture(GL_TEXTURE_2D, tname);
+                        glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)image);
+                        // create a Framebuffer Object to render into
+                        glGenFramebuffersOES(1, &name);
+                        glBindFramebufferOES(GL_FRAMEBUFFER_OES, name);
+                        glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES,
+                                GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tname, 0);
+                    } else {
+                        // since we're going to use glReadPixels() anyways,
+                        // use an intermediate renderbuffer instead
+                        glGenRenderbuffersOES(1, &tname);
+                        glBindRenderbufferOES(GL_RENDERBUFFER_OES, tname);
+                        glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_RGBA8_OES, reqWidth, reqHeight);
+                        // create a FBO to render into
+                        glGenFramebuffersOES(1, &name);
+                        glBindFramebufferOES(GL_FRAMEBUFFER_OES, name);
+                        glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES,
+                                GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, tname);
+                    }
+
+                    GLenum status = glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES);
+                    if (status == GL_FRAMEBUFFER_COMPLETE_OES) {
+                        // this will in fact render into our dequeued buffer
+                        // via an FBO, which means we didn't have to create
+                        // an EGLSurface and therefore we're not
+                        // dependent on the context's EGLConfig.
+                        renderScreenImplLocked(hw, reqWidth, reqHeight,
+                                minLayerZ, maxLayerZ, true);
+
+                        if (useReadPixels) {
+                            sp<GraphicBuffer> buf = static_cast<GraphicBuffer*>(buffer);
+                            void* vaddr;
+                            if (buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, &vaddr) == NO_ERROR) {
+                                glReadPixels(0, 0, buffer->stride, reqHeight,
+                                        GL_RGBA, GL_UNSIGNED_BYTE, vaddr);
+                                buf->unlock();
+                            }
+                        }
+                    } else {
+                        ALOGE("got GL_FRAMEBUFFER_COMPLETE_OES error while taking screenshot");
+                        result = INVALID_OPERATION;
+                    }
+
+                    // back to main framebuffer
+                    glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
+                    glDeleteFramebuffersOES(1, &name);
+                    if (!useReadPixels) {
+                        glDeleteTextures(1, &tname);
+                    } else {
+                        glDeleteRenderbuffersOES(1, &tname);
+                    }
+                    // destroy our image
+                    eglDestroyImageKHR(mEGLDisplay, image);
+                } else {
+                    result = BAD_VALUE;
+                }
+                window->queueBuffer(window, buffer, -1);
+            }
+        } else {
+            result = BAD_VALUE;
+        }
+        native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
+    }
 
     DisplayDevice::setViewportAndProjection(hw);
 
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 739099c..089c265 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -72,6 +72,13 @@
     eTransactionMask          = 0x07
 };
 
+enum GlesVersion {
+    GLES_VERSION_1_0    = 0x10000,
+    GLES_VERSION_1_1    = 0x10001,
+    GLES_VERSION_2_0    = 0x20000,
+    GLES_VERSION_3_0    = 0x30000,
+};
+
 class SurfaceFlinger : public BinderService<SurfaceFlinger>,
                        public BnSurfaceComposer,
                        private IBinder::DeathRecipient,
@@ -79,11 +86,11 @@
                        private HWComposer::EventHandler
 {
 public:
-    static char const* getServiceName() {
+    static char const* getServiceName() ANDROID_API {
         return "SurfaceFlinger";
     }
 
-    SurfaceFlinger();
+    SurfaceFlinger() ANDROID_API;
 
     enum {
         EVENT_VSYNC = HWC_EVENT_VSYNC
@@ -121,6 +128,11 @@
     // TODO: this should be made accessible only to HWComposer
     const Vector< sp<Layer> >& getLayerSortedByZForHwcDisplay(int id);
 
+    // return the version of the OpenGL ES composition context
+    GlesVersion getGlesVersion() const {
+        return mGlesVersion;
+    }
+
 private:
     friend class Client;
     friend class DisplayEventConnection;
@@ -298,14 +310,8 @@
             const sp<const DisplayDevice>& hw,
             const sp<IGraphicBufferProducer>& producer,
             uint32_t reqWidth, uint32_t reqHeight,
-            uint32_t minLayerZ, uint32_t maxLayerZ);
-
-    status_t captureScreenImplCpuConsumerLocked(
-            const sp<const DisplayDevice>& hw,
-            const sp<IGraphicBufferProducer>& producer,
-            uint32_t reqWidth, uint32_t reqHeight,
-            uint32_t minLayerZ, uint32_t maxLayerZ);
-
+            uint32_t minLayerZ, uint32_t maxLayerZ,
+            bool useReadPixels);
 
     /* ------------------------------------------------------------------------
      * EGL
@@ -385,12 +391,13 @@
      * Debugging & dumpsys
      */
     void listLayersLocked(const Vector<String16>& args, size_t& index,
-        String8& result, char* buffer, size_t SIZE) const;
+        String8& result) const;
     void dumpStatsLocked(const Vector<String16>& args, size_t& index,
-        String8& result, char* buffer, size_t SIZE) const;
+        String8& result) const;
     void clearStatsLocked(const Vector<String16>& args, size_t& index,
-        String8& result, char* buffer, size_t SIZE);
-    void dumpAllLocked(String8& result, char* buffer, size_t SIZE) const;
+        String8& result);
+    void dumpAllLocked(const Vector<String16>& args, size_t& index,
+        String8& result) const;
     bool startDdmConnection();
     static void appendSfConfigString(String8& result);
 
@@ -426,6 +433,7 @@
     EGLConfig mEGLConfig;
     EGLDisplay mEGLDisplay;
     EGLint mEGLNativeVisualId;
+    GlesVersion mGlesVersion;
     sp<IBinder> mBuiltinDisplays[DisplayDevice::NUM_DISPLAY_TYPES];
 
     // Can only accessed from the main thread, these members
diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.cpp b/services/surfaceflinger/SurfaceFlingerConsumer.cpp
index 2869250..6912dc0 100644
--- a/services/surfaceflinger/SurfaceFlingerConsumer.cpp
+++ b/services/surfaceflinger/SurfaceFlingerConsumer.cpp
@@ -69,7 +69,7 @@
     // reject buffers which have the wrong size
     int buf = item.mBuf;
     if (rejecter && rejecter->reject(mSlots[buf].mGraphicBuffer, item)) {
-        releaseBufferLocked(buf, EGL_NO_SYNC_KHR);
+        releaseBufferLocked(buf, item.mGraphicBuffer, EGL_NO_SYNC_KHR);
         return NO_ERROR;
     }