Merge "Adjust mBiggerTouchSlopSquare to the suitable value"
diff --git a/NOTICE b/NOTICE
index 2006201..c45f010 100644
--- a/NOTICE
+++ b/NOTICE
@@ -53,6 +53,27 @@
 These files are Copyright 1998 - 2009 PacketVideo, but released under
 the Apache2 License.
 
+   =========================================================================
+   ==  NOTICE file corresponding to the section 4 d of                    ==
+   ==  the Apache License, Version 2.0,                                   ==
+   ==  in this case for Additional Codecs code.                           ==
+   =========================================================================
+
+Additional Codecs
+These files are Copyright 2003-2010 VisualOn, but released under
+the Apache2 License.
+
+  =========================================================================
+  ==  NOTICE file corresponding to the section 4 d of                    ==
+  ==  the Apache License, Version 2.0,                                   ==
+  ==  in this case for the Audio Effects code.                           ==
+  =========================================================================
+
+Audio Effects
+These files are Copyright (C) 2004-2010 NXP Software and
+Copyright (C) 2010 The Android Open Source Project, but released under
+the Apache2 License.
+
                                Apache License
                            Version 2.0, January 2004
                         http://www.apache.org/licenses/
diff --git a/include/gui/SurfaceTexture.h b/include/gui/SurfaceTexture.h
new file mode 100644
index 0000000..255afdd
--- /dev/null
+++ b/include/gui/SurfaceTexture.h
@@ -0,0 +1,41 @@
+/*
+ * 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_GUI_SURFACETEXTURE_H
+#define ANDROID_GUI_SURFACETEXTURE_H
+
+namespace android {
+
+struct SurfaceTexture {
+    struct FrameAvailableListener : public virtual RefBase {};
+
+    SurfaceTexture(GLuint) {}
+    void updateTexImage() {}
+    void decStrong(android::sp<android::SurfaceTexture>* const) {}
+    void incStrong(android::sp<android::SurfaceTexture>* const) {}
+    void getTransformMatrix(float mtx[16]) {}
+    void setFrameAvailableListener(const sp<FrameAvailableListener>&) {}
+};
+
+static sp<SurfaceTexture> SurfaceTexture_getSurfaceTexture(JNIEnv* env, jobject thiz)
+{
+    sp<SurfaceTexture> s;
+    return s;
+}
+
+}
+
+#endif
diff --git a/include/gui/SurfaceTextureClient.h b/include/gui/SurfaceTextureClient.h
new file mode 100644
index 0000000..a83756e
--- /dev/null
+++ b/include/gui/SurfaceTextureClient.h
@@ -0,0 +1,30 @@
+/*
+ * 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_GUI_SURFACETEXTURECLIENT_H
+#define ANDROID_GUI_SURFACETEXTURECLIENT_H
+
+#include <ui/egl/android_natives.h>
+
+namespace android {
+
+struct SurfaceTextureClient : public ANativeWindow {
+    SurfaceTextureClient(const sp<SurfaceTexture>&){}
+};
+
+}
+
+#endif
diff --git a/include/private/surfaceflinger/SharedBufferStack.h b/include/private/surfaceflinger/SharedBufferStack.h
index d6ae5e9..4ae3cdf 100644
--- a/include/private/surfaceflinger/SharedBufferStack.h
+++ b/include/private/surfaceflinger/SharedBufferStack.h
@@ -105,7 +105,7 @@
     volatile int32_t head;      // server's current front buffer
     volatile int32_t available; // number of dequeue-able buffers
     volatile int32_t queued;    // number of buffers waiting for post
-    volatile int32_t inUse;     // buffer currently in use by SF
+    volatile int32_t reserved1;
     volatile status_t status;   // surface's status code
 
     // not part of the conditions
@@ -275,7 +275,6 @@
             int32_t identity);
 
     ssize_t retireAndLock();
-    status_t unlock(int buffer);
     void setStatus(status_t status);
     status_t reallocateAll();
     status_t reallocateAllExcept(int buffer);
@@ -346,11 +345,6 @@
     int mNumBuffers;
     BufferList mBufferList;
 
-    struct UnlockUpdate : public UpdateBase {
-        const int lockedBuffer;
-        inline UnlockUpdate(SharedBufferBase* sbb, int lockedBuffer);
-        inline ssize_t operator()();
-    };
 
     struct RetireUpdate : public UpdateBase {
         const int numBuffers;
diff --git a/include/surfaceflinger/Surface.h b/include/surfaceflinger/Surface.h
index 22684db..7b2a7f5 100644
--- a/include/surfaceflinger/Surface.h
+++ b/include/surfaceflinger/Surface.h
@@ -248,7 +248,7 @@
             uint32_t *pWidth, uint32_t *pHeight,
             uint32_t *pFormat, uint32_t *pUsage) const;
 
-    static void cleanCachedSurfaces();
+    static void cleanCachedSurfacesLocked();
 
     class BufferInfo {
         uint32_t mWidth;
diff --git a/include/ui/GraphicBuffer.h b/include/ui/GraphicBuffer.h
index a3e85a9..0be26a7 100644
--- a/include/ui/GraphicBuffer.h
+++ b/include/ui/GraphicBuffer.h
@@ -26,6 +26,8 @@
 #include <utils/Flattenable.h>
 #include <pixelflinger/pixelflinger.h>
 
+#include <hardware/hardware.h>
+
 struct android_native_buffer_t;
 
 namespace android {
@@ -63,6 +65,13 @@
         USAGE_HW_MASK           = GRALLOC_USAGE_HW_MASK
     };
 
+    enum {
+        TRANSFORM_IDENTITY      = 0,
+        TRANSFORM_ROT_90        = HAL_TRANSFORM_ROT_90,
+        TRANSFORM_ROT_180       = HAL_TRANSFORM_ROT_180,
+        TRANSFORM_ROT_270       = HAL_TRANSFORM_ROT_270
+    };
+
     GraphicBuffer();
 
     // creates w * h buffer
@@ -79,6 +88,7 @@
     uint32_t getHeight() const          { return height; }
     uint32_t getStride() const          { return stride; }
     uint32_t getUsage() const           { return usage; }
+    uint32_t getTransform() const       { return transform; }
     PixelFormat getPixelFormat() const  { return format; }
     Rect getBounds() const              { return Rect(width, height); }
     
@@ -88,12 +98,15 @@
     status_t lock(uint32_t usage, const Rect& rect, void** vaddr);
     status_t lock(GGLSurface* surface, uint32_t usage);
     status_t unlock();
-    
+
     android_native_buffer_t* getNativeBuffer() const;
     
     void setIndex(int index);
     int getIndex() const;
 
+    // for debugging
+    static void dumpAllocationsToSystemLog();
+
 private:
     virtual ~GraphicBuffer();
 
diff --git a/include/ui/GraphicBufferAllocator.h b/include/ui/GraphicBufferAllocator.h
index 54b8236..dffa788 100644
--- a/include/ui/GraphicBufferAllocator.h
+++ b/include/ui/GraphicBufferAllocator.h
@@ -68,6 +68,7 @@
     status_t free(buffer_handle_t handle);
 
     void dump(String8& res) const;
+    static void dumpToSystemLog();
 
 private:
     struct alloc_rec_t {
diff --git a/include/ui/Input.h b/include/ui/Input.h
index 8c6018b..4e809d6 100644
--- a/include/ui/Input.h
+++ b/include/ui/Input.h
@@ -38,6 +38,15 @@
     AKEY_EVENT_FLAG_START_TRACKING = 0x40000000
 };
 
+enum {
+    /*
+     * Indicates that an input device has switches.
+     * This input source flag is hidden from the API because switches are only used by the system
+     * and applications have no way to interact with them.
+     */
+    AINPUT_SOURCE_SWITCH = 0x80000000,
+};
+
 /*
  * Maximum number of pointers supported per motion event.
  * Smallest number of pointers is 1.
diff --git a/include/ui/InputReader.h b/include/ui/InputReader.h
index 49351b0..7568ba7 100644
--- a/include/ui/InputReader.h
+++ b/include/ui/InputReader.h
@@ -103,6 +103,12 @@
      */
     virtual bool filterJumpyTouchEvents() = 0;
 
+    /* Gets the amount of time to disable virtual keys after the screen is touched
+     * in order to filter out accidental virtual key presses due to swiping gestures
+     * or taps near the edge of the display.  May be 0 to disable the feature.
+     */
+    virtual nsecs_t getVirtualKeyQuietTime() = 0;
+
     /* Gets the configured virtual key definitions for an input device. */
     virtual void getVirtualKeyDefinitions(const String8& deviceName,
             Vector<VirtualKeyDefinition>& outVirtualKeyDefinitions) = 0;
@@ -177,6 +183,10 @@
     virtual void updateGlobalMetaState() = 0;
     virtual int32_t getGlobalMetaState() = 0;
 
+    virtual void disableVirtualKeysUntil(nsecs_t time) = 0;
+    virtual bool shouldDropVirtualKey(nsecs_t now,
+            InputDevice* device, int32_t keyCode, int32_t scanCode) = 0;
+
     virtual InputReaderPolicyInterface* getPolicy() = 0;
     virtual InputDispatcherInterface* getDispatcher() = 0;
     virtual EventHubInterface* getEventHub() = 0;
@@ -264,6 +274,11 @@
     InputConfiguration mInputConfiguration;
     void updateInputConfiguration();
 
+    nsecs_t mDisableVirtualKeysTimeout;
+    virtual void disableVirtualKeysUntil(nsecs_t time);
+    virtual bool shouldDropVirtualKey(nsecs_t now,
+            InputDevice* device, int32_t keyCode, int32_t scanCode);
+
     // state queries
     typedef int32_t (InputDevice::*GetStateFunc)(uint32_t sourceMask, int32_t code);
     int32_t getState(int32_t deviceId, uint32_t sourceMask, int32_t code,
@@ -585,6 +600,7 @@
         bool useBadTouchFilter;
         bool useJumpyTouchFilter;
         bool useAveragingTouchFilter;
+        nsecs_t virtualKeyQuietTime;
     } mParameters;
 
     // Immutable calibration parameters in parsed form.
@@ -810,6 +826,7 @@
     void dispatchTouch(nsecs_t when, uint32_t policyFlags, TouchData* touch,
             BitSet32 idBits, uint32_t changedId, uint32_t pointerCount,
             int32_t motionEventAction);
+    void detectGestures(nsecs_t when);
 
     bool isPointInsideSurfaceLocked(int32_t x, int32_t y);
     const VirtualKey* findVirtualKeyHitLocked(int32_t x, int32_t y);
diff --git a/include/ui/android_native_buffer.h b/include/ui/android_native_buffer.h
index 402843e..a472824 100644
--- a/include/ui/android_native_buffer.h
+++ b/include/ui/android_native_buffer.h
@@ -51,8 +51,12 @@
     int stride;
     int format;
     int usage;
-    
-    void* reserved[2];
+
+    /* transformation as defined in hardware.h */
+    uint8_t transform;
+
+    uint8_t reserved_bytes[3];
+    void* reserved[1];
 
     buffer_handle_t handle;
 
diff --git a/include/utils/AssetManager.h b/include/utils/AssetManager.h
index 9e2bf37..a8c7ddb 100644
--- a/include/utils/AssetManager.h
+++ b/include/utils/AssetManager.h
@@ -222,6 +222,7 @@
     {
         String8 path;
         FileType type;
+        String8 idmap;
     };
 
     Asset* openInPathLocked(const char* fileName, AccessMode mode,
@@ -262,6 +263,16 @@
     void setLocaleLocked(const char* locale);
     void updateResourceParamsLocked() const;
 
+    bool createIdmapFileLocked(const String8& originalPath, const String8& overlayPath,
+                               const String8& idmapPath);
+
+    bool isIdmapStaleLocked(const String8& originalPath, const String8& overlayPath,
+                            const String8& idmapPath);
+
+    Asset* openIdmapLocked(const struct asset_path& ap) const;
+
+    bool getZipEntryCrcLocked(const String8& zipPath, const char* entryFilename, uint32_t* pCrc);
+
     class SharedZip : public RefBase {
     public:
         static sp<SharedZip> get(const String8& path);
diff --git a/include/utils/Functor.h b/include/utils/Functor.h
new file mode 100644
index 0000000..56a7557
--- /dev/null
+++ b/include/utils/Functor.h
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_FUNCTOR_H
+#define ANDROID_FUNCTOR_H
+
+namespace  android {
+
+struct Functor{};
+
+}
+
+#endif
+
diff --git a/include/utils/RefBase.h b/include/utils/RefBase.h
index 9c64ac0..c24c0db 100644
--- a/include/utils/RefBase.h
+++ b/include/utils/RefBase.h
@@ -31,13 +31,10 @@
 
 // ---------------------------------------------------------------------------
 
-#define COMPARE(_op_)                                           \
+#define COMPARE_WEAK(_op_)                                      \
 inline bool operator _op_ (const sp<T>& o) const {              \
     return m_ptr _op_ o.m_ptr;                                  \
 }                                                               \
-inline bool operator _op_ (const wp<T>& o) const {              \
-    return m_ptr _op_ o.m_ptr;                                  \
-}                                                               \
 inline bool operator _op_ (const T* o) const {                  \
     return m_ptr _op_ o;                                        \
 }                                                               \
@@ -46,12 +43,18 @@
     return m_ptr _op_ o.m_ptr;                                  \
 }                                                               \
 template<typename U>                                            \
-inline bool operator _op_ (const wp<U>& o) const {              \
+inline bool operator _op_ (const U* o) const {                  \
+    return m_ptr _op_ o;                                        \
+}
+
+#define COMPARE(_op_)                                           \
+COMPARE_WEAK(_op_)                                              \
+inline bool operator _op_ (const wp<T>& o) const {              \
     return m_ptr _op_ o.m_ptr;                                  \
 }                                                               \
 template<typename U>                                            \
-inline bool operator _op_ (const U* o) const {                  \
-    return m_ptr _op_ o;                                        \
+inline bool operator _op_ (const wp<U>& o) const {              \
+    return m_ptr _op_ o.m_ptr;                                  \
 }
 
 // ---------------------------------------------------------------------------
@@ -274,13 +277,43 @@
     inline  T* unsafe_get() const { return m_ptr; }
 
     // Operators
-        
-    COMPARE(==)
-    COMPARE(!=)
-    COMPARE(>)
-    COMPARE(<)
-    COMPARE(<=)
-    COMPARE(>=)
+
+    COMPARE_WEAK(==)
+    COMPARE_WEAK(!=)
+    COMPARE_WEAK(>)
+    COMPARE_WEAK(<)
+    COMPARE_WEAK(<=)
+    COMPARE_WEAK(>=)
+
+    inline bool operator == (const wp<T>& o) const {
+        return (m_ptr == o.m_ptr) && (m_refs == o.m_refs);
+    }
+    template<typename U>
+    inline bool operator == (const wp<U>& o) const {
+        return m_ptr == o.m_ptr;
+    }
+
+    inline bool operator > (const wp<T>& o) const {
+        return (m_ptr == o.m_ptr) ? (m_refs > o.m_refs) : (m_ptr > o.m_ptr);
+    }
+    template<typename U>
+    inline bool operator > (const wp<U>& o) const {
+        return (m_ptr == o.m_ptr) ? (m_refs > o.m_refs) : (m_ptr > o.m_ptr);
+    }
+
+    inline bool operator < (const wp<T>& o) const {
+        return (m_ptr == o.m_ptr) ? (m_refs < o.m_refs) : (m_ptr < o.m_ptr);
+    }
+    template<typename U>
+    inline bool operator < (const wp<U>& o) const {
+        return (m_ptr == o.m_ptr) ? (m_refs < o.m_refs) : (m_ptr < o.m_ptr);
+    }
+                         inline bool operator != (const wp<T>& o) const { return m_refs != o.m_refs; }
+    template<typename U> inline bool operator != (const wp<U>& o) const { return !operator == (o); }
+                         inline bool operator <= (const wp<T>& o) const { return !operator > (o); }
+    template<typename U> inline bool operator <= (const wp<U>& o) const { return !operator > (o); }
+                         inline bool operator >= (const wp<T>& o) const { return !operator < (o); }
+    template<typename U> inline bool operator >= (const wp<U>& o) const { return !operator < (o); }
 
 private:
     template<typename Y> friend class sp;
@@ -294,6 +327,7 @@
 TextOutput& operator<<(TextOutput& to, const wp<T>& val);
 
 #undef COMPARE
+#undef COMPARE_WEAK
 
 // ---------------------------------------------------------------------------
 // No user serviceable parts below here.
diff --git a/include/utils/ResourceTypes.h b/include/utils/ResourceTypes.h
index da86da4..10baa11 100644
--- a/include/utils/ResourceTypes.h
+++ b/include/utils/ResourceTypes.h
@@ -1735,9 +1735,9 @@
     ~ResTable();
 
     status_t add(const void* data, size_t size, void* cookie,
-                 bool copyData=false);
+                 bool copyData=false, const void* idmap = NULL);
     status_t add(Asset* asset, void* cookie,
-                 bool copyData=false);
+                 bool copyData=false, const void* idmap = NULL);
     status_t add(ResTable* src);
 
     status_t getError() const;
@@ -1981,8 +1981,27 @@
 
     void getLocales(Vector<String8>* locales) const;
 
+    // Generate an idmap.
+    //
+    // Return value: on success: NO_ERROR; caller is responsible for free-ing
+    // outData (using free(3)). On failure, any status_t value other than
+    // NO_ERROR; the caller should not free outData.
+    status_t createIdmap(const ResTable& overlay, uint32_t originalCrc, uint32_t overlayCrc,
+                         void** outData, size_t* outSize) const;
+
+    enum {
+        IDMAP_HEADER_SIZE_BYTES = 3 * sizeof(uint32_t),
+    };
+    // Retrieve idmap meta-data.
+    //
+    // This function only requires the idmap header (the first
+    // IDMAP_HEADER_SIZE_BYTES) bytes of an idmap file.
+    static bool getIdmapInfo(const void* idmap, size_t size,
+                             uint32_t* pOriginalCrc, uint32_t* pOverlayCrc);
+
 #ifndef HAVE_ANDROID_OS
     void print(bool inclValues) const;
+    static String8 normalizeForOutput(const char* input);
 #endif
 
 private:
@@ -1993,7 +2012,7 @@
     struct bag_set;
 
     status_t add(const void* data, size_t size, void* cookie,
-                 Asset* asset, bool copyData);
+                 Asset* asset, bool copyData, const Asset* idmap);
 
     ssize_t getResourcePackageIndex(uint32_t resID) const;
     ssize_t getEntry(
@@ -2002,7 +2021,7 @@
         const ResTable_type** outType, const ResTable_entry** outEntry,
         const Type** outTypeClass) const;
     status_t parsePackage(
-        const ResTable_package* const pkg, const Header* const header);
+        const ResTable_package* const pkg, const Header* const header, uint32_t idmap_id);
 
     void print_value(const Package* pkg, const Res_value& value) const;
     
diff --git a/libs/surfaceflinger_client/ISurfaceComposer.cpp b/libs/surfaceflinger_client/ISurfaceComposer.cpp
index 969ee79..a2a5455 100644
--- a/libs/surfaceflinger_client/ISurfaceComposer.cpp
+++ b/libs/surfaceflinger_client/ISurfaceComposer.cpp
@@ -247,13 +247,13 @@
             int32_t mode = data.readInt32();
             status_t res = turnElectronBeamOff(mode);
             reply->writeInt32(res);
-        }
+        } break;
         case TURN_ELECTRON_BEAM_ON: {
             CHECK_INTERFACE(ISurfaceComposer, data, reply);
             int32_t mode = data.readInt32();
             status_t res = turnElectronBeamOn(mode);
             reply->writeInt32(res);
-        }
+        } break;
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/libs/surfaceflinger_client/SharedBufferStack.cpp b/libs/surfaceflinger_client/SharedBufferStack.cpp
index 4bc5d9e..b45e43f 100644
--- a/libs/surfaceflinger_client/SharedBufferStack.cpp
+++ b/libs/surfaceflinger_client/SharedBufferStack.cpp
@@ -58,7 +58,6 @@
 
 void SharedBufferStack::init(int32_t i)
 {
-    inUse = -2;
     status = NO_ERROR;
     identity = i;
 }
@@ -199,9 +198,9 @@
     SharedBufferStack& stack( *mSharedStack );
     snprintf(buffer, SIZE, 
             "%s[ head=%2d, available=%2d, queued=%2d ] "
-            "reallocMask=%08x, inUse=%2d, identity=%d, status=%d",
+            "reallocMask=%08x, identity=%d, status=%d",
             prefix, stack.head, stack.available, stack.queued,
-            stack.reallocMask, stack.inUse, stack.identity, stack.status);
+            stack.reallocMask, stack.identity, stack.status);
     result.append(buffer);
     result.append("\n");
     return result;
@@ -261,8 +260,7 @@
     // NOTE: if stack.head is messed up, we could crash the client
     // or cause some drawing artifacts. This is okay, as long as it is
     // limited to the client.
-    return (buf != stack.index[stack.head] ||
-            (stack.queued > 0 && stack.inUse != buf));
+    return (buf != stack.index[stack.head]);
 }
 
 // ----------------------------------------------------------------------------
@@ -295,22 +293,6 @@
     return NO_ERROR;
 }
 
-SharedBufferServer::UnlockUpdate::UnlockUpdate(
-        SharedBufferBase* sbb, int lockedBuffer)
-    : UpdateBase(sbb), lockedBuffer(lockedBuffer) {
-}
-ssize_t SharedBufferServer::UnlockUpdate::operator()() {
-    if (stack.inUse != lockedBuffer) {
-        LOGE("unlocking %d, but currently locked buffer is %d "
-             "(identity=%d, token=%d)",
-                lockedBuffer, stack.inUse,
-                stack.identity, stack.token);
-        return BAD_VALUE;
-    }
-    android_atomic_write(-1, &stack.inUse);
-    return NO_ERROR;
-}
-
 SharedBufferServer::RetireUpdate::RetireUpdate(
         SharedBufferBase* sbb, int numBuffers)
     : UpdateBase(sbb), numBuffers(numBuffers) {
@@ -320,9 +302,6 @@
     if (uint32_t(head) >= SharedBufferStack::NUM_BUFFER_MAX)
         return BAD_VALUE;
 
-    // Preventively lock the current buffer before updating queued.
-    android_atomic_write(stack.headBuf, &stack.inUse);
-
     // Decrement the number of queued buffers 
     int32_t queued;
     do {
@@ -338,7 +317,6 @@
     head = (head + 1) % numBuffers;
     const int8_t headBuf = stack.index[head];
     stack.headBuf = headBuf;
-    android_atomic_write(headBuf, &stack.inUse);
 
     // head is only modified here, so we don't need to use cmpxchg
     android_atomic_write(head, &stack.head);
@@ -542,13 +520,6 @@
     return buf;
 }
 
-status_t SharedBufferServer::unlock(int buf)
-{
-    UnlockUpdate update(this, buf);
-    status_t err = updateCondition( update );
-    return err;
-}
-
 void SharedBufferServer::setStatus(status_t status)
 {
     if (status < NO_ERROR) {
diff --git a/libs/surfaceflinger_client/Surface.cpp b/libs/surfaceflinger_client/Surface.cpp
index 854a3c6..017e94c 100644
--- a/libs/surfaceflinger_client/Surface.cpp
+++ b/libs/surfaceflinger_client/Surface.cpp
@@ -377,7 +377,7 @@
 
 
 Mutex Surface::sCachedSurfacesLock;
-DefaultKeyedVector<wp<IBinder>, wp<Surface> > Surface::sCachedSurfaces(wp<Surface>(0));
+DefaultKeyedVector<wp<IBinder>, wp<Surface> > Surface::sCachedSurfaces;
 
 sp<Surface> Surface::readFromParcel(const Parcel& data) {
     Mutex::Autolock _l(sCachedSurfacesLock);
@@ -390,13 +390,13 @@
     if (surface->mSurface == 0) {
       surface = 0;
     }
-    cleanCachedSurfaces();
+    cleanCachedSurfacesLocked();
     return surface;
 }
 
 // Remove the stale entries from the surface cache.  This should only be called
 // with sCachedSurfacesLock held.
-void Surface::cleanCachedSurfaces() {
+void Surface::cleanCachedSurfacesLocked() {
     for (int i = sCachedSurfaces.size()-1; i >= 0; --i) {
         wp<Surface> s(sCachedSurfaces.valueAt(i));
         if (s == 0 || s.promote() == 0) {
diff --git a/libs/ui/EGLUtils.cpp b/libs/ui/EGLUtils.cpp
index 1663313..f24a71d 100644
--- a/libs/ui/EGLUtils.cpp
+++ b/libs/ui/EGLUtils.cpp
@@ -66,12 +66,6 @@
     if (outConfig == NULL)
         return BAD_VALUE;
     
-    int err;
-    PixelFormatInfo fbFormatInfo;
-    if ((err = getPixelFormatInfo(PixelFormat(format), &fbFormatInfo)) < 0) {
-        return err;
-    }
-
     // Get all the "potential match" configs...
     if (eglGetConfigs(dpy, NULL, 0, &numConfigs) == EGL_FALSE)
         return BAD_VALUE;
@@ -81,23 +75,14 @@
         free(configs);
         return BAD_VALUE;
     }
-
-    const int fbSzA = fbFormatInfo.getSize(PixelFormatInfo::INDEX_ALPHA);
-    const int fbSzR = fbFormatInfo.getSize(PixelFormatInfo::INDEX_RED);
-    const int fbSzG = fbFormatInfo.getSize(PixelFormatInfo::INDEX_GREEN);
-    const int fbSzB = fbFormatInfo.getSize(PixelFormatInfo::INDEX_BLUE); 
     
     int i;
     EGLConfig config = NULL;
     for (i=0 ; i<n ; i++) {
-        EGLint r,g,b,a;
-        EGLConfig curr = configs[i];
-        eglGetConfigAttrib(dpy, curr, EGL_RED_SIZE,   &r);
-        eglGetConfigAttrib(dpy, curr, EGL_GREEN_SIZE, &g);
-        eglGetConfigAttrib(dpy, curr, EGL_BLUE_SIZE,  &b);
-        eglGetConfigAttrib(dpy, curr, EGL_ALPHA_SIZE, &a);
-        if (fbSzA == a && fbSzR == r && fbSzG == g && fbSzB  == b) {
-            config = curr;
+        EGLint nativeVisualId = 0;
+        eglGetConfigAttrib(dpy, configs[i], EGL_NATIVE_VISUAL_ID, &nativeVisualId);
+        if (nativeVisualId>0 && format == nativeVisualId) {
+            config = configs[i];
             break;
         }
     }
diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index 519c277..3671954 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -45,6 +45,7 @@
     stride = 
     format = 
     usage  = 0;
+    transform = 0;
     handle = NULL;
 }
 
@@ -57,7 +58,8 @@
     height = 
     stride = 
     format = 
-    usage  = 0;
+    usage  =
+    transform = 0;
     handle = NULL;
     mInitCheck = initSize(w, h, reqFormat, reqUsage);
 }
@@ -74,6 +76,7 @@
     stride = inStride;
     format = inFormat;
     usage  = inUsage;
+    transform = 0;
     handle = inHandle;
 }
 
@@ -99,6 +102,11 @@
     return mInitCheck;
 }
 
+void GraphicBuffer::dumpAllocationsToSystemLog()
+{
+    GraphicBufferAllocator::dumpToSystemLog();
+}
+
 android_native_buffer_t* GraphicBuffer::getNativeBuffer() const
 {
     return static_cast<android_native_buffer_t*>(
@@ -177,8 +185,10 @@
     return res;
 }
 
+const int kFlattenFdsOffset = 9;
+
 size_t GraphicBuffer::getFlattenedSize() const {
-    return (8 + (handle ? handle->numInts : 0))*sizeof(int);
+    return (kFlattenFdsOffset + (handle ? handle->numInts : 0))*sizeof(int);
 }
 
 size_t GraphicBuffer::getFdCount() const {
@@ -203,13 +213,14 @@
     buf[5] = usage;
     buf[6] = 0;
     buf[7] = 0;
+    buf[8] = transform;
 
     if (handle) {
         buf[6] = handle->numFds;
         buf[7] = handle->numInts;
         native_handle_t const* const h = handle;
         memcpy(fds,     h->data,             h->numFds*sizeof(int));
-        memcpy(&buf[8], h->data + h->numFds, h->numInts*sizeof(int));
+        memcpy(&buf[kFlattenFdsOffset], h->data + h->numFds, h->numInts*sizeof(int));
     }
 
     return NO_ERROR;
@@ -218,7 +229,7 @@
 status_t GraphicBuffer::unflatten(void const* buffer, size_t size,
         int fds[], size_t count)
 {
-    if (size < 8*sizeof(int)) return NO_MEMORY;
+    if (size < kFlattenFdsOffset*sizeof(int)) return NO_MEMORY;
 
     int const* buf = static_cast<int const*>(buffer);
     if (buf[0] != 'GBFR') return BAD_TYPE;
@@ -226,7 +237,7 @@
     const size_t numFds  = buf[6];
     const size_t numInts = buf[7];
 
-    const size_t sizeNeeded = (8 + numInts) * sizeof(int);
+    const size_t sizeNeeded = (kFlattenFdsOffset + numInts) * sizeof(int);
     if (size < sizeNeeded) return NO_MEMORY;
 
     size_t fdCountNeeded = 0;
@@ -243,9 +254,10 @@
         stride = buf[3];
         format = buf[4];
         usage  = buf[5];
+        transform = buf[8];
         native_handle* h = native_handle_create(numFds, numInts);
         memcpy(h->data,          fds,     numFds*sizeof(int));
-        memcpy(h->data + numFds, &buf[8], numInts*sizeof(int));
+        memcpy(h->data + numFds, &buf[kFlattenFdsOffset], numInts*sizeof(int));
         handle = h;
     } else {
         width = height = stride = format = usage = 0;
diff --git a/libs/ui/GraphicBufferAllocator.cpp b/libs/ui/GraphicBufferAllocator.cpp
index d51664d..fa46ab7 100644
--- a/libs/ui/GraphicBufferAllocator.cpp
+++ b/libs/ui/GraphicBufferAllocator.cpp
@@ -73,6 +73,13 @@
     result.append(buffer);
 }
 
+void GraphicBufferAllocator::dumpToSystemLog()
+{
+    String8 s;
+    GraphicBufferAllocator::getInstance().dump(s);
+    LOGD("%s", s.string());
+}
+
 status_t GraphicBufferAllocator::alloc(uint32_t w, uint32_t h, PixelFormat format,
         int usage, buffer_handle_t* handle, int32_t* stride)
 {
@@ -104,10 +111,6 @@
         rec.usage = usage;
         rec.size = h * stride[0] * bytesPerPixel(format);
         list.add(*handle, rec);
-    } else {
-        String8 s;
-        dump(s);
-        LOGD("%s", s.string());
     }
 
     return err;
diff --git a/libs/ui/InputDispatcher.cpp b/libs/ui/InputDispatcher.cpp
index 28ccc43..c0872e5 100644
--- a/libs/ui/InputDispatcher.cpp
+++ b/libs/ui/InputDispatcher.cpp
@@ -37,7 +37,9 @@
 // Log debug messages about the app switch latency optimization.
 #define DEBUG_APP_SWITCH 0
 
+#include <android/input.h>
 #include <cutils/log.h>
+#include <ui/Input.h>
 #include <ui/InputDispatcher.h>
 #include <ui/PowerManager.h>
 
@@ -592,10 +594,6 @@
     // mKeyRepeatState.lastKeyEntry in addition to the one we return.
     entry->refCount += 1;
 
-    if (entry->repeatCount == 1) {
-        entry->flags |= AKEY_EVENT_FLAG_LONG_PRESS;
-    }
-
     mKeyRepeatState.nextRepeatTime = currentTime + keyRepeatDelay;
     return entry;
 }
@@ -645,6 +643,12 @@
             resetKeyRepeatLocked();
         }
 
+        if (entry->repeatCount == 1) {
+            entry->flags |= AKEY_EVENT_FLAG_LONG_PRESS;
+        } else {
+            entry->flags &= ~AKEY_EVENT_FLAG_LONG_PRESS;
+        }
+
         entry->dispatchInProgress = true;
         resetTargetsLocked();
 
@@ -1405,8 +1409,13 @@
 
 void InputDispatcher::pokeUserActivityLocked(const EventEntry* eventEntry) {
     int32_t eventType = POWER_MANAGER_BUTTON_EVENT;
-    if (eventEntry->type == EventEntry::TYPE_MOTION) {
+    switch (eventEntry->type) {
+    case EventEntry::TYPE_MOTION: {
         const MotionEntry* motionEntry = static_cast<const MotionEntry*>(eventEntry);
+        if (motionEntry->action == AMOTION_EVENT_ACTION_CANCEL) {
+            return;
+        }
+
         if (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) {
             switch (motionEntry->action) {
             case AMOTION_EVENT_ACTION_DOWN:
@@ -1424,6 +1433,15 @@
                 break;
             }
         }
+        break;
+    }
+    case EventEntry::TYPE_KEY: {
+        const KeyEntry* keyEntry = static_cast<const KeyEntry*>(eventEntry);
+        if (keyEntry->flags & AKEY_EVENT_FLAG_CANCELED) {
+            return;
+        }
+        break;
+    }
     }
 
     CommandEntry* commandEntry = postCommandLocked(
@@ -2078,6 +2096,26 @@
         return;
     }
 
+    /* According to http://source.android.com/porting/keymaps_keyboard_input.html
+     * Key definitions: Key definitions follow the syntax key SCANCODE KEYCODE [FLAGS...],
+     * where SCANCODE is a number, KEYCODE is defined in your specific keylayout file
+     * (android.keylayout.xxx), and potential FLAGS are defined as follows:
+     *     SHIFT: While pressed, the shift key modifier is set
+     *     ALT: While pressed, the alt key modifier is set
+     *     CAPS: While pressed, the caps lock key modifier is set
+     *     Since KeyEvent.java doesn't check if Cap lock is ON and we don't have a
+     *     modifer state for cap lock, we will not support it.
+     */
+    if (policyFlags & POLICY_FLAG_ALT) {
+        metaState |= AMETA_ALT_ON | AMETA_ALT_LEFT_ON;
+    }
+    if (policyFlags & POLICY_FLAG_ALT_GR) {
+        metaState |= AMETA_ALT_ON | AMETA_ALT_RIGHT_ON;
+    }
+    if (policyFlags & POLICY_FLAG_SHIFT) {
+        metaState |= AMETA_SHIFT_ON | AMETA_SHIFT_LEFT_ON;
+    }
+
     policyFlags |= POLICY_FLAG_TRUSTED;
     mPolicy->interceptKeyBeforeQueueing(eventTime, deviceId, action, /*byref*/ flags,
             keyCode, scanCode, /*byref*/ policyFlags);
diff --git a/libs/ui/InputReader.cpp b/libs/ui/InputReader.cpp
index 3197ab2..336d489 100644
--- a/libs/ui/InputReader.cpp
+++ b/libs/ui/InputReader.cpp
@@ -198,7 +198,7 @@
         const sp<InputReaderPolicyInterface>& policy,
         const sp<InputDispatcherInterface>& dispatcher) :
         mEventHub(eventHub), mPolicy(policy), mDispatcher(dispatcher),
-        mGlobalMetaState(0) {
+        mGlobalMetaState(0), mDisableVirtualKeysTimeout(-1) {
     configureExcludedDevices();
     updateGlobalMetaState();
     updateInputConfiguration();
@@ -453,6 +453,24 @@
     } // release state lock
 }
 
+void InputReader::disableVirtualKeysUntil(nsecs_t time) {
+    mDisableVirtualKeysTimeout = time;
+}
+
+bool InputReader::shouldDropVirtualKey(nsecs_t now,
+        InputDevice* device, int32_t keyCode, int32_t scanCode) {
+    if (now < mDisableVirtualKeysTimeout) {
+        LOGI("Dropping virtual key from device %s because virtual keys are "
+                "temporarily disabled for the next %0.3fms.  keyCode=%d, scanCode=%d",
+                device->getName().string(),
+                (mDisableVirtualKeysTimeout - now) * 0.000001,
+                keyCode, scanCode);
+        return true;
+    } else {
+        return false;
+    }
+}
+
 void InputReader::getInputConfiguration(InputConfiguration* outConfiguration) {
     { // acquire state lock
         AutoMutex _l(mStateLock);
@@ -529,9 +547,9 @@
             for (size_t i = 0; i < numDevices; i++) {
                 InputDevice* device = mDevices.valueAt(i);
                 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
-                    result = (device->*getStateFunc)(sourceMask, code);
-                    if (result >= AKEY_STATE_DOWN) {
-                        return result;
+                    int32_t state = (device->*getStateFunc)(sourceMask, code);
+                    if (state > result) {
+                        result = state;
                     }
                 }
             }
@@ -719,9 +737,9 @@
     for (size_t i = 0; i < numMappers; i++) {
         InputMapper* mapper = mMappers[i];
         if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
-            result = (mapper->*getStateFunc)(sourceMask, code);
-            if (result >= AKEY_STATE_DOWN) {
-                return result;
+            int32_t state = (mapper->*getStateFunc)(sourceMask, code);
+            if (state > result) {
+                result = state;
             }
         }
     }
@@ -806,7 +824,7 @@
 }
 
 uint32_t SwitchInputMapper::getSources() {
-    return 0;
+    return AINPUT_SOURCE_SWITCH;
 }
 
 void SwitchInputMapper::process(const RawEvent* rawEvent) {
@@ -937,6 +955,11 @@
                 keyCode = mLocked.keyDowns.itemAt(keyDownIndex).keyCode;
             } else {
                 // key down
+                if ((policyFlags & POLICY_FLAG_VIRTUAL)
+                        && mContext->shouldDropVirtualKey(when, getDevice(), keyCode, scanCode)) {
+                    return;
+                }
+
                 mLocked.keyDowns.push();
                 KeyDown& keyDown = mLocked.keyDowns.editTop();
                 keyDown.keyCode = keyCode;
@@ -1340,6 +1363,7 @@
     mParameters.useBadTouchFilter = getPolicy()->filterTouchEvents();
     mParameters.useAveragingTouchFilter = getPolicy()->filterTouchEvents();
     mParameters.useJumpyTouchFilter = getPolicy()->filterJumpyTouchEvents();
+    mParameters.virtualKeyQuietTime = getPolicy()->getVirtualKeyQuietTime();
 }
 
 void TouchInputMapper::dumpParameters(String8& dump) {
@@ -2060,6 +2084,7 @@
 
     TouchResult touchResult = consumeOffScreenTouches(when, policyFlags);
     if (touchResult == DISPATCH_TOUCH) {
+        detectGestures(when);
         dispatchTouches(when, policyFlags);
     }
 
@@ -2145,6 +2170,11 @@
                     if (mCurrentTouch.pointerCount == 1) {
                         const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y);
                         if (virtualKey) {
+                            if (mContext->shouldDropVirtualKey(when, getDevice(),
+                                    virtualKey->keyCode, virtualKey->scanCode)) {
+                                return DROP_STROKE;
+                            }
+
                             mLocked.currentVirtualKey.down = true;
                             mLocked.currentVirtualKey.downTime = when;
                             mLocked.currentVirtualKey.keyCode = virtualKey->keyCode;
@@ -2182,6 +2212,26 @@
     return touchResult;
 }
 
+void TouchInputMapper::detectGestures(nsecs_t when) {
+    // Disable all virtual key touches that happen within a short time interval of the
+    // most recent touch.  The idea is to filter out stray virtual key presses when
+    // interacting with the touch screen.
+    //
+    // Problems we're trying to solve:
+    //
+    // 1. While scrolling a list or dragging the window shade, the user swipes down into a
+    //    virtual key area that is implemented by a separate touch panel and accidentally
+    //    triggers a virtual key.
+    //
+    // 2. While typing in the on screen keyboard, the user taps slightly outside the screen
+    //    area and accidentally triggers a virtual key.  This often happens when virtual keys
+    //    are layed out below the screen near to where the on screen keyboard's space bar
+    //    is displayed.
+    if (mParameters.virtualKeyQuietTime > 0 && mCurrentTouch.pointerCount != 0) {
+        mContext->disableVirtualKeysUntil(when + mParameters.virtualKeyQuietTime);
+    }
+}
+
 void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
     uint32_t currentPointerCount = mCurrentTouch.pointerCount;
     uint32_t lastPointerCount = mLastTouch.pointerCount;
diff --git a/libs/ui/tests/InputReader_test.cpp b/libs/ui/tests/InputReader_test.cpp
index de4b05a..09d1680 100644
--- a/libs/ui/tests/InputReader_test.cpp
+++ b/libs/ui/tests/InputReader_test.cpp
@@ -131,6 +131,10 @@
         return mFilterJumpyTouchEvents;
     }
 
+    virtual nsecs_t getVirtualKeyQuietTime() {
+        return 0;
+    }
+
     virtual void getVirtualKeyDefinitions(const String8& deviceName,
             Vector<VirtualKeyDefinition>& outVirtualKeyDefinitions) {
         ssize_t index = mVirtualKeyDefinitions.indexOfKey(deviceName);
@@ -631,6 +635,14 @@
     virtual InputDispatcherInterface* getDispatcher() {
         return mDispatcher.get();
     }
+
+    virtual void disableVirtualKeysUntil(nsecs_t time) {
+    }
+
+    virtual bool shouldDropVirtualKey(nsecs_t now,
+            InputDevice* device, int32_t keyCode, int32_t scanCode) {
+        return false;
+    }
 };
 
 
@@ -1356,7 +1368,7 @@
     SwitchInputMapper* mapper = new SwitchInputMapper(mDevice);
     addMapperAndConfigure(mapper);
 
-    ASSERT_EQ(uint32_t(0), mapper->getSources());
+    ASSERT_EQ(uint32_t(AINPUT_SOURCE_SWITCH), mapper->getSources());
 }
 
 TEST_F(SwitchInputMapperTest, GetSwitchState) {
diff --git a/libs/utils/AssetManager.cpp b/libs/utils/AssetManager.cpp
index e09e755..13004cd 100644
--- a/libs/utils/AssetManager.cpp
+++ b/libs/utils/AssetManager.cpp
@@ -36,6 +36,19 @@
 #include <dirent.h>
 #include <errno.h>
 #include <assert.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#ifndef TEMP_FAILURE_RETRY
+/* Used to retry syscalls that can return EINTR. */
+#define TEMP_FAILURE_RETRY(exp) ({         \
+    typeof (exp) _rc;                      \
+    do {                                   \
+        _rc = (exp);                       \
+    } while (_rc == -1 && errno == EINTR); \
+    _rc; })
+#endif
 
 using namespace android;
 
@@ -48,6 +61,7 @@
 static const char* kAssetsRoot = "assets";
 static const char* kAppZipName = NULL; //"classes.jar";
 static const char* kSystemAssets = "framework/framework-res.apk";
+static const char* kIdmapCacheDir = "resource-cache";
 
 static const char* kExcludeExtension = ".EXCLUDE";
 
@@ -55,6 +69,35 @@
 
 static volatile int32_t gCount = 0;
 
+namespace {
+    // Transform string /a/b/c.apk to /data/resource-cache/a@b@c.apk@idmap
+    String8 idmapPathForPackagePath(const String8& pkgPath)
+    {
+        const char* root = getenv("ANDROID_DATA");
+        LOG_ALWAYS_FATAL_IF(root == NULL, "ANDROID_DATA not set");
+        String8 path(root);
+        path.appendPath(kIdmapCacheDir);
+
+        char buf[256]; // 256 chars should be enough for anyone...
+        strncpy(buf, pkgPath.string(), 255);
+        buf[255] = '\0';
+        char* filename = buf;
+        while (*filename && *filename == '/') {
+            ++filename;
+        }
+        char* p = filename;
+        while (*p) {
+            if (*p == '/') {
+                *p = '@';
+            }
+            ++p;
+        }
+        path.appendPath(filename);
+        path.append("@idmap");
+
+        return path;
+    }
+}
 
 /*
  * ===========================================================================
@@ -122,7 +165,7 @@
             return true;
         }
     }
-    
+
     LOGV("In %p Asset %s path: %s", this,
          ap.type == kFileTypeDirectory ? "dir" : "zip", ap.path.string());
 
@@ -133,9 +176,181 @@
         *cookie = (void*)mAssetPaths.size();
     }
 
+    // add overlay packages for /system/framework; apps are handled by the
+    // (Java) package manager
+    if (strncmp(path.string(), "/system/framework/", 18) == 0) {
+        // When there is an environment variable for /vendor, this
+        // should be changed to something similar to how ANDROID_ROOT
+        // and ANDROID_DATA are used in this file.
+        String8 overlayPath("/vendor/overlay/framework/");
+        overlayPath.append(path.getPathLeaf());
+        if (TEMP_FAILURE_RETRY(access(overlayPath.string(), R_OK)) == 0) {
+            asset_path oap;
+            oap.path = overlayPath;
+            oap.type = ::getFileType(overlayPath.string());
+            bool addOverlay = (oap.type == kFileTypeRegular); // only .apks supported as overlay
+            if (addOverlay) {
+                oap.idmap = idmapPathForPackagePath(overlayPath);
+
+                if (isIdmapStaleLocked(ap.path, oap.path, oap.idmap)) {
+                    addOverlay = createIdmapFileLocked(ap.path, oap.path, oap.idmap);
+                }
+            }
+            if (addOverlay) {
+                mAssetPaths.add(oap);
+            } else {
+                LOGW("failed to add overlay package %s\n", overlayPath.string());
+            }
+        }
+    }
+
     return true;
 }
 
+bool AssetManager::isIdmapStaleLocked(const String8& originalPath, const String8& overlayPath,
+                                      const String8& idmapPath)
+{
+    struct stat st;
+    if (TEMP_FAILURE_RETRY(stat(idmapPath.string(), &st)) == -1) {
+        if (errno == ENOENT) {
+            return true; // non-existing idmap is always stale
+        } else {
+            LOGW("failed to stat file %s: %s\n", idmapPath.string(), strerror(errno));
+            return false;
+        }
+    }
+    if (st.st_size < ResTable::IDMAP_HEADER_SIZE_BYTES) {
+        LOGW("file %s has unexpectedly small size=%zd\n", idmapPath.string(), (size_t)st.st_size);
+        return false;
+    }
+    int fd = TEMP_FAILURE_RETRY(::open(idmapPath.string(), O_RDONLY));
+    if (fd == -1) {
+        LOGW("failed to open file %s: %s\n", idmapPath.string(), strerror(errno));
+        return false;
+    }
+    char buf[ResTable::IDMAP_HEADER_SIZE_BYTES];
+    ssize_t bytesLeft = ResTable::IDMAP_HEADER_SIZE_BYTES;
+    for (;;) {
+        ssize_t r = TEMP_FAILURE_RETRY(read(fd, buf + ResTable::IDMAP_HEADER_SIZE_BYTES - bytesLeft,
+                                            bytesLeft));
+        if (r < 0) {
+            TEMP_FAILURE_RETRY(close(fd));
+            return false;
+        }
+        bytesLeft -= r;
+        if (bytesLeft == 0) {
+            break;
+        }
+    }
+    TEMP_FAILURE_RETRY(close(fd));
+
+    uint32_t cachedOriginalCrc, cachedOverlayCrc;
+    if (!ResTable::getIdmapInfo(buf, ResTable::IDMAP_HEADER_SIZE_BYTES,
+                                &cachedOriginalCrc, &cachedOverlayCrc)) {
+        return false;
+    }
+
+    uint32_t actualOriginalCrc, actualOverlayCrc;
+    if (!getZipEntryCrcLocked(originalPath, "resources.arsc", &actualOriginalCrc)) {
+        return false;
+    }
+    if (!getZipEntryCrcLocked(overlayPath, "resources.arsc", &actualOverlayCrc)) {
+        return false;
+    }
+    return cachedOriginalCrc != actualOriginalCrc || cachedOverlayCrc != actualOverlayCrc;
+}
+
+bool AssetManager::getZipEntryCrcLocked(const String8& zipPath, const char* entryFilename,
+                                        uint32_t* pCrc)
+{
+    asset_path ap;
+    ap.path = zipPath;
+    const ZipFileRO* zip = getZipFileLocked(ap);
+    if (zip == NULL) {
+        return false;
+    }
+    const ZipEntryRO entry = zip->findEntryByName(entryFilename);
+    if (entry == NULL) {
+        return false;
+    }
+    if (!zip->getEntryInfo(entry, NULL, NULL, NULL, NULL, NULL, (long*)pCrc)) {
+        return false;
+    }
+    return true;
+}
+
+bool AssetManager::createIdmapFileLocked(const String8& originalPath, const String8& overlayPath,
+                                         const String8& idmapPath)
+{
+    LOGD("%s: originalPath=%s overlayPath=%s idmapPath=%s\n",
+         __FUNCTION__, originalPath.string(), overlayPath.string(), idmapPath.string());
+    ResTable tables[2];
+    const String8* paths[2] = { &originalPath, &overlayPath };
+    uint32_t originalCrc, overlayCrc;
+    bool retval = false;
+    ssize_t offset = 0;
+    int fd = 0;
+    uint32_t* data = NULL;
+    size_t size;
+
+    for (int i = 0; i < 2; ++i) {
+        asset_path ap;
+        ap.type = kFileTypeRegular;
+        ap.path = *paths[i];
+        Asset* ass = openNonAssetInPathLocked("resources.arsc", Asset::ACCESS_BUFFER, ap);
+        if (ass == NULL) {
+            LOGW("failed to find resources.arsc in %s\n", ap.path.string());
+            goto error;
+        }
+        tables[i].add(ass, (void*)1, false);
+    }
+
+    if (!getZipEntryCrcLocked(originalPath, "resources.arsc", &originalCrc)) {
+        LOGW("failed to retrieve crc for resources.arsc in %s\n", originalPath.string());
+        goto error;
+    }
+    if (!getZipEntryCrcLocked(overlayPath, "resources.arsc", &overlayCrc)) {
+        LOGW("failed to retrieve crc for resources.arsc in %s\n", overlayPath.string());
+        goto error;
+    }
+
+    if (tables[0].createIdmap(tables[1], originalCrc, overlayCrc,
+                              (void**)&data, &size) != NO_ERROR) {
+        LOGW("failed to generate idmap data for file %s\n", idmapPath.string());
+        goto error;
+    }
+
+    // This should be abstracted (eg replaced by a stand-alone
+    // application like dexopt, triggered by something equivalent to
+    // installd).
+    fd = TEMP_FAILURE_RETRY(::open(idmapPath.string(), O_WRONLY | O_CREAT | O_TRUNC, 0644));
+    if (fd == -1) {
+        LOGW("failed to write idmap file %s (open: %s)\n", idmapPath.string(), strerror(errno));
+        goto error_free;
+    }
+    for (;;) {
+        ssize_t written = TEMP_FAILURE_RETRY(write(fd, data + offset, size));
+        if (written < 0) {
+            LOGW("failed to write idmap file %s (write: %s)\n", idmapPath.string(),
+                 strerror(errno));
+            goto error_close;
+        }
+        size -= (size_t)written;
+        offset += written;
+        if (size == 0) {
+            break;
+        }
+    }
+
+    retval = true;
+error_close:
+    TEMP_FAILURE_RETRY(close(fd));
+error_free:
+    free(data);
+error:
+    return retval;
+}
+
 bool AssetManager::addDefaultAssets()
 {
     const char* root = getenv("ANDROID_ROOT");
@@ -404,6 +619,7 @@
         ResTable* sharedRes = NULL;
         bool shared = true;
         const asset_path& ap = mAssetPaths.itemAt(i);
+        Asset* idmap = openIdmapLocked(ap);
         LOGV("Looking for resource asset in '%s'\n", ap.path.string());
         if (ap.type != kFileTypeDirectory) {
             if (i == 0) {
@@ -433,7 +649,7 @@
                     // can quickly copy it out for others.
                     LOGV("Creating shared resources for %s", ap.path.string());
                     sharedRes = new ResTable();
-                    sharedRes->add(ass, (void*)(i+1), false);
+                    sharedRes->add(ass, (void*)(i+1), false, idmap);
                     sharedRes = const_cast<AssetManager*>(this)->
                         mZipSet.setZipResourceTable(ap.path, sharedRes);
                 }
@@ -457,7 +673,7 @@
                 rt->add(sharedRes);
             } else {
                 LOGV("Parsing resources for %s", ap.path.string());
-                rt->add(ass, (void*)(i+1), !shared);
+                rt->add(ass, (void*)(i+1), !shared, idmap);
             }
 
             if (!shared) {
@@ -498,6 +714,21 @@
     res->setParameters(mConfig);
 }
 
+Asset* AssetManager::openIdmapLocked(const struct asset_path& ap) const
+{
+    Asset* ass = NULL;
+    if (ap.idmap.size() != 0) {
+        ass = const_cast<AssetManager*>(this)->
+            openAssetFromFileLocked(ap.idmap, Asset::ACCESS_BUFFER);
+        if (ass) {
+            LOGV("loading idmap %s\n", ap.idmap.string());
+        } else {
+            LOGW("failed to load idmap %s\n", ap.idmap.string());
+        }
+    }
+    return ass;
+}
+
 const ResTable& AssetManager::getResources(bool required) const
 {
     const ResTable* rt = getResTable(required);
diff --git a/libs/utils/README b/libs/utils/README
index 36a706d..01741e0 100644
--- a/libs/utils/README
+++ b/libs/utils/README
@@ -1,4 +1,6 @@
 Android Utility Function Library
+================================
+
 
 If you need a feature that is native to Linux but not present on other
 platforms, construct a platform-dependent implementation that shares
@@ -12,3 +14,276 @@
 layer.  The goal is to provide an optimized solution for Linux with
 reasonable implementations for other platforms.
 
+
+
+Resource overlay
+================
+
+
+Introduction
+------------
+
+Overlay packages are special .apk files which provide no code but
+additional resource values (and possibly new configurations) for
+resources in other packages. When an application requests resources,
+the system will return values from either the application's original
+package or any associated overlay package. Any redirection is completely
+transparent to the calling application.
+
+Resource values have the following precedence table, listed in
+descending precedence.
+
+ * overlay package, matching config (eg res/values-en-land)
+
+ * original package, matching config
+
+ * overlay package, no config (eg res/values)
+
+ * original package, no config
+
+During compilation, overlay packages are differentiated from regular
+packages by passing the -o flag to aapt.
+
+
+Background
+----------
+
+This section provides generic background material on resources in
+Android.
+
+
+How resources are bundled in .apk files
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Android .apk files are .zip files, usually housing .dex code,
+certificates and resources, though packages containing resources but
+no code are possible. Resources can be divided into the following
+categories; a `configuration' indicates a set of phone language, display
+density, network operator, etc.
+
+ * assets: uncompressed, raw files packaged as part of an .apk and
+           explicitly referenced by filename. These files are
+           independent of configuration.
+
+ * res/drawable: bitmap or xml graphics. Each file may have different
+                 values depending on configuration.
+
+ * res/values: integers, strings, etc. Each resource may have different
+               values depending on configuration.
+
+Resource meta information and information proper is stored in a binary
+format in a named file resources.arsc, bundled as part of the .apk.
+
+Resource IDs and lookup
+~~~~~~~~~~~~~~~~~~~~~~~
+During compilation, the aapt tool gathers application resources and
+generates a resources.arsc file. Each resource name is assigned an
+integer ID 0xppttiii (translated to a symbolic name via R.java), where
+
+ * pp: corresponds to the package namespace (details below).
+
+ * tt: corresponds to the resource type (string, int, etc). Every
+       resource of the same type within the same package has the same
+       tt value, but depending on available types, the actual numerical
+       value may be different between packages.
+
+ * iiii: sequential number, assigned in the order resources are found.
+
+Resource values are specified paired with a set of configuration
+constraints (the default being the empty set), eg res/values-sv-port
+which imposes restrictions on language (Swedish) and display orientation
+(portrait). During lookup, every constraint set is matched against the
+current configuration, and the value corresponding to the best matching
+constraint set is returned (ResourceTypes.{h,cpp}).
+
+Parsing of resources.arsc is handled by ResourceTypes.cpp; this utility
+is governed by AssetManager.cpp, which tracks loaded resources per
+process.
+
+Assets are looked up by path and filename in AssetManager.cpp. The path
+to resources in res/drawable are located by ResourceTypes.cpp and then
+handled like assets by AssetManager.cpp. Other resources are handled
+solely by ResourceTypes.cpp.
+
+Package ID as namespace
+~~~~~~~~~~~~~~~~~~~~~~~
+The pp part of a resource ID defines a namespace. Android currently
+defines two namespaces:
+
+ * 0x01: system resources (pre-installed in framework-res.apk)
+
+ * 0x7f: application resources (bundled in the application .apk)
+
+ResourceTypes.cpp supports package IDs between 0x01 and 0x7f
+(inclusive); values outside this range are invalid.
+
+Each running (Dalvik) process is assigned a unique instance of
+AssetManager, which in turn keeps a forest structure of loaded
+resource.arsc files. Normally, this forest is structured as follows,
+where mPackageMap is the internal vector employed in ResourceTypes.cpp.
+
+mPackageMap[0x00] -> system package
+mPackageMap[0x01] -> NULL
+mPackageMap[0x02] -> NULL
+...
+mPackageMap[0x7f - 2] -> NULL
+mPackageMap[0x7f - 1] -> application package
+
+
+
+The resource overlay extension
+------------------------------
+
+The resource overlay mechanism aims to (partly) shadow and extend
+existing resources with new values for defined and new configurations.
+Technically, this is achieved by adding resource-only packages (called
+overlay packages) to existing resource namespaces, like so:
+
+mPackageMap[0x00] -> system package -> system overlay package
+mPackageMap[0x01] -> NULL
+mPackageMap[0x02] -> NULL
+...
+mPackageMap[0x7f - 2] -> NULL
+mPackageMap[0x7f - 1] -> application package -> overlay 1 -> overlay 2
+
+The use of overlay resources is completely transparent to
+applications; no additional resource identifiers are introduced, only
+configuration/value pairs. Any number of overlay packages may be loaded
+at a time; overlay packages are agnostic to what they target -- both
+system and application resources are fair game.
+
+The package targeted by an overlay package is called the target or
+original package.
+
+Resource overlay operates on symbolic resources names. Hence, to
+override the string/str1 resources in a package, the overlay package
+would include a resource also named string/str1. The end user does not
+have to worry about the numeric resources IDs assigned by aapt, as this
+is resolved automatically by the system.
+
+As of this writing, the use of resource overlay has not been fully
+explored. Until it has, only OEMs are trusted to use resource overlay.
+For this reason, overlay packages must reside in /system/overlay.
+
+
+Resource ID mapping
+~~~~~~~~~~~~~~~~~~~
+Resource identifiers must be coherent within the same namespace (ie
+PackageGroup in ResourceTypes.cpp). Calling applications will refer to
+resources using the IDs defined in the original package, but there is no
+guarantee aapt has assigned the same ID to the corresponding resource in
+an overlay package. To translate between the two, a resource ID mapping
+{original ID -> overlay ID} is created during package installation
+(PackageManagerService.java) and used during resource lookup. The
+mapping is stored in /data/resource-cache, with a @idmap file name
+suffix.
+
+The idmap file format is documented in a separate section, below.
+
+
+Package management
+~~~~~~~~~~~~~~~~~~
+Packages are managed by the PackageManagerService. Addition and removal
+of packages are monitored via the inotify framework, exposed via
+android.os.FileObserver.
+
+During initialization of a Dalvik process, ActivityThread.java requests
+the process' AssetManager (by proxy, via AssetManager.java and JNI)
+to load a list of packages. This list includes overlay packages, if
+present.
+
+When a target package or a corresponding overlay package is installed,
+the target package's process is stopped and a new idmap is generated.
+This is similar to how applications are stopped when their packages are
+upgraded.
+
+
+Creating overlay packages
+-------------------------
+
+Overlay packages should contain no code, define (some) resources with
+the same type and name as in the original package, and be compiled with
+the -o flag passed to aapt.
+
+The aapt -o flag instructs aapt to create an overlay package.
+Technically, this means the package will be assigned package id 0x00.
+
+There are no restrictions on overlay packages names, though the naming
+convention <original.package.name>.overlay.<name> is recommended.
+
+
+Example overlay package
+~~~~~~~~~~~~~~~~~~~~~~~
+
+To overlay the resource bool/b in package com.foo.bar, to be applied
+when the display is in landscape mode, create a new package with
+no source code and a single .xml file under res/values-land, with
+an entry for bool/b. Compile with aapt -o and place the results in
+/system/overlay by adding the following to Android.mk:
+
+LOCAL_AAPT_FLAGS := -o com.foo.bar
+LOCAL_MODULE_PATH := $(TARGET_OUT)/overlay
+
+
+The ID map (idmap) file format
+------------------------------
+
+The idmap format is designed for lookup performance. However, leading
+and trailing undefined overlay values are discarded to reduce the memory
+footprint.
+
+
+idmap grammar
+~~~~~~~~~~~~~
+All atoms (names in square brackets) are uint32_t integers. The
+idmap-magic constant spells "idmp" in ASCII. Offsets are given relative
+to the data_header, not to the beginning of the file.
+
+map          := header data
+header       := idmap-magic <crc32-original-pkg> <crc32-overlay-pkg>
+idmap-magic  := <0x706d6469>
+data         := data_header type_block+
+data_header  := <m> header_block{m}
+header_block := <0> | <type_block_offset>
+type_block   := <n> <id_offset> entry{n}
+entry        := <resource_id_in_target_package>
+
+
+idmap example
+~~~~~~~~~~~~~
+Given a pair of target and overlay packages with CRC sums 0x216a8fe2
+and 0x6b9beaec, each defining the following resources
+
+Name          Target package  Overlay package
+string/str0   0x7f010000      -
+string/str1   0x7f010001      0x7f010000
+string/str2   0x7f010002      -
+string/str3   0x7f010003      0x7f010001
+string/str4   0x7f010004      -
+bool/bool0    0x7f020000      -
+integer/int0  0x7f030000      0x7f020000
+integer/int1  0x7f030001      -
+
+the corresponding resource map is
+
+0x706d6469 0x216a8fe2 0x6b9beaec 0x00000003 \
+0x00000004 0x00000000 0x00000009 0x00000003 \
+0x00000001 0x7f010000 0x00000000 0x7f010001 \
+0x00000001 0x00000000 0x7f020000
+
+or, formatted differently
+
+0x706d6469  # magic: all idmap files begin with this constant
+0x216a8fe2  # CRC32 of the resources.arsc file in the original package
+0x6b9beaec  # CRC32 of the resources.arsc file in the overlay package
+0x00000003  # header; three types (string, bool, integer) in the target package
+0x00000004  #   header_block for type 0 (string) is located at offset 4
+0x00000000  #   no bool type exists in overlay package -> no header_block
+0x00000009  #   header_block for type 2 (integer) is located at offset 9
+0x00000003  # header_block for string; overlay IDs span 3 elements
+0x00000001  #   the first string in target package is entry 1 == offset
+0x7f010000  #   target 0x7f01001 -> overlay 0x7f010000
+0x00000000  #   str2 not defined in overlay package
+0x7f010001  #   target 0x7f010003 -> overlay 0x7f010001
+0x00000001  # header_block for integer; overlay IDs span 1 element
+0x00000000  #   offset == 0
+0x7f020000  #   target 0x7f030000 -> overlay 0x7f020000
diff --git a/libs/utils/RefBase.cpp b/libs/utils/RefBase.cpp
index 0bd1af4..d28b751 100644
--- a/libs/utils/RefBase.cpp
+++ b/libs/utils/RefBase.cpp
@@ -480,7 +480,7 @@
 
 void RefBase::weakref_type::trackMe(bool enable, bool retain)
 {
-    static_cast<const weakref_impl*>(this)->trackMe(enable, retain);
+    static_cast<weakref_impl*>(this)->trackMe(enable, retain);
 }
 
 RefBase::weakref_type* RefBase::createWeak(const void* id) const
diff --git a/libs/utils/ResourceTypes.cpp b/libs/utils/ResourceTypes.cpp
index 8345cc3..57aaf24 100644
--- a/libs/utils/ResourceTypes.cpp
+++ b/libs/utils/ResourceTypes.cpp
@@ -63,6 +63,10 @@
 #endif
 #endif
 
+#define IDMAP_MAGIC         0x706d6469
+// size measured in sizeof(uint32_t)
+#define IDMAP_HEADER_SIZE (ResTable::IDMAP_HEADER_SIZE_BYTES / sizeof(uint32_t))
+
 static void printToLogFunc(void* cookie, const char* txt)
 {
     LOGV("%s", txt);
@@ -214,6 +218,81 @@
     outData->colors = (uint32_t*) data;
 }
 
+static bool assertIdmapHeader(const uint32_t* map, size_t sizeBytes)
+{
+    if (sizeBytes < ResTable::IDMAP_HEADER_SIZE_BYTES) {
+        LOGW("idmap assertion failed: size=%d bytes\n", sizeBytes);
+        return false;
+    }
+    if (*map != htodl(IDMAP_MAGIC)) { // htodl: map data expected to be in correct endianess
+        LOGW("idmap assertion failed: invalid magic found (is 0x%08x, expected 0x%08x)\n",
+             *map, htodl(IDMAP_MAGIC));
+        return false;
+    }
+    return true;
+}
+
+static status_t idmapLookup(const uint32_t* map, size_t sizeBytes, uint32_t key, uint32_t* outValue)
+{
+    // see README for details on the format of map
+    if (!assertIdmapHeader(map, sizeBytes)) {
+        return UNKNOWN_ERROR;
+    }
+    map = map + IDMAP_HEADER_SIZE; // skip ahead to data segment
+    // size of data block, in uint32_t
+    const size_t size = (sizeBytes - ResTable::IDMAP_HEADER_SIZE_BYTES) / sizeof(uint32_t);
+    const uint32_t type = Res_GETTYPE(key) + 1; // add one, idmap stores "public" type id
+    const uint32_t entry = Res_GETENTRY(key);
+    const uint32_t typeCount = *map;
+
+    if (type > typeCount) {
+        LOGW("Resource ID map: type=%d exceeds number of types=%d\n", type, typeCount);
+        return UNKNOWN_ERROR;
+    }
+    if (typeCount > size) {
+        LOGW("Resource ID map: number of types=%d exceeds size of map=%d\n", typeCount, size);
+        return UNKNOWN_ERROR;
+    }
+    const uint32_t typeOffset = map[type];
+    if (typeOffset == 0) {
+        *outValue = 0;
+        return NO_ERROR;
+    }
+    if (typeOffset + 1 > size) {
+        LOGW("Resource ID map: type offset=%d exceeds reasonable value, size of map=%d\n",
+             typeOffset, size);
+        return UNKNOWN_ERROR;
+    }
+    const uint32_t entryCount = map[typeOffset];
+    const uint32_t entryOffset = map[typeOffset + 1];
+    if (entryCount == 0 || entry < entryOffset || entry - entryOffset > entryCount - 1) {
+        *outValue = 0;
+        return NO_ERROR;
+    }
+    const uint32_t index = typeOffset + 2 + entry - entryOffset;
+    if (index > size) {
+        LOGW("Resource ID map: entry index=%d exceeds size of map=%d\n", index, size);
+        *outValue = 0;
+        return NO_ERROR;
+    }
+    *outValue = map[index];
+
+    return NO_ERROR;
+}
+
+static status_t getIdmapPackageId(const uint32_t* map, size_t mapSize, uint32_t *outId)
+{
+    if (!assertIdmapHeader(map, mapSize)) {
+        return UNKNOWN_ERROR;
+    }
+    const uint32_t* p = map + IDMAP_HEADER_SIZE + 1;
+    while (*p == 0) {
+        ++p;
+    }
+    *outId = (map[*p + IDMAP_HEADER_SIZE + 2] >> 24) & 0x000000ff;
+    return NO_ERROR;
+}
+
 Res_png_9patch* Res_png_9patch::deserialize(const void* inData)
 {
     if (sizeof(void*) != sizeof(int32_t)) {
@@ -1235,7 +1314,13 @@
 
 struct ResTable::Header
 {
-    Header(ResTable* _owner) : owner(_owner), ownedData(NULL), header(NULL) { }
+    Header(ResTable* _owner) : owner(_owner), ownedData(NULL), header(NULL),
+        resourceIDMap(NULL), resourceIDMapSize(0) { }
+
+    ~Header()
+    {
+        free(resourceIDMap);
+    }
 
     ResTable* const                 owner;
     void*                           ownedData;
@@ -1246,6 +1331,8 @@
     void*                           cookie;
 
     ResStringPool                   values;
+    uint32_t*                       resourceIDMap;
+    size_t                          resourceIDMapSize;
 };
 
 struct ResTable::Type
@@ -1661,12 +1748,13 @@
     return ((ssize_t)mPackageMap[Res_GETPACKAGE(resID)+1])-1;
 }
 
-status_t ResTable::add(const void* data, size_t size, void* cookie, bool copyData)
+status_t ResTable::add(const void* data, size_t size, void* cookie, bool copyData,
+                       const void* idmap)
 {
-    return add(data, size, cookie, NULL, copyData);
+    return add(data, size, cookie, NULL, copyData, reinterpret_cast<const Asset*>(idmap));
 }
 
-status_t ResTable::add(Asset* asset, void* cookie, bool copyData)
+status_t ResTable::add(Asset* asset, void* cookie, bool copyData, const void* idmap)
 {
     const void* data = asset->getBuffer(true);
     if (data == NULL) {
@@ -1674,7 +1762,7 @@
         return UNKNOWN_ERROR;
     }
     size_t size = (size_t)asset->getLength();
-    return add(data, size, cookie, asset, copyData);
+    return add(data, size, cookie, asset, copyData, reinterpret_cast<const Asset*>(idmap));
 }
 
 status_t ResTable::add(ResTable* src)
@@ -1702,19 +1790,30 @@
 }
 
 status_t ResTable::add(const void* data, size_t size, void* cookie,
-                       Asset* asset, bool copyData)
+                       Asset* asset, bool copyData, const Asset* idmap)
 {
     if (!data) return NO_ERROR;
     Header* header = new Header(this);
     header->index = mHeaders.size();
     header->cookie = cookie;
+    if (idmap != NULL) {
+        const size_t idmap_size = idmap->getLength();
+        const void* idmap_data = const_cast<Asset*>(idmap)->getBuffer(true);
+        header->resourceIDMap = (uint32_t*)malloc(idmap_size);
+        if (header->resourceIDMap == NULL) {
+            delete header;
+            return (mError = NO_MEMORY);
+        }
+        memcpy((void*)header->resourceIDMap, idmap_data, idmap_size);
+        header->resourceIDMapSize = idmap_size;
+    }
     mHeaders.add(header);
 
     const bool notDeviceEndian = htods(0xf0) != 0xf0;
 
     LOAD_TABLE_NOISY(
-        LOGV("Adding resources to ResTable: data=%p, size=0x%x, cookie=%p, asset=%p, copy=%d\n",
-             data, size, cookie, asset, copyData));
+        LOGV("Adding resources to ResTable: data=%p, size=0x%x, cookie=%p, asset=%p, copy=%d "
+             "idmap=%p\n", data, size, cookie, asset, copyData, idmap));
     
     if (copyData || notDeviceEndian) {
         header->ownedData = malloc(size);
@@ -1781,7 +1880,16 @@
                      dtohl(header->header->packageCount));
                 return (mError=BAD_TYPE);
             }
-            if (parsePackage((ResTable_package*)chunk, header) != NO_ERROR) {
+            uint32_t idmap_id = 0;
+            if (idmap != NULL) {
+                uint32_t tmp;
+                if (getIdmapPackageId(header->resourceIDMap,
+                                      header->resourceIDMapSize,
+                                      &tmp) == NO_ERROR) {
+                    idmap_id = tmp;
+                }
+            }
+            if (parsePackage((ResTable_package*)chunk, header, idmap_id) != NO_ERROR) {
                 return mError;
             }
             curPackage++;
@@ -1803,6 +1911,7 @@
     if (mError != NO_ERROR) {
         LOGW("No string values found in resource table!");
     }
+
     TABLE_NOISY(LOGV("Returning from add with mError=%d\n", mError));
     return mError;
 }
@@ -1925,17 +2034,38 @@
     size_t ip = grp->packages.size();
     while (ip > 0) {
         ip--;
+        int T = t;
+        int E = e;
 
         const Package* const package = grp->packages[ip];
+        if (package->header->resourceIDMap) {
+            uint32_t overlayResID = 0x0;
+            status_t retval = idmapLookup(package->header->resourceIDMap,
+                                          package->header->resourceIDMapSize,
+                                          resID, &overlayResID);
+            if (retval == NO_ERROR && overlayResID != 0x0) {
+                // for this loop iteration, this is the type and entry we really want
+                LOGV("resource map 0x%08x -> 0x%08x\n", resID, overlayResID);
+                T = Res_GETTYPE(overlayResID);
+                E = Res_GETENTRY(overlayResID);
+            } else {
+                // resource not present in overlay package, continue with the next package
+                continue;
+            }
+        }
 
         const ResTable_type* type;
         const ResTable_entry* entry;
         const Type* typeClass;
-        ssize_t offset = getEntry(package, t, e, &mParams, &type, &entry, &typeClass);
+        ssize_t offset = getEntry(package, T, E, &mParams, &type, &entry, &typeClass);
         if (offset <= 0) {
-            if (offset < 0) {
+            // No {entry, appropriate config} pair found in package. If this
+            // package is an overlay package (ip != 0), this simply means the
+            // overlay package did not specify a default.
+            // Non-overlay packages are still required to provide a default.
+            if (offset < 0 && ip == 0) {
                 LOGW("Failure getting entry for 0x%08x (t=%d e=%d) in package %zd (error %d)\n",
-                        resID, t, e, ip, (int)offset);
+                        resID, T, E, ip, (int)offset);
                 return offset;
             }
             continue;
@@ -1965,13 +2095,16 @@
 
         if (outSpecFlags != NULL) {
             if (typeClass->typeSpecFlags != NULL) {
-                *outSpecFlags |= dtohl(typeClass->typeSpecFlags[e]);
+                *outSpecFlags |= dtohl(typeClass->typeSpecFlags[E]);
             } else {
                 *outSpecFlags = -1;
             }
         }
-        
-        if (bestPackage != NULL && bestItem.isMoreSpecificThan(thisConfig)) {
+
+        if (bestPackage != NULL &&
+            (bestItem.isMoreSpecificThan(thisConfig) || bestItem.diff(thisConfig) == 0)) {
+            // Discard thisConfig not only if bestItem is more specific, but also if the two configs
+            // are identical (diff == 0), or overlay packages will not take effect.
             continue;
         }
         
@@ -2165,21 +2298,45 @@
 
     TABLE_NOISY(LOGI("Building bag: %p\n", (void*)resID));
     
+    ResTable_config bestConfig;
+    memset(&bestConfig, 0, sizeof(bestConfig));
+
     // Now collect all bag attributes from all packages.
     size_t ip = grp->packages.size();
     while (ip > 0) {
         ip--;
+        int T = t;
+        int E = e;
 
         const Package* const package = grp->packages[ip];
+        if (package->header->resourceIDMap) {
+            uint32_t overlayResID = 0x0;
+            status_t retval = idmapLookup(package->header->resourceIDMap,
+                                          package->header->resourceIDMapSize,
+                                          resID, &overlayResID);
+            if (retval == NO_ERROR && overlayResID != 0x0) {
+                // for this loop iteration, this is the type and entry we really want
+                LOGV("resource map 0x%08x -> 0x%08x\n", resID, overlayResID);
+                T = Res_GETTYPE(overlayResID);
+                E = Res_GETENTRY(overlayResID);
+            } else {
+                // resource not present in overlay package, continue with the next package
+                continue;
+            }
+        }
 
         const ResTable_type* type;
         const ResTable_entry* entry;
         const Type* typeClass;
-        LOGV("Getting entry pkg=%p, t=%d, e=%d\n", package, t, e);
-        ssize_t offset = getEntry(package, t, e, &mParams, &type, &entry, &typeClass);
+        LOGV("Getting entry pkg=%p, t=%d, e=%d\n", package, T, E);
+        ssize_t offset = getEntry(package, T, E, &mParams, &type, &entry, &typeClass);
         LOGV("Resulting offset=%d\n", offset);
         if (offset <= 0) {
-            if (offset < 0) {
+            // No {entry, appropriate config} pair found in package. If this
+            // package is an overlay package (ip != 0), this simply means the
+            // overlay package did not specify a default.
+            // Non-overlay packages are still required to provide a default.
+            if (offset < 0 && ip == 0) {
                 if (set) free(set);
                 return offset;
             }
@@ -2192,6 +2349,15 @@
             continue;
         }
 
+        if (set != NULL && !type->config.isBetterThan(bestConfig, NULL)) {
+            continue;
+        }
+        bestConfig = type->config;
+        if (set) {
+            free(set);
+            set = NULL;
+        }
+
         const uint16_t entrySize = dtohs(entry->size);
         const uint32_t parent = entrySize >= sizeof(ResTable_map_entry)
             ? dtohl(((const ResTable_map_entry*)entry)->parent.ident) : 0;
@@ -2203,43 +2369,41 @@
         TABLE_NOISY(LOGI("Found map: size=%p parent=%p count=%d\n",
                          entrySize, parent, count));
 
-        if (set == NULL) {
-            // If this map inherits from another, we need to start
-            // with its parent's values.  Otherwise start out empty.
-            TABLE_NOISY(printf("Creating new bag, entrySize=0x%08x, parent=0x%08x\n",
-                         entrySize, parent));
-            if (parent) {
-                const bag_entry* parentBag;
-                uint32_t parentTypeSpecFlags = 0;
-                const ssize_t NP = getBagLocked(parent, &parentBag, &parentTypeSpecFlags);
-                const size_t NT = ((NP >= 0) ? NP : 0) + N;
-                set = (bag_set*)malloc(sizeof(bag_set)+sizeof(bag_entry)*NT);
-                if (set == NULL) {
-                    return NO_MEMORY;
-                }
-                if (NP > 0) {
-                    memcpy(set+1, parentBag, NP*sizeof(bag_entry));
-                    set->numAttrs = NP;
-                    TABLE_NOISY(LOGI("Initialized new bag with %d inherited attributes.\n", NP));
-                } else {
-                    TABLE_NOISY(LOGI("Initialized new bag with no inherited attributes.\n"));
-                    set->numAttrs = 0;
-                }
-                set->availAttrs = NT;
-                set->typeSpecFlags = parentTypeSpecFlags;
-            } else {
-                set = (bag_set*)malloc(sizeof(bag_set)+sizeof(bag_entry)*N);
-                if (set == NULL) {
-                    return NO_MEMORY;
-                }
-                set->numAttrs = 0;
-                set->availAttrs = N;
-                set->typeSpecFlags = 0;
+        // If this map inherits from another, we need to start
+        // with its parent's values.  Otherwise start out empty.
+        TABLE_NOISY(printf("Creating new bag, entrySize=0x%08x, parent=0x%08x\n",
+                           entrySize, parent));
+        if (parent) {
+            const bag_entry* parentBag;
+            uint32_t parentTypeSpecFlags = 0;
+            const ssize_t NP = getBagLocked(parent, &parentBag, &parentTypeSpecFlags);
+            const size_t NT = ((NP >= 0) ? NP : 0) + N;
+            set = (bag_set*)malloc(sizeof(bag_set)+sizeof(bag_entry)*NT);
+            if (set == NULL) {
+                return NO_MEMORY;
             }
+            if (NP > 0) {
+                memcpy(set+1, parentBag, NP*sizeof(bag_entry));
+                set->numAttrs = NP;
+                TABLE_NOISY(LOGI("Initialized new bag with %d inherited attributes.\n", NP));
+            } else {
+                TABLE_NOISY(LOGI("Initialized new bag with no inherited attributes.\n"));
+                set->numAttrs = 0;
+            }
+            set->availAttrs = NT;
+            set->typeSpecFlags = parentTypeSpecFlags;
+        } else {
+            set = (bag_set*)malloc(sizeof(bag_set)+sizeof(bag_entry)*N);
+            if (set == NULL) {
+                return NO_MEMORY;
+            }
+            set->numAttrs = 0;
+            set->availAttrs = N;
+            set->typeSpecFlags = 0;
         }
 
         if (typeClass->typeSpecFlags != NULL) {
-            set->typeSpecFlags |= dtohl(typeClass->typeSpecFlags[e]);
+            set->typeSpecFlags |= dtohl(typeClass->typeSpecFlags[E]);
         } else {
             set->typeSpecFlags = -1;
         }
@@ -3759,7 +3923,7 @@
 }
 
 status_t ResTable::parsePackage(const ResTable_package* const pkg,
-                                const Header* const header)
+                                const Header* const header, uint32_t idmap_id)
 {
     const uint8_t* base = (const uint8_t*)pkg;
     status_t err = validate_chunk(&pkg->header, sizeof(*pkg),
@@ -3793,8 +3957,12 @@
     
     Package* package = NULL;
     PackageGroup* group = NULL;
-    uint32_t id = dtohl(pkg->id);
-    if (id != 0 && id < 256) {
+    uint32_t id = idmap_id != 0 ? idmap_id : dtohl(pkg->id);
+    // If at this point id == 0, pkg is an overlay package without a
+    // corresponding idmap. During regular usage, overlay packages are
+    // always loaded alongside their idmaps, but during idmap creation
+    // the package is temporarily loaded by itself.
+    if (id < 256) {
     
         package = new Package(this, header, pkg);
         if (package == NULL) {
@@ -3847,7 +4015,7 @@
             return (mError=err);
         }
     } else {
-        LOG_ALWAYS_FATAL("Skins not supported!");
+        LOG_ALWAYS_FATAL("Package id out of range");
         return NO_ERROR;
     }
 
@@ -3998,6 +4166,136 @@
     return NO_ERROR;
 }
 
+status_t ResTable::createIdmap(const ResTable& overlay, uint32_t originalCrc, uint32_t overlayCrc,
+                               void** outData, size_t* outSize) const
+{
+    // see README for details on the format of map
+    if (mPackageGroups.size() == 0) {
+        return UNKNOWN_ERROR;
+    }
+    if (mPackageGroups[0]->packages.size() == 0) {
+        return UNKNOWN_ERROR;
+    }
+
+    Vector<Vector<uint32_t> > map;
+    const PackageGroup* pg = mPackageGroups[0];
+    const Package* pkg = pg->packages[0];
+    size_t typeCount = pkg->types.size();
+    // starting size is header + first item (number of types in map)
+    *outSize = (IDMAP_HEADER_SIZE + 1) * sizeof(uint32_t);
+    const String16 overlayPackage(overlay.mPackageGroups[0]->packages[0]->package->name);
+    const uint32_t pkg_id = pkg->package->id << 24;
+
+    for (size_t typeIndex = 0; typeIndex < typeCount; ++typeIndex) {
+        ssize_t offset = -1;
+        const Type* typeConfigs = pkg->getType(typeIndex);
+        ssize_t mapIndex = map.add();
+        if (mapIndex < 0) {
+            return NO_MEMORY;
+        }
+        Vector<uint32_t>& vector = map.editItemAt(mapIndex);
+        for (size_t entryIndex = 0; entryIndex < typeConfigs->entryCount; ++entryIndex) {
+            uint32_t resID = (0xff000000 & ((pkg->package->id)<<24))
+                | (0x00ff0000 & ((typeIndex+1)<<16))
+                | (0x0000ffff & (entryIndex));
+            resource_name resName;
+            if (!this->getResourceName(resID, &resName)) {
+                return UNKNOWN_ERROR;
+            }
+
+            const String16 overlayType(resName.type, resName.typeLen);
+            const String16 overlayName(resName.name, resName.nameLen);
+            uint32_t overlayResID = overlay.identifierForName(overlayName.string(),
+                                                              overlayName.size(),
+                                                              overlayType.string(),
+                                                              overlayType.size(),
+                                                              overlayPackage.string(),
+                                                              overlayPackage.size());
+            if (overlayResID != 0) {
+                // overlay package has package ID == 0, use original package's ID instead
+                overlayResID |= pkg_id;
+            }
+            vector.push(overlayResID);
+            if (overlayResID != 0 && offset == -1) {
+                offset = Res_GETENTRY(resID);
+            }
+#if 0
+            if (overlayResID != 0) {
+                LOGD("%s/%s 0x%08x -> 0x%08x\n",
+                     String8(String16(resName.type)).string(),
+                     String8(String16(resName.name)).string(),
+                     resID, overlayResID);
+            }
+#endif
+        }
+
+        if (offset != -1) {
+            // shave off leading and trailing entries which lack overlay values
+            vector.removeItemsAt(0, offset);
+            vector.insertAt((uint32_t)offset, 0, 1);
+            while (vector.top() == 0) {
+                vector.pop();
+            }
+            // reserve space for number and offset of entries, and the actual entries
+            *outSize += (2 + vector.size()) * sizeof(uint32_t);
+        } else {
+            // no entries of current type defined in overlay package
+            vector.clear();
+            // reserve space for type offset
+            *outSize += 1 * sizeof(uint32_t);
+        }
+    }
+
+    if ((*outData = malloc(*outSize)) == NULL) {
+        return NO_MEMORY;
+    }
+    uint32_t* data = (uint32_t*)*outData;
+    *data++ = htodl(IDMAP_MAGIC);
+    *data++ = htodl(originalCrc);
+    *data++ = htodl(overlayCrc);
+    const size_t mapSize = map.size();
+    *data++ = htodl(mapSize);
+    size_t offset = mapSize;
+    for (size_t i = 0; i < mapSize; ++i) {
+        const Vector<uint32_t>& vector = map.itemAt(i);
+        const size_t N = vector.size();
+        if (N == 0) {
+            *data++ = htodl(0);
+        } else {
+            offset++;
+            *data++ = htodl(offset);
+            offset += N;
+        }
+    }
+    for (size_t i = 0; i < mapSize; ++i) {
+        const Vector<uint32_t>& vector = map.itemAt(i);
+        const size_t N = vector.size();
+        if (N == 0) {
+            continue;
+        }
+        *data++ = htodl(N - 1); // do not count the offset (which is vector's first element)
+        for (size_t j = 0; j < N; ++j) {
+            const uint32_t& overlayResID = vector.itemAt(j);
+            *data++ = htodl(overlayResID);
+        }
+    }
+
+    return NO_ERROR;
+}
+
+bool ResTable::getIdmapInfo(const void* idmap, size_t sizeBytes,
+                            uint32_t* pOriginalCrc, uint32_t* pOverlayCrc)
+{
+    const uint32_t* map = (const uint32_t*)idmap;
+    if (!assertIdmapHeader(map, sizeBytes)) {
+        return false;
+    }
+    *pOriginalCrc = map[1];
+    *pOverlayCrc = map[2];
+    return true;
+}
+
+
 #ifndef HAVE_ANDROID_OS
 #define CHAR16_TO_CSTR(c16, len) (String8(String16(c16,len)).string())
 
@@ -4038,6 +4336,38 @@
     }
 }
 
+// Normalize a string for output
+String8 ResTable::normalizeForOutput( const char *input )
+{
+    String8 ret;
+    char buff[2];
+    buff[1] = '\0';
+
+    while (*input != '\0') {
+        switch (*input) {
+            // All interesting characters are in the ASCII zone, so we are making our own lives
+            // easier by scanning the string one byte at a time.
+        case '\\':
+            ret += "\\\\";
+            break;
+        case '\n':
+            ret += "\\n";
+            break;
+        case '"':
+            ret += "\\\"";
+            break;
+        default:
+            buff[0] = *input;
+            ret += buff;
+            break;
+        }
+
+        input++;
+    }
+
+    return ret;
+}
+
 void ResTable::print_value(const Package* pkg, const Res_value& value) const
 {
     if (value.dataType == Res_value::TYPE_NULL) {
@@ -4051,13 +4381,13 @@
         const char* str8 = pkg->header->values.string8At(
                 value.data, &len);
         if (str8 != NULL) {
-            printf("(string8) \"%s\"\n", str8);
+            printf("(string8) \"%s\"\n", normalizeForOutput(str8).string());
         } else {
             const char16_t* str16 = pkg->header->values.stringAt(
                     value.data, &len);
             if (str16 != NULL) {
                 printf("(string16) \"%s\"\n",
-                    String8(str16, len).string());
+                    normalizeForOutput(String8(str16, len).string()).string());
             } else {
                 printf("(string) null\n");
             }
diff --git a/libs/utils/Threads.cpp b/libs/utils/Threads.cpp
index f6c55e4..b1bd828 100644
--- a/libs/utils/Threads.cpp
+++ b/libs/utils/Threads.cpp
@@ -774,7 +774,11 @@
             self->mExitPending = true;
             self->mLock.lock();
             self->mRunning = false;
+            // clear thread ID so that requestExitAndWait() does not exit if
+            // called by a new thread using the same thread ID as this one.
+            self->mThread = thread_id_t(-1);
             self->mThreadExitedCondition.broadcast();
+            self->mThread = thread_id_t(-1); // thread id could be reused
             self->mLock.unlock();
             break;
         }
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index ab260d5..d26d13e 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -40,6 +40,8 @@
 #include <utils/KeyedVector.h>
 #include <utils/String8.h>
 
+#include <ui/egl/android_natives.h>
+
 #include "hooks.h"
 #include "egl_impl.h"
 #include "Loader.h"
@@ -196,15 +198,16 @@
 {
     typedef egl_object_t::LocalRef<egl_surface_t, EGLSurface> Ref;
 
-    egl_surface_t(EGLDisplay dpy, EGLSurface surface, EGLConfig config,
-            int impl, egl_connection_t const* cnx) 
-    : dpy(dpy), surface(surface), config(config), impl(impl), cnx(cnx) {
+    egl_surface_t(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win,
+            EGLSurface surface, int impl, egl_connection_t const* cnx)
+    : dpy(dpy), surface(surface), config(config), win(win), impl(impl), cnx(cnx) {
     }
     ~egl_surface_t() {
     }
     EGLDisplay                  dpy;
     EGLSurface                  surface;
     EGLConfig                   config;
+    sp<ANativeWindow>           win;
     int                         impl;
     egl_connection_t const*     cnx;
 };
@@ -215,8 +218,8 @@
     
     egl_context_t(EGLDisplay dpy, EGLContext context, EGLConfig config,
             int impl, egl_connection_t const* cnx, int version) 
-    : dpy(dpy), context(context), read(0), draw(0), impl(impl), cnx(cnx),
-      version(version)
+    : dpy(dpy), context(context), config(config), read(0), draw(0), impl(impl),
+      cnx(cnx), version(version)
     {
     }
     EGLDisplay                  dpy;
@@ -811,7 +814,7 @@
     dp->refs--;
     dp->numTotalConfigs = 0;
     delete [] dp->configs;
-    clearTLS();
+
     return res;
 }
 
@@ -984,11 +987,22 @@
     egl_display_t const* dp = 0;
     egl_connection_t* cnx = validate_display_config(dpy, config, dp);
     if (cnx) {
+        EGLDisplay iDpy = dp->disp[ dp->configs[intptr_t(config)].impl ].dpy;
+        EGLConfig iConfig = dp->configs[intptr_t(config)].config;
+        EGLint format;
+
+        // set the native window's buffers format to match this config
+        if (cnx->egl.eglGetConfigAttrib(iDpy,
+                iConfig, EGL_NATIVE_VISUAL_ID, &format)) {
+            if (format != 0) {
+                native_window_set_buffers_geometry(window, 0, 0, format);
+            }
+        }
+
         EGLSurface surface = cnx->egl.eglCreateWindowSurface(
-                dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
-                dp->configs[intptr_t(config)].config, window, attrib_list);
+                iDpy, iConfig, window, attrib_list);
         if (surface != EGL_NO_SURFACE) {
-            egl_surface_t* s = new egl_surface_t(dpy, surface, config,
+            egl_surface_t* s = new egl_surface_t(dpy, config, window, surface,
                     dp->configs[intptr_t(config)].impl, cnx);
             return s;
         }
@@ -1007,7 +1021,7 @@
                 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
                 dp->configs[intptr_t(config)].config, pixmap, attrib_list);
         if (surface != EGL_NO_SURFACE) {
-            egl_surface_t* s = new egl_surface_t(dpy, surface, config,
+            egl_surface_t* s = new egl_surface_t(dpy, config, NULL, surface,
                     dp->configs[intptr_t(config)].impl, cnx);
             return s;
         }
@@ -1025,7 +1039,7 @@
                 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
                 dp->configs[intptr_t(config)].config, attrib_list);
         if (surface != EGL_NO_SURFACE) {
-            egl_surface_t* s = new egl_surface_t(dpy, surface, config,
+            egl_surface_t* s = new egl_surface_t(dpy, config, NULL, surface,
                     dp->configs[intptr_t(config)].impl, cnx);
             return s;
         }
@@ -1046,6 +1060,9 @@
     EGLBoolean result = s->cnx->egl.eglDestroySurface(
             dp->disp[s->impl].dpy, s->surface);
     if (result == EGL_TRUE) {
+        if (s->win != NULL) {
+            native_window_set_buffers_geometry(s->win.get(), 0, 0, 0);
+        }
         _s.terminate();
     }
     return result;
@@ -1133,6 +1150,27 @@
     return result;
 }
 
+static void loseCurrent(egl_context_t * cur_c)
+{
+    if (cur_c) {
+        egl_surface_t * cur_r = get_surface(cur_c->read);
+        egl_surface_t * cur_d = get_surface(cur_c->draw);
+
+        // by construction, these are either 0 or valid (possibly terminated)
+        // it should be impossible for these to be invalid
+        ContextRef _cur_c(cur_c);
+        SurfaceRef _cur_r(cur_r);
+        SurfaceRef _cur_d(cur_d);
+
+        cur_c->read = NULL;
+        cur_c->draw = NULL;
+
+        _cur_c.release();
+        _cur_r.release();
+        _cur_d.release();
+    }
+}
+
 EGLBoolean eglMakeCurrent(  EGLDisplay dpy, EGLSurface draw,
                             EGLSurface read, EGLContext ctx)
 {
@@ -1161,13 +1199,9 @@
 
     // these are the current objects structs
     egl_context_t * cur_c = get_context(getContext());
-    egl_surface_t * cur_r = NULL;
-    egl_surface_t * cur_d = NULL;
     
     if (ctx != EGL_NO_CONTEXT) {
         c = get_context(ctx);
-        cur_r = get_surface(c->read);
-        cur_d = get_surface(c->draw);
         impl_ctx = c->context;
     } else {
         // no context given, use the implementation of the current context
@@ -1213,30 +1247,21 @@
     }
 
     if (result == EGL_TRUE) {
-        // by construction, these are either 0 or valid (possibly terminated)
-        // it should be impossible for these to be invalid
-        ContextRef _cur_c(cur_c);
-        SurfaceRef _cur_r(cur_r);
-        SurfaceRef _cur_d(cur_d);
 
-        // cur_c has to be valid here (but could be terminated)
+        loseCurrent(cur_c);
+
         if (ctx != EGL_NO_CONTEXT) {
             setGlThreadSpecific(c->cnx->hooks[c->version]);
             setContext(ctx);
             _c.acquire();
+            _r.acquire();
+            _d.acquire();
+            c->read = read;
+            c->draw = draw;
         } else {
             setGlThreadSpecific(&gHooksNoContext);
             setContext(EGL_NO_CONTEXT);
         }
-        _cur_c.release();
-
-        _r.acquire();
-        _cur_r.release();
-        if (c) c->read = read;
-
-        _d.acquire();
-        _cur_d.release();
-        if (c) c->draw = draw;
     }
     return result;
 }
@@ -1620,6 +1645,9 @@
 
 EGLBoolean eglReleaseThread(void)
 {
+    // If there is context bound to the thread, release it
+    loseCurrent(get_context(getContext()));
+
     for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
         egl_connection_t* const cnx = &gEGLImpl[i];
         if (cnx->dso) {
@@ -1815,3 +1843,8 @@
     }
     return setError(EGL_BAD_DISPLAY, NULL);
 }
+
+EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync) { return 0; }
+EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list) { return 0; }
+EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout) { return 0; }
+
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index e2f8a74..c5bdaa1 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -37,7 +37,6 @@
 
 LOCAL_SHARED_LIBRARIES := \
 	libcutils \
-	libpixelflinger \
 	libhardware \
 	libutils \
 	libEGL \
diff --git a/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp
index 28a512e..818774d 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp
+++ b/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp
@@ -339,6 +339,12 @@
     //glClear(GL_COLOR_BUFFER_BIT);
 }
 
+status_t DisplayHardware::postBypassBuffer(const native_handle_t* handle) const
+{
+   framebuffer_device_t *fbDev = (framebuffer_device_t *)mNativeWindow->getDevice();
+   return fbDev->post(fbDev, handle);
+}
+
 uint32_t DisplayHardware::getFlags() const
 {
     return mFlags;
diff --git a/services/surfaceflinger/DisplayHardware/DisplayHardware.h b/services/surfaceflinger/DisplayHardware/DisplayHardware.h
index 2d7900c..79ef2a7 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayHardware.h
+++ b/services/surfaceflinger/DisplayHardware/DisplayHardware.h
@@ -64,6 +64,7 @@
     // Flip the front and back buffers if the back buffer is "dirty".  Might
     // be instantaneous, might involve copying the frame buffer around.
     void flip(const Region& dirty) const;
+    status_t postBypassBuffer(const native_handle_t* handle) const;
 
     float       getDpiX() const;
     float       getDpiY() const;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index a060d31..dfee803 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -57,7 +57,8 @@
         mSecure(false),
         mTextureManager(),
         mBufferManager(mTextureManager),
-        mWidth(0), mHeight(0), mFixedSize(false)
+        mWidth(0), mHeight(0), mNeedsScaling(false), mFixedSize(false),
+        mBypassState(false)
 {
 }
 
@@ -216,13 +217,10 @@
 
 void Layer::drawForSreenShot() const
 {
-    bool currentFixedSize = mFixedSize;
-    bool currentBlending = mNeedsBlending;
-    const_cast<Layer*>(this)->mFixedSize = false;
-    const_cast<Layer*>(this)->mFixedSize = true;
+    const bool currentFiltering = mNeedsFiltering;
+    const_cast<Layer*>(this)->mNeedsFiltering = true;
     LayerBase::drawForSreenShot();
-    const_cast<Layer*>(this)->mFixedSize = currentFixedSize;
-    const_cast<Layer*>(this)->mNeedsBlending = currentBlending;
+    const_cast<Layer*>(this)->mNeedsFiltering = currentFiltering;
 }
 
 void Layer::onDraw(const Region& clip) const
@@ -254,17 +252,39 @@
         }
         return;
     }
+
+#ifdef USE_COMPOSITION_BYPASS
+    sp<GraphicBuffer> buffer(mBufferManager.getActiveBuffer());
+    if ((buffer != NULL) && (buffer->transform)) {
+        // Here we have a "bypass" buffer, but we need to composite it
+        // most likely because it's not fullscreen anymore.
+        // Since the buffer may have a transformation applied by the client
+        // we need to inverse this transformation here.
+
+        // calculate the inverse of the buffer transform
+        const uint32_t mask = HAL_TRANSFORM_FLIP_V | HAL_TRANSFORM_FLIP_H;
+        const uint32_t bufferTransformInverse = buffer->transform ^ mask;
+
+        // To accomplish the inverse transform, we use "mBufferTransform"
+        // which is not used by Layer.cpp
+        const_cast<Layer*>(this)->mBufferTransform = bufferTransformInverse;
+        drawWithOpenGL(clip, tex);
+        // reset to "no transfrom"
+        const_cast<Layer*>(this)->mBufferTransform = 0;
+        return;
+    }
+#endif
+
     drawWithOpenGL(clip, tex);
 }
 
 bool Layer::needsFiltering() const
 {
     if (!(mFlags & DisplayHardware::SLOW_CONFIG)) {
-        // NOTE: there is a race here, because mFixedSize is updated in a
-        // binder transaction. however, it doesn't really matter since it is
-        // evaluated each time we draw. To be perfectly correct, this flag
-        // would have to be associated with a buffer.
-        if (mFixedSize)
+        // if our buffer is not the same size than ourselves,
+        // we need filtering.
+        Mutex::Autolock _l(mLock);
+        if (mNeedsScaling)
             return true;
     }
     return LayerBase::needsFiltering();
@@ -315,12 +335,14 @@
      * buffer 'index' as our front buffer.
      */
 
-    status_t err = NO_ERROR;
-    uint32_t w, h, f;
+    uint32_t w, h, f, bypass;
     { // scope for the lock
         Mutex::Autolock _l(mLock);
 
+        bypass = mBypassState;
+
         // zero means default
+        mFixedSize = reqWidth && reqHeight;
         if (!reqFormat) reqFormat = mFormat;
         if (!reqWidth)  reqWidth = mWidth;
         if (!reqHeight) reqHeight = mHeight;
@@ -334,6 +356,7 @@
             mReqWidth  = reqWidth;
             mReqHeight = reqHeight;
             mReqFormat = reqFormat;
+            mNeedsScaling = mWidth != mReqWidth || mHeight != mReqHeight;
 
             lcblk->reallocateAllExcept(index);
         }
@@ -342,11 +365,43 @@
     // here we have to reallocate a new buffer because the buffer could be
     // used as the front buffer, or by a client in our process
     // (eg: status bar), and we can't release the handle under its feet.
-    const uint32_t effectiveUsage = getEffectiveUsage(usage);
-    buffer = new GraphicBuffer(w, h, f, effectiveUsage);
-    err = buffer->initCheck();
+    uint32_t effectiveUsage = getEffectiveUsage(usage);
+
+    status_t err = NO_MEMORY;
+
+#ifdef USE_COMPOSITION_BYPASS
+    if (!mSecure && bypass && (effectiveUsage & GRALLOC_USAGE_HW_RENDER)) {
+        // always allocate a buffer matching the screen size. the size
+        // may be different from (w,h) if the buffer is rotated.
+        const DisplayHardware& hw(graphicPlane(0).displayHardware());
+        int32_t w = hw.getWidth();
+        int32_t h = hw.getHeight();
+        int32_t f = hw.getFormat();
+
+        buffer = new GraphicBuffer(w, h, f, effectiveUsage | GRALLOC_USAGE_HW_FB);
+        err = buffer->initCheck();
+        buffer->transform = uint8_t(getOrientation());
+
+        if (err != NO_ERROR) {
+            // allocation didn't succeed, probably because an older bypass
+            // window hasn't released all its resources yet.
+            ClientRef::Access sharedClient(mUserClientRef);
+            SharedBufferServer* lcblk(sharedClient.get());
+            if (lcblk) {
+                // all buffers need reallocation
+                lcblk->reallocateAll();
+            }
+        }
+    }
+#endif
+
+    if (err != NO_ERROR) {
+        buffer = new GraphicBuffer(w, h, f, effectiveUsage);
+        err = buffer->initCheck();
+    }
 
     if (err || buffer->handle == 0) {
+        GraphicBuffer::dumpAllocationsToSystemLog();
         LOGE_IF(err || buffer->handle == 0,
                 "Layer::requestBuffer(this=%p), index=%d, w=%d, h=%d failed (%s)",
                 this, index, w, h, strerror(-err));
@@ -390,6 +445,39 @@
     return usage;
 }
 
+bool Layer::setBypass(bool enable)
+{
+    Mutex::Autolock _l(mLock);
+
+    if (mNeedsScaling || mNeedsFiltering) {
+        return false;
+    }
+
+    if (mBypassState != enable) {
+        mBypassState = enable;
+        ClientRef::Access sharedClient(mUserClientRef);
+        SharedBufferServer* lcblk(sharedClient.get());
+        if (lcblk) {
+            // all buffers need reallocation
+            lcblk->reallocateAll();
+        }
+    }
+
+    return true;
+}
+
+void Layer::updateBuffersOrientation()
+{
+    sp<GraphicBuffer> buffer(getBypassBuffer());
+    if (buffer != NULL && mOrientation != buffer->transform) {
+        ClientRef::Access sharedClient(mUserClientRef);
+        SharedBufferServer* lcblk(sharedClient.get());
+        if (lcblk) { // all buffers need reallocation
+            lcblk->reallocateAll();
+        }
+    }
+}
+
 uint32_t Layer::doTransaction(uint32_t flags)
 {
     const Layer::State& front(drawingState());
@@ -456,6 +544,7 @@
     Mutex::Autolock _l(mLock);
     mWidth = w;
     mHeight = h;
+    mNeedsScaling = mWidth != mReqWidth || mHeight != mReqHeight;
 }
 
 bool Layer::isFixedSize() const {
@@ -593,22 +682,6 @@
     }
 }
 
-void Layer::finishPageFlip()
-{
-    ClientRef::Access sharedClient(mUserClientRef);
-    SharedBufferServer* lcblk(sharedClient.get());
-    if (lcblk) {
-        int buf = mBufferManager.getActiveBufferIndex();
-        if (buf >= 0) {
-            status_t err = lcblk->unlock( buf );
-            LOGE_IF(err!=NO_ERROR,
-                    "layer %p, buffer=%d wasn't locked!",
-                    this, buf);
-        }
-    }
-}
-
-
 void Layer::dump(String8& result, char* buffer, size_t SIZE) const
 {
     LayerBaseClient::dump(result, buffer, SIZE);
@@ -639,9 +712,9 @@
     snprintf(buffer, SIZE,
             "      "
             "format=%2d, [%3ux%3u:%3u] [%3ux%3u:%3u],"
-            " freezeLock=%p, dq-q-time=%u us\n",
+            " freezeLock=%p, bypass=%d, dq-q-time=%u us\n",
             mFormat, w0, h0, s0, w1, h1, s1,
-            getFreezeLock().get(), totalTime);
+            getFreezeLock().get(), mBypassState, totalTime);
 
     result.append(buffer);
 }
@@ -801,8 +874,16 @@
     ssize_t index = mActiveBuffer;
     if (index >= 0) {
         if (!mFailover) {
-            Image& texture(mBufferData[index].texture);
-            err = mTextureManager.initEglImage(&texture, dpy, buffer);
+            {
+               // Without that lock, there is a chance of race condition
+               // where while composing a specific index, requestBuf
+               // with the same index can be executed and touch the same data
+               // that is being used in initEglImage.
+               // (e.g. dirty flag in texture)
+               Mutex::Autolock _l(mLock);
+               Image& texture(mBufferData[index].texture);
+               err = mTextureManager.initEglImage(&texture, dpy, buffer);
+            }
             // if EGLImage fails, we switch to regular texture mode, and we
             // free all resources associated with using EGLImages.
             if (err == NO_ERROR) {
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 263c372..7bb207a 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -73,7 +73,6 @@
     virtual uint32_t doTransaction(uint32_t transactionFlags);
     virtual void lockPageFlip(bool& recomputeVisibleRegions);
     virtual void unlockPageFlip(const Transform& planeTransform, Region& outDirtyRegion);
-    virtual void finishPageFlip();
     virtual bool needsBlending() const      { return mNeedsBlending; }
     virtual bool needsDithering() const     { return mNeedsDithering; }
     virtual bool needsFiltering() const;
@@ -81,6 +80,12 @@
     virtual sp<Surface> createSurface() const;
     virtual status_t ditch();
     virtual void onRemoved();
+    virtual bool setBypass(bool enable);
+
+    void updateBuffersOrientation();
+
+    inline sp<GraphicBuffer> getBypassBuffer() const {
+        return mBufferManager.getActiveBuffer(); }
 
     // only for debugging
     inline sp<GraphicBuffer> getBuffer(int i) const {
@@ -230,7 +235,9 @@
     uint32_t mReqWidth;
     uint32_t mReqHeight;
     uint32_t mReqFormat;
+    bool mNeedsScaling;
     bool mFixedSize;
+    bool mBypassState;
 };
 
 // ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp
index 64eed4b..21c36e1 100644
--- a/services/surfaceflinger/LayerBase.cpp
+++ b/services/surfaceflinger/LayerBase.cpp
@@ -216,14 +216,10 @@
         flags |= eVisibleRegion;
         this->contentDirty = true;
 
-        mNeedsFiltering = false;
-        if (!(mFlags & DisplayHardware::SLOW_CONFIG)) {
-            // we may use linear filtering, if the matrix scales us
-            const uint8_t type = temp.transform.getType();
-            if (!temp.transform.preserveRects() || (type >= Transform::SCALE)) {
-                mNeedsFiltering = true;
-            }
-        }
+        // we may use linear filtering, if the matrix scales us
+        const uint8_t type = temp.transform.getType();
+        mNeedsFiltering = (!temp.transform.preserveRects() ||
+                (type >= Transform::SCALE));
     }
 
     // Commit the transaction
@@ -277,10 +273,6 @@
     }
 }
 
-void LayerBase::finishPageFlip()
-{
-}
-
 void LayerBase::invalidate()
 {
     if ((android_atomic_or(1, &mInvalidate)&1) == 0) {
diff --git a/services/surfaceflinger/LayerBase.h b/services/surfaceflinger/LayerBase.h
index d688f65..afc5ec8 100644
--- a/services/surfaceflinger/LayerBase.h
+++ b/services/surfaceflinger/LayerBase.h
@@ -35,6 +35,7 @@
 
 #include <pixelflinger/pixelflinger.h>
 
+#include "DisplayHardware/DisplayHardware.h"
 #include "Transform.h"
 
 namespace android {
@@ -118,6 +119,11 @@
     virtual void drawForSreenShot() const;
     
     /**
+     * bypass mode
+     */
+    virtual bool setBypass(bool enable) { return false; }
+
+    /**
      * onDraw - draws the surface.
      */
     virtual void onDraw(const Region& clip) const = 0;
@@ -168,11 +174,6 @@
     virtual void unlockPageFlip(const Transform& planeTransform, Region& outDirtyRegion);
     
     /**
-     * finishPageFlip - called after all surfaces have drawn.
-     */
-    virtual void finishPageFlip();
-    
-    /**
      * needsBlending - true if this surface needs blending
      */
     virtual bool needsBlending() const  { return false; }
@@ -185,7 +186,9 @@
     /**
      * needsLinearFiltering - true if this surface needs filtering
      */
-    virtual bool needsFiltering() const { return mNeedsFiltering; }
+    virtual bool needsFiltering() const {
+        return (!(mFlags & DisplayHardware::SLOW_CONFIG)) && mNeedsFiltering;
+    }
 
     /**
      * isSecure - true if this surface is secure, that is if it prevents
diff --git a/services/surfaceflinger/LayerBuffer.cpp b/services/surfaceflinger/LayerBuffer.cpp
index 23506cf..55d859d 100644
--- a/services/surfaceflinger/LayerBuffer.cpp
+++ b/services/surfaceflinger/LayerBuffer.cpp
@@ -93,6 +93,9 @@
 }
 
 void LayerBuffer::setNeedsBlending(bool blending) {
+    if (mNeedsBlending != blending) {
+        mFlinger->invalidateLayerVisibility(this);
+    }
     mNeedsBlending = blending;
 }
 
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index a9b3965..c08e2c9 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -61,6 +61,10 @@
 #define AID_GRAPHICS 1003
 #endif
 
+#ifdef USE_COMPOSITION_BYPASS
+#warning "using COMPOSITION_BYPASS"
+#endif
+
 #define DISPLAY_COUNT       1
 
 namespace android {
@@ -373,8 +377,15 @@
 
     const DisplayHardware& hw(graphicPlane(0).displayHardware());
     if (LIKELY(hw.canDraw() && !isFrozen())) {
-        // repaint the framebuffer (if needed)
 
+#ifdef USE_COMPOSITION_BYPASS
+        if (handleBypassLayer()) {
+            unlockClients();
+            return true;
+        }
+#endif
+
+        // repaint the framebuffer (if needed)
         const int index = hw.getCurrentBufferIndex();
         GraphicLog& logger(GraphicLog::getInstance());
 
@@ -385,22 +396,32 @@
         logger.log(GraphicLog::SF_COMPOSITION_COMPLETE, index);
         hw.compositionComplete();
 
-        // release the clients before we flip ('cause flip might block)
-        logger.log(GraphicLog::SF_UNLOCK_CLIENTS, index);
-        unlockClients();
-
         logger.log(GraphicLog::SF_SWAP_BUFFERS, index);
         postFramebuffer();
 
         logger.log(GraphicLog::SF_REPAINT_DONE, index);
     } else {
         // pretend we did the post
-        unlockClients();
+        hw.compositionComplete();
         usleep(16667); // 60 fps period
     }
     return true;
 }
 
+bool SurfaceFlinger::handleBypassLayer()
+{
+    sp<Layer> bypassLayer(mBypassLayer.promote());
+    if (bypassLayer != 0) {
+        sp<GraphicBuffer> buffer(bypassLayer->getBypassBuffer());
+        if (buffer!=0 && (buffer->usage & GRALLOC_USAGE_HW_FB)) {
+            const DisplayHardware& hw(graphicPlane(0).displayHardware());
+            hw.postBypassBuffer(buffer->handle);
+            return true;
+        }
+    }
+    return false;
+}
+
 void SurfaceFlinger::postFramebuffer()
 {
     if (!mInvalidRegion.isEmpty()) {
@@ -696,6 +717,32 @@
     mTransactionCV.broadcast();
 }
 
+void SurfaceFlinger::setBypassLayer(const sp<LayerBase>& layer)
+{
+    // if this layer is already the bypass layer, do nothing
+    sp<Layer> cur(mBypassLayer.promote());
+    if (mBypassLayer == layer) {
+        if (cur != NULL) {
+            cur->updateBuffersOrientation();
+        }
+        return;
+    }
+
+    // clear the current bypass layer
+    mBypassLayer.clear();
+    if (cur != 0) {
+        cur->setBypass(false);
+        cur.clear();
+    }
+
+    // set new bypass layer
+    if (layer != 0) {
+        if (layer->setBypass(true)) {
+            mBypassLayer = static_cast<Layer*>(layer.get());
+        }
+    }
+}
+
 void SurfaceFlinger::handlePageFlip()
 {
     bool visibleRegions = mVisibleRegionsDirty;
@@ -721,6 +768,21 @@
                     mVisibleLayersSortedByZ.add(currentLayers[i]);
             }
 
+#ifdef USE_COMPOSITION_BYPASS
+            sp<LayerBase> bypassLayer;
+            const size_t numVisibleLayers = mVisibleLayersSortedByZ.size();
+            if (numVisibleLayers == 1) {
+                const sp<LayerBase>& candidate(mVisibleLayersSortedByZ[0]);
+                const Region& visibleRegion(candidate->visibleRegionScreen);
+                const Region reminder(screenRegion.subtract(visibleRegion));
+                if (reminder.isEmpty()) {
+                    // fullscreen candidate!
+                    bypassLayer = candidate;
+                }
+            }
+            setBypassLayer(bypassLayer);
+#endif
+
             mWormholeRegion = screenRegion.subtract(opaqueRegion);
             mVisibleRegionsDirty = false;
         }
@@ -828,17 +890,6 @@
     }
 }
 
-void SurfaceFlinger::unlockClients()
-{
-    const LayerVector& drawingLayers(mDrawingState.layersSortedByZ);
-    const size_t count = drawingLayers.size();
-    sp<LayerBase> const* const layers = drawingLayers.array();
-    for (size_t i=0 ; i<count ; ++i) {
-        const sp<LayerBase>& layer = layers[i];
-        layer->finishPageFlip();
-    }
-}
-
 void SurfaceFlinger::debugFlashRegions()
 {
     const DisplayHardware& hw(graphicPlane(0).displayHardware());
@@ -1416,9 +1467,9 @@
         mWormholeRegion.dump(result, "WormholeRegion");
         const DisplayHardware& hw(graphicPlane(0).displayHardware());
         snprintf(buffer, SIZE,
-                "  display frozen: %s, freezeCount=%d, orientation=%d, canDraw=%d\n",
+                "  display frozen: %s, freezeCount=%d, orientation=%d, bypass=%p, canDraw=%d\n",
                 mFreezeDisplay?"yes":"no", mFreezeCount,
-                mCurrentState.orientation, hw.canDraw());
+                mCurrentState.orientation, mBypassLayer.unsafe_get(), hw.canDraw());
         result.append(buffer);
         snprintf(buffer, SIZE,
                 "  last eglSwapBuffers() time: %f us\n"
@@ -2047,6 +2098,7 @@
 
         // invert everything, b/c glReadPixel() below will invert the FB
         glViewport(0, 0, sw, sh);
+        glScissor(0, 0, sw, sh);
         glMatrixMode(GL_PROJECTION);
         glPushMatrix();
         glLoadIdentity();
@@ -2056,6 +2108,7 @@
         // redraw the screen entirely...
         glClearColor(0,0,0,1);
         glClear(GL_COLOR_BUFFER_BIT);
+
         const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ);
         const size_t count = layers.size();
         for (size_t i=0 ; i<count ; ++i) {
@@ -2090,7 +2143,6 @@
                 result = NO_MEMORY;
             }
         }
-
         glEnable(GL_SCISSOR_TEST);
         glViewport(0, 0, hw_w, hw_h);
         glMatrixMode(GL_PROJECTION);
@@ -2106,6 +2158,9 @@
     glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
     glDeleteRenderbuffersOES(1, &tname);
     glDeleteFramebuffersOES(1, &name);
+
+    hw.compositionComplete();
+
     return result;
 }
 
@@ -2329,7 +2384,7 @@
             }
             break;
         }
-        if (++name > 31)
+        if (++name >= SharedBufferStack::NUM_LAYERS_MAX)
             name = NO_MEMORY;
     } while(name >= 0);
 
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 4262175..df1ca48 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -307,9 +307,9 @@
             bool        lockPageFlip(const LayerVector& currentLayers);
             void        unlockPageFlip(const LayerVector& currentLayers);
             void        handleRepaint();
+            bool        handleBypassLayer();
             void        postFramebuffer();
             void        composeSurfaces(const Region& dirty);
-            void        unlockClients();
 
 
             ssize_t     addClientLayer(const sp<Client>& client,
@@ -322,6 +322,7 @@
             uint32_t    setTransactionFlags(uint32_t flags);
             void        commitTransaction();
 
+            void        setBypassLayer(const sp<LayerBase>& layer);
 
             status_t captureScreenImplLocked(DisplayID dpy,
                     sp<IMemoryHeap>* heap,
@@ -399,6 +400,7 @@
                 int32_t                     mFreezeCount;
                 nsecs_t                     mFreezeDisplayTime;
                 Vector< sp<LayerBase> >     mVisibleLayersSortedByZ;
+                wp<Layer>                   mBypassLayer;
 
 
                 // don't use a lock for these, we don't care
diff --git a/services/surfaceflinger/TextureManager.cpp b/services/surfaceflinger/TextureManager.cpp
index c9a15f5..9e24f90d 100644
--- a/services/surfaceflinger/TextureManager.cpp
+++ b/services/surfaceflinger/TextureManager.cpp
@@ -186,7 +186,7 @@
     if (texture->name == -1UL) {
         status_t err = initTexture(texture);
         LOGE_IF(err, "loadTexture failed in initTexture (%s)", strerror(err));
-        return err;
+        if (err != NO_ERROR) return err;
     }
 
     if (texture->target != Texture::TEXTURE_2D)