Merge "Add a battery capacity value to the power profile."
diff --git a/camera/tests/CameraServiceTest/Android.mk b/camera/tests/CameraServiceTest/Android.mk
index 9bb190a..cf4e42f 100644
--- a/camera/tests/CameraServiceTest/Android.mk
+++ b/camera/tests/CameraServiceTest/Android.mk
@@ -21,4 +21,6 @@
                 libcamera_client \
                 libsurfaceflinger_client
 
-include $(BUILD_EXECUTABLE)
+# Disable it because the ISurface interface may change, and before we have a
+# chance to fix this test, we don't want to break normal builds.
+#include $(BUILD_EXECUTABLE)
diff --git a/include/private/surfaceflinger/SharedBufferStack.h b/include/private/surfaceflinger/SharedBufferStack.h
index a1a02e0..b859e78 100644
--- a/include/private/surfaceflinger/SharedBufferStack.h
+++ b/include/private/surfaceflinger/SharedBufferStack.h
@@ -55,12 +55,6 @@
  * 
  */
 
-// When changing these values, the COMPILE_TIME_ASSERT at the end of this
-// file need to be updated.
-const unsigned int NUM_LAYERS_MAX  = 31;
-const unsigned int NUM_BUFFER_MAX  = 16;
-const unsigned int NUM_DISPLAY_MAX = 4;
-
 // ----------------------------------------------------------------------------
 
 class Region;
@@ -82,6 +76,13 @@
     friend class SharedBufferServer;
 
 public:
+    // When changing these values, the COMPILE_TIME_ASSERT at the end of this
+    // file need to be updated.
+    static const unsigned int NUM_LAYERS_MAX  = 31;
+    static const unsigned int NUM_BUFFER_MAX  = 16;
+    static const unsigned int NUM_BUFFER_MIN  = 2;
+    static const unsigned int NUM_DISPLAY_MAX = 4;
+
     struct Statistics { // 4 longs
         typedef int32_t usecs_t;
         usecs_t  totalTime;
@@ -147,7 +148,7 @@
     // FIXME: this should be replaced by a lock-less primitive
     Mutex lock;
     Condition cv;
-    SharedBufferStack surfaces[ NUM_LAYERS_MAX ];
+    SharedBufferStack surfaces[ SharedBufferStack::NUM_LAYERS_MAX ];
 };
 
 // ============================================================================
@@ -155,10 +156,9 @@
 class SharedBufferBase
 {
 public:
-    SharedBufferBase(SharedClient* sharedClient, int surface, int num,
+    SharedBufferBase(SharedClient* sharedClient, int surface,
             int32_t identity);
     ~SharedBufferBase();
-    uint32_t getIdentity();
     status_t getStatus() const;
     size_t getFrontBuffer() const;
     String8 dump(char const* prefix) const;
@@ -166,9 +166,7 @@
 protected:
     SharedClient* const mSharedClient;
     SharedBufferStack* const mSharedStack;
-    int mNumBuffers;
     const int mIdentity;
-    int32_t computeTail() const;
 
     friend struct Update;
     friend struct QueueUpdate;
@@ -217,8 +215,16 @@
     bool needNewBuffer(int buffer) const;
     status_t setDirtyRegion(int buffer, const Region& reg);
     status_t setCrop(int buffer, const Rect& reg);
-    status_t setBufferCount(int bufferCount);
     
+
+    class SetBufferCountCallback {
+        friend class SharedBufferClient;
+        virtual status_t operator()(int bufferCount) const = 0;
+    protected:
+        virtual ~SetBufferCountCallback() { }
+    };
+    status_t setBufferCount(int bufferCount, const SetBufferCountCallback& ipc);
+
 private:
     friend struct Condition;
     friend struct DequeueCondition;
@@ -249,11 +255,16 @@
         inline const char* name() const { return "LockCondition"; }
     };
 
+    int32_t computeTail() const;
+
+    mutable RWLock mLock;
+    int mNumBuffers;
+
     int32_t tail;
     int32_t undoDequeueTail;
     int32_t queued_head;
     // statistics...
-    nsecs_t mDequeueTime[NUM_BUFFER_MAX];
+    nsecs_t mDequeueTime[SharedBufferStack::NUM_BUFFER_MAX];
 };
 
 // ----------------------------------------------------------------------------
@@ -267,7 +278,8 @@
     ssize_t retireAndLock();
     status_t unlock(int buffer);
     void setStatus(status_t status);
-    status_t reallocate();
+    status_t reallocateAll();
+    status_t reallocateAllExcept(int buffer);
     status_t assertReallocate(int buffer);
     int32_t getQueuedCount() const;
     Region getDirtyRegion(int buffer) const;
@@ -287,9 +299,11 @@
         size_t mCapacity;
         uint32_t mList;
     public:
-        BufferList(size_t c = NUM_BUFFER_MAX) : mCapacity(c), mList(0) { }
+        BufferList(size_t c = SharedBufferStack::NUM_BUFFER_MAX)
+            : mCapacity(c), mList(0) { }
         status_t add(int value);
         status_t remove(int value);
+        uint32_t getMask() const { return mList; }
 
         class const_iterator {
             friend class BufferList;
@@ -324,6 +338,9 @@
         }
     };
 
+    // this protects mNumBuffers and mBufferList
+    mutable RWLock mLock;
+    int mNumBuffers;
     BufferList mBufferList;
 
     struct UnlockUpdate : public UpdateBase {
@@ -373,7 +390,7 @@
     uint8_t         connected;
     uint8_t         reserved[3];
     uint32_t        pad[7];
-    display_cblk_t  displays[NUM_DISPLAY_MAX];
+    display_cblk_t  displays[SharedBufferStack::NUM_DISPLAY_MAX];
 };
 
 // ---------------------------------------------------------------------------
diff --git a/include/surfaceflinger/ISurface.h b/include/surfaceflinger/ISurface.h
index 9476686..18e7950 100644
--- a/include/surfaceflinger/ISurface.h
+++ b/include/surfaceflinger/ISurface.h
@@ -53,7 +53,8 @@
 public: 
     DECLARE_META_INTERFACE(Surface);
 
-    virtual sp<GraphicBuffer> requestBuffer(int bufferIdx, int usage) = 0; 
+    virtual sp<GraphicBuffer> requestBuffer(int bufferIdx,
+            uint32_t w, uint32_t h, uint32_t format, uint32_t usage) = 0;
     virtual status_t setBufferCount(int bufferCount) = 0;
     
     class BufferHeap {
diff --git a/include/surfaceflinger/Surface.h b/include/surfaceflinger/Surface.h
index 973780f..e561fb9 100644
--- a/include/surfaceflinger/Surface.h
+++ b/include/surfaceflinger/Surface.h
@@ -36,6 +36,7 @@
 
 // ---------------------------------------------------------------------------
 
+class GraphicBuffer;
 class GraphicBufferMapper;
 class IOMX;
 class Rect;
@@ -212,30 +213,55 @@
     int  dispatch_connect(va_list args);
     int  dispatch_disconnect(va_list args);
     int  dispatch_crop(va_list args);
+    int  dispatch_set_buffer_count(va_list args);
+    int  dispatch_set_buffers_geometry(va_list args);
     
     void setUsage(uint32_t reqUsage);
     int  connect(int api);
     int  disconnect(int api);
     int  crop(Rect const* rect);
     int  setBufferCount(int bufferCount);
+    int  setBuffersGeometry(int w, int h, int format);
 
     /*
      *  private stuff...
      */
     void init();
     status_t validate() const;
-    sp<SurfaceComposerClient> getClient() const;
+    status_t initCheck() const;
     sp<ISurface> getISurface() const;
 
     inline const GraphicBufferMapper& getBufferMapper() const { return mBufferMapper; }
     inline GraphicBufferMapper& getBufferMapper() { return mBufferMapper; }
 
-    status_t getBufferLocked(int index, int usage);
+    status_t getBufferLocked(int index,
+            uint32_t w, uint32_t h, uint32_t format, uint32_t usage);
     int getBufferIndex(const sp<GraphicBuffer>& buffer) const;
 
-    uint32_t getUsage() const;
-    int      getConnectedApi() const;
+    int getConnectedApi() const;
     
+    bool needNewBuffer(int bufIdx,
+            uint32_t *pWidth, uint32_t *pHeight,
+            uint32_t *pFormat, uint32_t *pUsage) const;
+
+    class BufferInfo {
+        uint32_t mWidth;
+        uint32_t mHeight;
+        uint32_t mFormat;
+        uint32_t mUsage;
+        mutable uint32_t mDirty;
+        enum {
+            GEOMETRY = 0x01
+        };
+    public:
+        BufferInfo();
+        void set(uint32_t w, uint32_t h, uint32_t format);
+        void set(uint32_t usage);
+        void get(uint32_t *pWidth, uint32_t *pHeight,
+                uint32_t *pFormat, uint32_t *pUsage) const;
+        bool validateBuffer(const sp<GraphicBuffer>& buffer) const;
+    };
+
     // constants
     sp<SurfaceComposerClient>   mClient;
     sp<ISurface>                mSurface;
@@ -245,16 +271,16 @@
     uint32_t                    mFlags;
     GraphicBufferMapper&        mBufferMapper;
     SharedBufferClient*         mSharedBufferClient;
+    status_t                    mInitCheck;
 
     // protected by mSurfaceLock
     Rect                        mSwapRectangle;
-    uint32_t                    mUsage;
     int                         mConnected;
     Rect                        mNextBufferCrop;
+    BufferInfo                  mBufferInfo;
     
     // protected by mSurfaceLock. These are also used from lock/unlock
     // but in that case, they must be called form the same thread.
-    sp<GraphicBuffer>           mBuffers[2];
     mutable Region              mDirtyRegion;
 
     // must be used from the lock/unlock thread
@@ -263,6 +289,9 @@
     mutable Region              mOldDirtyRegion;
     bool                        mReserved;
 
+    // only used from dequeueBuffer()
+    Vector< sp<GraphicBuffer> > mBuffers;
+
     // query() must be called from dequeueBuffer() thread
     uint32_t                    mWidth;
     uint32_t                    mHeight;
diff --git a/include/surfaceflinger/SurfaceComposerClient.h b/include/surfaceflinger/SurfaceComposerClient.h
index 9d0f0cb..8396038 100644
--- a/include/surfaceflinger/SurfaceComposerClient.h
+++ b/include/surfaceflinger/SurfaceComposerClient.h
@@ -123,13 +123,6 @@
     status_t linkToComposerDeath(const sp<IBinder::DeathRecipient>& recipient,
             void* cookie = NULL, uint32_t flags = 0);
 
-private:
-    friend class Surface;
-    friend class SurfaceControl;
-    
-    SurfaceComposerClient(const sp<ISurfaceComposer>& sm, 
-            const sp<IBinder>& conn);
-
     status_t    hide(SurfaceID id);
     status_t    show(SurfaceID id, int32_t layer = -1);
     status_t    freeze(SurfaceID id);
@@ -142,17 +135,21 @@
     status_t    setMatrix(SurfaceID id, float dsdx, float dtdx, float dsdy, float dtdy);
     status_t    setPosition(SurfaceID id, int32_t x, int32_t y);
     status_t    setSize(SurfaceID id, uint32_t w, uint32_t h);
-    
     void        signalServer();
-
     status_t    destroySurface(SurfaceID sid);
 
-    void        _init(const sp<ISurfaceComposer>& sm,
+    SharedClient*   getSharedClient() const;
+
+private:
+    SurfaceComposerClient(const sp<ISurfaceComposer>& sm,
+            const sp<IBinder>& conn);
+
+    void        init(const sp<ISurfaceComposer>& sm,
                     const sp<ISurfaceFlingerClient>& conn);
 
-    inline layer_state_t*   _get_state_l(SurfaceID id);
-    layer_state_t*          _lockLayerState(SurfaceID id);
-    inline void             _unlockLayerState();
+    inline layer_state_t*   get_state_l(SurfaceID id);
+    layer_state_t*          lockLayerState(SurfaceID id);
+    inline void             unlockLayerState();
 
     mutable     Mutex                               mLock;
                 layer_state_t*                      mPrebuiltLayerState;
diff --git a/include/ui/egl/android_natives.h b/include/ui/egl/android_natives.h
index 49bfa2b..171f3df 100644
--- a/include/ui/egl/android_natives.h
+++ b/include/ui/egl/android_natives.h
@@ -81,6 +81,8 @@
     NATIVE_WINDOW_CONNECT,
     NATIVE_WINDOW_DISCONNECT,
     NATIVE_WINDOW_SET_CROP,
+    NATIVE_WINDOW_SET_BUFFER_COUNT,
+    NATIVE_WINDOW_SET_BUFFERS_GEOMETRY,
 };
 
 /* parameter for NATIVE_WINDOW_[DIS]CONNECT */
@@ -190,6 +192,8 @@
      *     NATIVE_WINDOW_CONNECT
      *     NATIVE_WINDOW_DISCONNECT
      *     NATIVE_WINDOW_SET_CROP
+     *     NATIVE_WINDOW_SET_BUFFER_COUNT
+     *     NATIVE_WINDOW_SET_BUFFERS_GEOMETRY
      *  
      */
     
@@ -201,8 +205,9 @@
 
 
 /*
- *  native_window_set_usage() sets the intended usage flags for the next
- *  buffers acquired with (*lockBuffer)() and on.
+ *  native_window_set_usage(..., usage)
+ *  Sets the intended usage flags for the next buffers
+ *  acquired with (*lockBuffer)() and on.
  *  By default (if this function is never called), a usage of
  *      GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE
  *  is assumed.
@@ -217,8 +222,8 @@
 }
 
 /*
- * native_window_connect(..., NATIVE_WINDOW_API_EGL) must be called
- * by EGL when the window is made current.
+ * native_window_connect(..., NATIVE_WINDOW_API_EGL)
+ * Must be called by EGL when the window is made current.
  * Returns -EINVAL if for some reason the window cannot be connected, which
  * can happen if it's connected to some other API.
  */
@@ -229,8 +234,8 @@
 }
 
 /*
- * native_window_disconnect(..., NATIVE_WINDOW_API_EGL) must be called
- * by EGL when the window is made not current.
+ * native_window_disconnect(..., NATIVE_WINDOW_API_EGL)
+ * Must be called by EGL when the window is made not current.
  * An error is returned if for instance the window wasn't connected in the
  * first place.
  */
@@ -241,8 +246,8 @@
 }
 
 /*
- * native_window_set_crop(..., crop) sets which region of the next queued
- * buffers needs to be considered.
+ * native_window_set_crop(..., crop)
+ * Sets which region of the next queued buffers needs to be considered.
  * A buffer's crop region is scaled to match the surface's size.
  *
  * The specified crop region applies to all buffers queued after it is called.
@@ -259,6 +264,36 @@
     return window->perform(window, NATIVE_WINDOW_SET_CROP, crop);
 }
 
+/*
+ * native_window_set_buffer_count(..., count)
+ * Sets the number of buffers associated with this native window.
+ */
+static inline int native_window_set_buffer_count(
+        android_native_window_t* window,
+        size_t bufferCount)
+{
+    return window->perform(window, NATIVE_WINDOW_SET_BUFFER_COUNT, bufferCount);
+}
+
+/*
+ * native_window_set_buffers_geometry(..., int w, int h, int format)
+ * All buffers dequeued after this call will have the geometry specified.
+ * In particular, all buffers will have a fixed-size, independent form the
+ * native-window size. They will be appropriately scaled to the window-size
+ * upon composition.
+ *
+ * If all parameters are 0, the normal behavior is restored. That is,
+ * dequeued buffers following this call will be sized to the window's size.
+ *
+ */
+static inline int native_window_set_buffers_geometry(
+        android_native_window_t* window,
+        int w, int h, int format)
+{
+    return window->perform(window, NATIVE_WINDOW_SET_BUFFERS_GEOMETRY,
+            w, h, format);
+}
+
 // ---------------------------------------------------------------------------
 
 /* FIXME: this is legacy for pixmaps */
diff --git a/libs/audioflinger/AudioPolicyManagerBase.cpp b/libs/audioflinger/AudioPolicyManagerBase.cpp
index 381a958..549d661 100644
--- a/libs/audioflinger/AudioPolicyManagerBase.cpp
+++ b/libs/audioflinger/AudioPolicyManagerBase.cpp
@@ -902,7 +902,8 @@
 #ifdef AUDIO_POLICY_TEST
     Thread(false),
 #endif //AUDIO_POLICY_TEST
-    mPhoneState(AudioSystem::MODE_NORMAL), mRingerMode(0), mMusicStopTime(0), mLimitRingtoneVolume(false)
+    mPhoneState(AudioSystem::MODE_NORMAL), mRingerMode(0), mMusicStopTime(0), mLimitRingtoneVolume(false),
+    mLastVoiceVolume(-1.0f)
 {
     mpClientInterface = clientInterface;
 
@@ -1713,29 +1714,38 @@
     }
 
     float volume = computeVolume(stream, index, output, device);
-    // do not set volume if the float value did not change
-    if (volume != mOutputs.valueFor(output)->mCurVolume[stream] || force) {
+    // We actually change the volume if:
+    // - the float value returned by computeVolume() changed
+    // - the force flag is set
+    if (volume != mOutputs.valueFor(output)->mCurVolume[stream] ||
+            force) {
         mOutputs.valueFor(output)->mCurVolume[stream] = volume;
         LOGV("setStreamVolume() for output %d stream %d, volume %f, delay %d", output, stream, volume, delayMs);
         if (stream == AudioSystem::VOICE_CALL ||
             stream == AudioSystem::DTMF ||
             stream == AudioSystem::BLUETOOTH_SCO) {
-            float voiceVolume = -1.0;
             // offset value to reflect actual hardware volume that never reaches 0
             // 1% corresponds roughly to first step in VOICE_CALL stream volume setting (see AudioService.java)
             volume = 0.01 + 0.99 * volume;
-            if (stream == AudioSystem::VOICE_CALL) {
-                voiceVolume = (float)index/(float)mStreams[stream].mIndexMax;
-            } else if (stream == AudioSystem::BLUETOOTH_SCO) {
-                voiceVolume = 1.0;
-            }
-            if (voiceVolume >= 0 && output == mHardwareOutput) {
-                mpClientInterface->setVoiceVolume(voiceVolume, delayMs);
-            }
         }
         mpClientInterface->setStreamVolume((AudioSystem::stream_type)stream, volume, output, delayMs);
     }
 
+    if (stream == AudioSystem::VOICE_CALL ||
+        stream == AudioSystem::BLUETOOTH_SCO) {
+        float voiceVolume;
+        // Force voice volume to max for bluetooth SCO as volume is managed by the headset
+        if (stream == AudioSystem::VOICE_CALL) {
+            voiceVolume = (float)index/(float)mStreams[stream].mIndexMax;
+        } else {
+            voiceVolume = 1.0;
+        }
+        if (voiceVolume != mLastVoiceVolume && output == mHardwareOutput) {
+            mpClientInterface->setVoiceVolume(voiceVolume, delayMs);
+            mLastVoiceVolume = voiceVolume;
+        }
+    }
+
     return NO_ERROR;
 }
 
diff --git a/libs/surfaceflinger/Barrier.h b/libs/surfaceflinger/Barrier.h
index e2bcf6a..6f8507e 100644
--- a/libs/surfaceflinger/Barrier.h
+++ b/libs/surfaceflinger/Barrier.h
@@ -29,10 +29,6 @@
     inline Barrier() : state(CLOSED) { }
     inline ~Barrier() { }
     void open() {
-        // gcc memory barrier, this makes sure all memory writes
-        // have been issued by gcc. On an SMP system we'd need a real
-        // h/w barrier.
-        asm volatile ("":::"memory");
         Mutex::Autolock _l(lock);
         state = OPENED;
         cv.broadcast();
diff --git a/libs/surfaceflinger/Layer.cpp b/libs/surfaceflinger/Layer.cpp
index 1fe997d..3fbb4d3 100644
--- a/libs/surfaceflinger/Layer.cpp
+++ b/libs/surfaceflinger/Layer.cpp
@@ -55,12 +55,13 @@
         mNeedsBlending(true),
         mNeedsDithering(false),
         mTextureManager(mFlags),
-        mBufferManager(mTextureManager)
+        mBufferManager(mTextureManager),
+        mWidth(0), mHeight(0), mFixedSize(false)
 {
     // no OpenGL operation is possible here, since we might not be
     // in the OpenGL thread.
     lcblk = new SharedBufferServer(
-            client->ctrlblk, i, mBufferManager.getBufferCount(),
+            client->ctrlblk, i, mBufferManager.getDefaultBufferCount(),
             getIdentity());
 
    mBufferManager.setActiveBufferIndex( lcblk->getFrontBuffer() );
@@ -68,7 +69,10 @@
 
 Layer::~Layer()
 {
-    destroy();
+    // FIXME: must be called from the main UI thread
+    EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay());
+    mBufferManager.destroy(dpy);
+
     // the actual buffers will be destroyed here
     delete lcblk;
 }
@@ -81,17 +85,6 @@
     lcblk->setStatus(NO_INIT);
 }
 
-void Layer::destroy()
-{
-    EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay());
-    mBufferManager.destroy(dpy);
-
-    mSurface.clear();
-
-    Mutex::Autolock _l(mLock);
-    mWidth = mHeight = 0;
-}
-
 sp<LayerBaseClient::Surface> Layer::createSurface() const
 {
     return mSurface;
@@ -99,9 +92,17 @@
 
 status_t Layer::ditch()
 {
+    // NOTE: Called from the main UI thread
+
     // the layer is not on screen anymore. free as much resources as possible
     mFreezeLock.clear();
-    destroy();
+
+    EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay());
+    mBufferManager.destroy(dpy);
+    mSurface.clear();
+
+    Mutex::Autolock _l(mLock);
+    mWidth = mHeight = 0;
     return NO_ERROR;
 }
 
@@ -208,10 +209,23 @@
     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)
+            return true;
+    }
+    return LayerBase::needsFiltering();
+}
+
 
 status_t Layer::setBufferCount(int bufferCount)
 {
-    // this ensures our client doesn't go away while we're accessing
+    // Ensures our client doesn't go away while we're accessing
     // the shared area.
     sp<Client> ourClient(client.promote());
     if (ourClient == 0) {
@@ -219,23 +233,26 @@
         return DEAD_OBJECT;
     }
 
-    status_t err;
-
-    // FIXME: resize() below is NOT thread-safe, we need to synchronize
-    // the users of lcblk in our process (ie: retire), and we assume the
-    // client is not mucking with the SharedStack, which is only enforced
-    // by construction, therefore we need to protect ourselves against
-    // buggy and malicious client (as always)
-
-    err = lcblk->resize(bufferCount);
+    // NOTE: lcblk->resize() is protected by an internal lock
+    status_t err = lcblk->resize(bufferCount);
+    if (err == NO_ERROR)
+        mBufferManager.resize(bufferCount);
 
     return err;
 }
 
-sp<GraphicBuffer> Layer::requestBuffer(int index, int usage)
+sp<GraphicBuffer> Layer::requestBuffer(int index,
+        uint32_t reqWidth, uint32_t reqHeight, uint32_t reqFormat,
+        uint32_t usage)
 {
     sp<GraphicBuffer> buffer;
 
+    if ((reqWidth | reqHeight | reqFormat) < 0)
+        return buffer;
+
+    if ((!reqWidth && reqHeight) || (reqWidth && !reqHeight))
+        return buffer;
+
     // this ensures our client doesn't go away while we're accessing
     // the shared area.
     sp<Client> ourClient(client.promote());
@@ -248,7 +265,7 @@
      * This is called from the client's Surface::dequeue(). This can happen
      * at any time, especially while we're in the middle of using the
      * buffer 'index' as our front buffer.
-     * 
+     *
      * Make sure the buffer we're resizing is not the front buffer and has been
      * dequeued. Once this condition is asserted, we are guaranteed that this
      * buffer cannot become the front buffer under our feet, since we're called
@@ -261,23 +278,33 @@
         return buffer;
     }
 
-    uint32_t w, h;
+    uint32_t w, h, f;
     { // scope for the lock
         Mutex::Autolock _l(mLock);
-        w = mWidth;
-        h = mHeight;
+        const bool fixedSizeChanged = mFixedSize != (reqWidth && reqHeight);
+        const bool formatChanged    = mReqFormat != reqFormat;
+        mReqWidth  = reqWidth;
+        mReqHeight = reqHeight;
+        mReqFormat = reqFormat;
+        mFixedSize = reqWidth && reqHeight;
+        w = reqWidth  ? reqWidth  : mWidth;
+        h = reqHeight ? reqHeight : mHeight;
+        f = reqFormat ? reqFormat : mFormat;
         buffer = mBufferManager.detachBuffer(index);
+        if (fixedSizeChanged || formatChanged) {
+            lcblk->reallocateAllExcept(index);
+        }
     }
 
     const uint32_t effectiveUsage = getEffectiveUsage(usage);
     if (buffer!=0 && buffer->getStrongCount() == 1) {
-        err = buffer->reallocate(w, h, mFormat, effectiveUsage);
+        err = buffer->reallocate(w, h, f, effectiveUsage);
     } else {
         // here we have to reallocate a new buffer because we could have a
         // client in our process with a reference to it (eg: status bar),
         // and we can't release the handle under its feet.
         buffer.clear();
-        buffer = new GraphicBuffer(w, h, mFormat, effectiveUsage);
+        buffer = new GraphicBuffer(w, h, f, effectiveUsage);
         err = buffer->initCheck();
     }
 
@@ -293,12 +320,7 @@
 
     if (err == NO_ERROR && buffer->handle != 0) {
         Mutex::Autolock _l(mLock);
-        if (mWidth && mHeight) {
-            mBufferManager.attachBuffer(index, buffer);
-        } else {
-            // oops we got killed while we were allocating the buffer
-            buffer.clear();
-        }
+        mBufferManager.attachBuffer(index, buffer);
     }
     return buffer;
 }
@@ -335,39 +357,46 @@
     const Layer::State& front(drawingState());
     const Layer::State& temp(currentState());
 
-    if ((front.requested_w != temp.requested_w) || 
-        (front.requested_h != temp.requested_h)) {
+    const bool sizeChanged = (front.requested_w != temp.requested_w) ||
+            (front.requested_h != temp.requested_h);
+
+    if (sizeChanged) {
         // the size changed, we need to ask our client to request a new buffer
         LOGD_IF(DEBUG_RESIZE,
-                    "resize (layer=%p), requested (%dx%d), drawing (%d,%d)",
-                    this, 
-                    int(temp.requested_w), int(temp.requested_h),
-                    int(front.requested_w), int(front.requested_h));
+                "resize (layer=%p), requested (%dx%d), drawing (%d,%d)",
+                this,
+                int(temp.requested_w), int(temp.requested_h),
+                int(front.requested_w), int(front.requested_h));
 
-        // we're being resized and there is a freeze display request,
-        // acquire a freeze lock, so that the screen stays put
-        // until we've redrawn at the new size; this is to avoid
-        // glitches upon orientation changes.
-        if (mFlinger->hasFreezeRequest()) {
-            // if the surface is hidden, don't try to acquire the
-            // freeze lock, since hidden surfaces may never redraw
-            if (!(front.flags & ISurfaceComposer::eLayerHidden)) {
-                mFreezeLock = mFlinger->getFreezeLock();
+        if (!isFixedSize()) {
+            // we're being resized and there is a freeze display request,
+            // acquire a freeze lock, so that the screen stays put
+            // until we've redrawn at the new size; this is to avoid
+            // glitches upon orientation changes.
+            if (mFlinger->hasFreezeRequest()) {
+                // if the surface is hidden, don't try to acquire the
+                // freeze lock, since hidden surfaces may never redraw
+                if (!(front.flags & ISurfaceComposer::eLayerHidden)) {
+                    mFreezeLock = mFlinger->getFreezeLock();
+                }
             }
+
+            // this will make sure LayerBase::doTransaction doesn't update
+            // the drawing state's size
+            Layer::State& editDraw(mDrawingState);
+            editDraw.requested_w = temp.requested_w;
+            editDraw.requested_h = temp.requested_h;
+
+            // record the new size, form this point on, when the client request
+            // a buffer, it'll get the new size.
+            setBufferSize(temp.requested_w, temp.requested_h);
+
+            // all buffers need reallocation
+            lcblk->reallocateAll();
+        } else {
+            // record the new size
+            setBufferSize(temp.requested_w, temp.requested_h);
         }
-
-        // this will make sure LayerBase::doTransaction doesn't update
-        // the drawing state's size
-        Layer::State& editDraw(mDrawingState);
-        editDraw.requested_w = temp.requested_w;
-        editDraw.requested_h = temp.requested_h;
-
-        // record the new size, form this point on, when the client request a
-        // buffer, it'll get the new size.
-        setDrawingSize(temp.requested_w, temp.requested_h);
-
-        // all buffers need reallocation
-        lcblk->reallocate();
     }
 
     if (temp.sequence != front.sequence) {
@@ -381,12 +410,17 @@
     return LayerBase::doTransaction(flags);
 }
 
-void Layer::setDrawingSize(uint32_t w, uint32_t h) {
+void Layer::setBufferSize(uint32_t w, uint32_t h) {
     Mutex::Autolock _l(mLock);
     mWidth = w;
     mHeight = h;
 }
 
+bool Layer::isFixedSize() const {
+    Mutex::Autolock _l(mLock);
+    return mFixedSize;
+}
+
 // ----------------------------------------------------------------------------
 // pageflip handling...
 // ----------------------------------------------------------------------------
@@ -544,12 +578,20 @@
 // ---------------------------------------------------------------------------
 
 Layer::BufferManager::BufferManager(TextureManager& tm)
-    : mTextureManager(tm), mActiveBuffer(0), mFailover(false)
+    : mNumBuffers(NUM_BUFFERS), mTextureManager(tm),
+      mActiveBuffer(0), mFailover(false)
 {
 }
 
-size_t Layer::BufferManager::getBufferCount() const {
-    return NUM_BUFFERS;
+Layer::BufferManager::~BufferManager()
+{
+}
+
+status_t Layer::BufferManager::resize(size_t size)
+{
+    Mutex::Autolock _l(mLock);
+    mNumBuffers = size;
+    return NO_ERROR;
 }
 
 // only for debugging
@@ -568,51 +610,55 @@
 }
 
 Texture Layer::BufferManager::getActiveTexture() const {
-    return mFailover ? mFailoverTexture : mBufferData[mActiveBuffer].texture;
+    Texture res;
+    if (mFailover) {
+        res = mFailoverTexture;
+    } else {
+        static_cast<Image&>(res) = mBufferData[mActiveBuffer].texture;
+    }
+    return res;
 }
 
 sp<GraphicBuffer> Layer::BufferManager::getActiveBuffer() const {
+    const size_t activeBuffer = mActiveBuffer;
+    BufferData const * const buffers = mBufferData;
     Mutex::Autolock _l(mLock);
-    return mBufferData[mActiveBuffer].buffer;
+    return buffers[activeBuffer].buffer;
 }
 
 sp<GraphicBuffer> Layer::BufferManager::detachBuffer(size_t index)
 {
+    BufferData* const buffers = mBufferData;
     sp<GraphicBuffer> buffer;
     Mutex::Autolock _l(mLock);
-    buffer = mBufferData[index].buffer;
-    mBufferData[index].buffer = 0;
+    buffer = buffers[index].buffer;
+    buffers[index].buffer = 0;
     return buffer;
 }
 
 status_t Layer::BufferManager::attachBuffer(size_t index,
         const sp<GraphicBuffer>& buffer)
 {
+    BufferData* const buffers = mBufferData;
     Mutex::Autolock _l(mLock);
-    mBufferData[index].buffer = buffer;
-    mBufferData[index].texture.dirty = true;
-    return NO_ERROR;
-}
-
-status_t Layer::BufferManager::destroyTexture(Texture* tex, EGLDisplay dpy)
-{
-    if (tex->name != -1U) {
-        glDeleteTextures(1, &tex->name);
-        tex->name = -1U;
-    }
-    if (tex->image != EGL_NO_IMAGE_KHR) {
-        eglDestroyImageKHR(dpy, tex->image);
-        tex->image = EGL_NO_IMAGE_KHR;
-    }
+    buffers[index].buffer = buffer;
+    buffers[index].texture.dirty = true;
     return NO_ERROR;
 }
 
 status_t Layer::BufferManager::destroy(EGLDisplay dpy)
 {
-    Mutex::Autolock _l(mLock);
-    for (size_t i=0 ; i<NUM_BUFFERS ; i++) {
-        destroyTexture(&mBufferData[i].texture, dpy);
-        mBufferData[i].buffer = 0;
+    BufferData* const buffers = mBufferData;
+    size_t num;
+    { // scope for the lock
+        Mutex::Autolock _l(mLock);
+        num = mNumBuffers;
+        for (size_t i=0 ; i<num ; i++) {
+            buffers[i].buffer = 0;
+        }
+    }
+    for (size_t i=0 ; i<num ; i++) {
+        destroyTexture(&buffers[i].texture, dpy);
     }
     destroyTexture(&mFailoverTexture, dpy);
     return NO_ERROR;
@@ -622,7 +668,7 @@
         const sp<GraphicBuffer>& buffer)
 {
     size_t index = mActiveBuffer;
-    Texture& texture(mBufferData[index].texture);
+    Image& texture(mBufferData[index].texture);
     status_t err = mTextureManager.initEglImage(&texture, dpy, buffer);
     // if EGLImage fails, we switch to regular texture mode, and we
     // free all resources associated with using EGLImages.
@@ -631,7 +677,8 @@
         destroyTexture(&mFailoverTexture, dpy);
     } else {
         mFailover = true;
-        for (size_t i=0 ; i<NUM_BUFFERS ; i++) {
+        const size_t num = mNumBuffers;
+        for (size_t i=0 ; i<num ; i++) {
             destroyTexture(&mBufferData[i].texture, dpy);
         }
     }
@@ -644,6 +691,19 @@
     return mTextureManager.loadTexture(&mFailoverTexture, dirty, t);
 }
 
+status_t Layer::BufferManager::destroyTexture(Image* tex, EGLDisplay dpy)
+{
+    if (tex->name != -1U) {
+        glDeleteTextures(1, &tex->name);
+        tex->name = -1U;
+    }
+    if (tex->image != EGL_NO_IMAGE_KHR) {
+        eglDestroyImageKHR(dpy, tex->image);
+        tex->image = EGL_NO_IMAGE_KHR;
+    }
+    return NO_ERROR;
+}
+
 // ---------------------------------------------------------------------------
 
 Layer::SurfaceLayer::SurfaceLayer(const sp<SurfaceFlinger>& flinger,
@@ -656,12 +716,18 @@
 {
 }
 
-sp<GraphicBuffer> Layer::SurfaceLayer::requestBuffer(int index, int usage)
+sp<GraphicBuffer> Layer::SurfaceLayer::requestBuffer(int index,
+        uint32_t w, uint32_t h, uint32_t format, uint32_t usage)
 {
     sp<GraphicBuffer> buffer;
     sp<Layer> owner(getOwner());
     if (owner != 0) {
-        buffer = owner->requestBuffer(index, usage);
+        /*
+         * requestBuffer() cannot be called from the main thread
+         * as it could cause a dead-lock, since it may have to wait
+         * on conditions updated my the main thread.
+         */
+        buffer = owner->requestBuffer(index, w, h, format, usage);
     }
     return buffer;
 }
@@ -671,6 +737,11 @@
     status_t err = DEAD_OBJECT;
     sp<Layer> owner(getOwner());
     if (owner != 0) {
+        /*
+         * setBufferCount() cannot be called from the main thread
+         * as it could cause a dead-lock, since it may have to wait
+         * on conditions updated my the main thread.
+         */
         err = owner->setBufferCount(bufferCount);
     }
     return err;
diff --git a/libs/surfaceflinger/Layer.h b/libs/surfaceflinger/Layer.h
index 80fbd6a..59603a5 100644
--- a/libs/surfaceflinger/Layer.h
+++ b/libs/surfaceflinger/Layer.h
@@ -57,7 +57,8 @@
     status_t setBuffers(uint32_t w, uint32_t h, 
             PixelFormat format, uint32_t flags=0);
 
-    void setDrawingSize(uint32_t w, uint32_t h);
+    void setBufferSize(uint32_t w, uint32_t h);
+    bool isFixedSize() const;
 
     virtual void onDraw(const Region& clip) const;
     virtual uint32_t doTransaction(uint32_t transactionFlags);
@@ -66,6 +67,7 @@
     virtual void finishPageFlip();
     virtual bool needsBlending() const      { return mNeedsBlending; }
     virtual bool needsDithering() const     { return mNeedsDithering; }
+    virtual bool needsFiltering() const;
     virtual bool isSecure() const           { return mSecure; }
     virtual sp<Surface> createSurface() const;
     virtual status_t ditch();
@@ -88,9 +90,9 @@
 
     uint32_t getEffectiveUsage(uint32_t usage) const;
 
-    sp<GraphicBuffer> requestBuffer(int index, int usage);
+    sp<GraphicBuffer> requestBuffer(int bufferIdx,
+            uint32_t w, uint32_t h, uint32_t format, uint32_t usage);
     status_t setBufferCount(int bufferCount);
-    void destroy();
 
     class SurfaceLayer : public LayerBaseClient::Surface {
     public:
@@ -98,7 +100,8 @@
                 SurfaceID id, const sp<Layer>& owner);
         ~SurfaceLayer();
     private:
-        virtual sp<GraphicBuffer> requestBuffer(int index, int usage);
+        virtual sp<GraphicBuffer> requestBuffer(int bufferIdx,
+                uint32_t w, uint32_t h, uint32_t format, uint32_t usage);
         virtual status_t setBufferCount(int bufferCount);
         sp<Layer> getOwner() const {
             return static_cast<Layer*>(Surface::getOwner().get());
@@ -120,25 +123,32 @@
                 static const size_t NUM_BUFFERS = 2;
                 struct BufferData {
                     sp<GraphicBuffer>   buffer;
-                    Texture             texture;
+                    Image               texture;
                 };
+                // this lock protect mBufferData[].buffer but since there
+                // is very little contention, we have only one like for
+                // the whole array, we also use it to protect mNumBuffers.
                 mutable Mutex mLock;
-                BufferData          mBufferData[NUM_BUFFERS];
+                BufferData          mBufferData[SharedBufferStack::NUM_BUFFER_MAX];
+                size_t              mNumBuffers;
                 Texture             mFailoverTexture;
                 TextureManager&     mTextureManager;
                 ssize_t             mActiveBuffer;
                 bool                mFailover;
-                static status_t destroyTexture(Texture* tex, EGLDisplay dpy);
+                static status_t destroyTexture(Image* tex, EGLDisplay dpy);
 
             public:
+                static size_t getDefaultBufferCount() { return NUM_BUFFERS; }
                 BufferManager(TextureManager& tm);
-
-                size_t getBufferCount() const;
+                ~BufferManager();
 
                 // detach/attach buffer from/to given index
                 sp<GraphicBuffer> detachBuffer(size_t index);
                 status_t attachBuffer(size_t index, const sp<GraphicBuffer>& buffer);
 
+                // resize the number of active buffers
+                status_t resize(size_t size);
+
                 // ----------------------------------------------
                 // must be called from GL thread
 
@@ -170,9 +180,15 @@
             TextureManager mTextureManager;
             BufferManager mBufferManager;
 
+            // this lock protects mWidth and mHeight which are accessed from
+            // the main thread and requestBuffer's binder transaction thread.
             mutable Mutex mLock;
             uint32_t    mWidth;
             uint32_t    mHeight;
+            uint32_t    mReqWidth;
+            uint32_t    mReqHeight;
+            uint32_t    mReqFormat;
+            bool        mFixedSize;
 };
 
 // ---------------------------------------------------------------------------
diff --git a/libs/surfaceflinger/LayerBase.cpp b/libs/surfaceflinger/LayerBase.cpp
index 63b9520..76733a9 100644
--- a/libs/surfaceflinger/LayerBase.cpp
+++ b/libs/surfaceflinger/LayerBase.cpp
@@ -42,8 +42,7 @@
 LayerBase::LayerBase(SurfaceFlinger* flinger, DisplayID display)
     : dpy(display), contentDirty(false),
       mFlinger(flinger),
-      mTransformed(false),
-      mUseLinearFiltering(false),
+      mNeedsFiltering(false),
       mOrientation(0),
       mLeft(0), mTop(0),
       mTransactionFlags(0),
@@ -214,13 +213,12 @@
         flags |= eVisibleRegion;
         this->contentDirty = true;
 
-        const bool linearFiltering = mUseLinearFiltering;
-        mUseLinearFiltering = false;
+        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)) {
-                mUseLinearFiltering = true;
+                mNeedsFiltering = true;
             }
         }
     }
@@ -260,7 +258,6 @@
     // cache a few things...
     mOrientation = tr.getOrientation();
     mTransformedBounds = tr.makeBounds(w, h);
-    mTransformed = transformed;
     mLeft = tr.tx();
     mTop  = tr.ty();
 }
@@ -341,13 +338,13 @@
     */
 }
 
-void LayerBase::clearWithOpenGL(const Region& clip, GLclampx red,
-                                GLclampx green, GLclampx blue,
-                                GLclampx alpha) const
+void LayerBase::clearWithOpenGL(const Region& clip, GLclampf red,
+                                GLclampf green, GLclampf blue,
+                                GLclampf alpha) const
 {
     const DisplayHardware& hw(graphicPlane(0).displayHardware());
     const uint32_t fbHeight = hw.getHeight();
-    glColor4x(red,green,blue,alpha);
+    glColor4f(red,green,blue,alpha);
     glDisable(GL_TEXTURE_2D);
     glDisable(GL_BLEND);
     glDisable(GL_DITHER);
@@ -466,7 +463,7 @@
     glBindTexture(GL_TEXTURE_2D, textureName);
     // TODO: reload the texture if needed
     // this is currently done in loadTexture() below
-    if (mUseLinearFiltering) {
+    if (needsFiltering()) {
         glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
         glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
     } else {
@@ -500,7 +497,7 @@
 
 // ---------------------------------------------------------------------------
 
-int32_t LayerBaseClient::sIdentity = 0;
+int32_t LayerBaseClient::sIdentity = 1;
 
 LayerBaseClient::LayerBaseClient(SurfaceFlinger* flinger, DisplayID display,
         const sp<Client>& client, int32_t i)
@@ -616,7 +613,8 @@
     return BnSurface::onTransact(code, data, reply, flags);
 }
 
-sp<GraphicBuffer> LayerBaseClient::Surface::requestBuffer(int index, int usage) 
+sp<GraphicBuffer> LayerBaseClient::Surface::requestBuffer(int bufferIdx,
+        uint32_t w, uint32_t h, uint32_t format, uint32_t usage)
 {
     return NULL; 
 }
diff --git a/libs/surfaceflinger/LayerBase.h b/libs/surfaceflinger/LayerBase.h
index 53b848f..a78424e 100644
--- a/libs/surfaceflinger/LayerBase.h
+++ b/libs/surfaceflinger/LayerBase.h
@@ -177,9 +177,9 @@
     virtual bool needsDithering() const { return false; }
 
     /**
-     * transformed -- true is this surface needs a to be transformed
+     * needsLinearFiltering - true if this surface needs filtering
      */
-    virtual bool transformed() const    { return mTransformed; }
+    virtual bool needsFiltering() const { return mNeedsFiltering; }
 
     /**
      * isSecure - true if this surface is secure, that is if it prevents
@@ -222,8 +222,8 @@
     const GraphicPlane& graphicPlane(int dpy) const;
           GraphicPlane& graphicPlane(int dpy);
 
-          void clearWithOpenGL(const Region& clip, GLclampx r, GLclampx g,
-                               GLclampx b, GLclampx alpha) const;
+          void clearWithOpenGL(const Region& clip, GLclampf r, GLclampf g,
+                               GLclampf b, GLclampf alpha) const;
           void clearWithOpenGL(const Region& clip) const;
           void drawWithOpenGL(const Region& clip, const Texture& texture) const;
           
@@ -231,8 +231,7 @@
                 uint32_t        mFlags;
 
                 // cached during validateVisibility()
-                bool            mTransformed;
-                bool            mUseLinearFiltering;
+                bool            mNeedsFiltering;
                 int32_t         mOrientation;
                 GLfloat         mVertices[4][2];
                 Rect            mTransformedBounds;
@@ -301,7 +300,8 @@
         sp<LayerBaseClient> getOwner() const;
 
     private:
-        virtual sp<GraphicBuffer> requestBuffer(int index, int usage);
+        virtual sp<GraphicBuffer> requestBuffer(int bufferIdx,
+                uint32_t w, uint32_t h, uint32_t format, uint32_t usage);
         virtual status_t setBufferCount(int bufferCount);
 
         virtual status_t registerBuffers(const ISurface::BufferHeap& buffers); 
diff --git a/libs/surfaceflinger/LayerBlur.cpp b/libs/surfaceflinger/LayerBlur.cpp
index 2d77876..09c90e8 100644
--- a/libs/surfaceflinger/LayerBlur.cpp
+++ b/libs/surfaceflinger/LayerBlur.cpp
@@ -95,7 +95,9 @@
                     mCacheDirty = false;
                 } else {
                     if (!mAutoRefreshPending) {
-                        mFlinger->signalDelayedEvent(ms2ns(500));
+                        mFlinger->postMessageAsync(
+                                new MessageBase(MessageQueue::INVALIDATE),
+                                ms2ns(500));
                         mAutoRefreshPending = true;
                     }
                 }
diff --git a/libs/surfaceflinger/LayerBuffer.cpp b/libs/surfaceflinger/LayerBuffer.cpp
index dfcc80f..8a582da 100644
--- a/libs/surfaceflinger/LayerBuffer.cpp
+++ b/libs/surfaceflinger/LayerBuffer.cpp
@@ -118,7 +118,7 @@
         source->onTransaction(flags);
     uint32_t res = LayerBase::doTransaction(flags);
     // we always want filtering for these surfaces
-    mUseLinearFiltering = !(mFlags & DisplayHardware::SLOW_CONFIG);
+    mNeedsFiltering = !(mFlags & DisplayHardware::SLOW_CONFIG);
     return res;
 }
 
@@ -143,14 +143,6 @@
     }
 }
 
-bool LayerBuffer::transformed() const
-{
-    sp<Source> source(getSource());
-    if (LIKELY(source != 0))
-        return source->transformed();
-    return false;
-}
-
 void LayerBuffer::serverDestroy()
 {
     sp<Source> source(clearSource());
@@ -319,9 +311,6 @@
 }
 void LayerBuffer::Source::unregisterBuffers() {
 }
-bool LayerBuffer::Source::transformed() const {
-    return mLayer.mTransformed; 
-}
 
 // ---------------------------------------------------------------------------
 
@@ -442,11 +431,6 @@
     mBuffer = buffer;
 }
 
-bool LayerBuffer::BufferSource::transformed() const
-{
-    return mBufferHeap.transform ? true : Source::transformed(); 
-}
-
 void LayerBuffer::BufferSource::onDraw(const Region& clip) const 
 {
     sp<Buffer> ourBuffer(getBuffer());
@@ -542,7 +526,7 @@
     // figure out if we need linear filtering
     if (buffers.w * h == buffers.h * w) {
         // same pixel area, don't use filtering
-        mLayer.mUseLinearFiltering = false;
+        mLayer.mNeedsFiltering = false;
     }
 
     // Allocate a temporary buffer and create the corresponding EGLImageKHR
@@ -638,9 +622,9 @@
 void LayerBuffer::OverlaySource::onDraw(const Region& clip) const
 {
     // this would be where the color-key would be set, should we need it.
-    GLclampx red = 0;
-    GLclampx green = 0;
-    GLclampx blue = 0;
+    GLclampf red = 0;
+    GLclampf green = 0;
+    GLclampf blue = 0;
     mLayer.clearWithOpenGL(clip, red, green, blue, 0);
 }
 
diff --git a/libs/surfaceflinger/LayerBuffer.h b/libs/surfaceflinger/LayerBuffer.h
index 869c74f..d38dde2 100644
--- a/libs/surfaceflinger/LayerBuffer.h
+++ b/libs/surfaceflinger/LayerBuffer.h
@@ -46,7 +46,6 @@
         virtual void onVisibilityResolved(const Transform& planeTransform);
         virtual void postBuffer(ssize_t offset);
         virtual void unregisterBuffers();
-        virtual bool transformed() const;
         virtual void destroy() { }
     protected:
         LayerBuffer& mLayer;
@@ -66,7 +65,6 @@
     virtual void onDraw(const Region& clip) const;
     virtual uint32_t doTransaction(uint32_t flags);
     virtual void unlockPageFlip(const Transform& planeTransform, Region& outDirtyRegion);
-    virtual bool transformed() const;
 
     status_t registerBuffers(const ISurface::BufferHeap& buffers);
     void postBuffer(ssize_t offset);
@@ -130,7 +128,6 @@
         virtual void onDraw(const Region& clip) const;
         virtual void postBuffer(ssize_t offset);
         virtual void unregisterBuffers();
-        virtual bool transformed() const;
         virtual void destroy() { }
     private:
         status_t initTempBuffer() const;
diff --git a/libs/surfaceflinger/MessageQueue.cpp b/libs/surfaceflinger/MessageQueue.cpp
index b43d801..d668e88 100644
--- a/libs/surfaceflinger/MessageQueue.cpp
+++ b/libs/surfaceflinger/MessageQueue.cpp
@@ -60,9 +60,9 @@
 {
 }
 
-MessageList::value_type MessageQueue::waitMessage(nsecs_t timeout)
+sp<MessageBase> MessageQueue::waitMessage(nsecs_t timeout)
 {
-    MessageList::value_type result;
+    sp<MessageBase> result;
 
     bool again;
     do {
@@ -132,6 +132,7 @@
         if (again) {
             // the message has been processed. release our reference to it
             // without holding the lock.
+            result->notify();
             result = 0;
         }
         
@@ -141,7 +142,7 @@
 }
 
 status_t MessageQueue::postMessage(
-        const MessageList::value_type& message, nsecs_t relTime, uint32_t flags)
+        const sp<MessageBase>& message, nsecs_t relTime, uint32_t flags)
 {
     return queueMessage(message, relTime, flags);
 }
@@ -154,7 +155,7 @@
 }
 
 status_t MessageQueue::queueMessage(
-        const MessageList::value_type& message, nsecs_t relTime, uint32_t flags)
+        const sp<MessageBase>& message, nsecs_t relTime, uint32_t flags)
 {
     Mutex::Autolock _l(mLock);
     message->when = systemTime() + relTime;
@@ -167,13 +168,13 @@
     return NO_ERROR;
 }
 
-void MessageQueue::dump(const MessageList::value_type& message)
+void MessageQueue::dump(const sp<MessageBase>& message)
 {
     Mutex::Autolock _l(mLock);
     dumpLocked(message);
 }
 
-void MessageQueue::dumpLocked(const MessageList::value_type& message)
+void MessageQueue::dumpLocked(const sp<MessageBase>& message)
 {
     LIST::const_iterator cur(mMessages.begin());
     LIST::const_iterator end(mMessages.end());
diff --git a/libs/surfaceflinger/MessageQueue.h b/libs/surfaceflinger/MessageQueue.h
index dc8138d..890f809 100644
--- a/libs/surfaceflinger/MessageQueue.h
+++ b/libs/surfaceflinger/MessageQueue.h
@@ -25,6 +25,7 @@
 #include <utils/Timers.h>
 #include <utils/List.h>
 
+#include "Barrier.h"
 
 namespace android {
 
@@ -37,7 +38,6 @@
     List< sp<MessageBase> > mList;
     typedef List< sp<MessageBase> > LIST;
 public:
-    typedef sp<MessageBase> value_type;
     inline LIST::iterator begin()                { return mList.begin(); }
     inline LIST::const_iterator begin() const    { return mList.begin(); }
     inline LIST::iterator end()                  { return mList.end(); }
@@ -63,11 +63,19 @@
     
     // return true if message has a handler
     virtual bool handler() { return false; }
+
+    // waits for the handler to be processed
+    void wait() const { barrier.wait(); }
     
+    // releases all waiters. this is done automatically if
+    // handler returns true
+    void notify() const { barrier.open(); }
+
 protected:
     virtual ~MessageBase() { }
 
 private:
+    mutable Barrier barrier;
     friend class LightRefBase<MessageBase>;
 };
 
@@ -82,42 +90,33 @@
     typedef List< sp<MessageBase> > LIST;
 public:
 
-    // this is a work-around the multichar constant warning. A macro would
-    // work too, but would pollute the namespace.
-    template <int a, int b, int c, int d>
-    struct WHAT {
-        static const uint32_t Value = 
-            (uint32_t(a&0xff)<<24)|(uint32_t(b&0xff)<<16)|
-            (uint32_t(c&0xff)<<8)|uint32_t(d&0xff);
-    };
-    
     MessageQueue();
     ~MessageQueue();
 
     // pre-defined messages
     enum {
-        INVALIDATE = WHAT<'_','p','d','t'>::Value
+        INVALIDATE = '_upd'
     };
 
-    MessageList::value_type waitMessage(nsecs_t timeout = -1);
+    sp<MessageBase> waitMessage(nsecs_t timeout = -1);
     
-    status_t postMessage(const MessageList::value_type& message, 
+    status_t postMessage(const sp<MessageBase>& message,
             nsecs_t reltime=0, uint32_t flags = 0);
-        
+
     status_t invalidate();
     
-    void dump(const MessageList::value_type& message);
+    void dump(const sp<MessageBase>& message);
 
 private:
-    status_t queueMessage(const MessageList::value_type& message,
+    status_t queueMessage(const sp<MessageBase>& message,
             nsecs_t reltime, uint32_t flags);
-    void dumpLocked(const MessageList::value_type& message);
+    void dumpLocked(const sp<MessageBase>& message);
     
     Mutex           mLock;
     Condition       mCondition;
     MessageList     mMessages;
     bool            mInvalidate;
-    MessageList::value_type mInvalidateMessage;
+    sp<MessageBase> mInvalidateMessage;
 };
 
 // ---------------------------------------------------------------------------
diff --git a/libs/surfaceflinger/SurfaceFlinger.cpp b/libs/surfaceflinger/SurfaceFlinger.cpp
index 62d829b..5a6893f 100644
--- a/libs/surfaceflinger/SurfaceFlinger.cpp
+++ b/libs/surfaceflinger/SurfaceFlinger.cpp
@@ -426,7 +426,7 @@
             timeout = waitTime>0 ? waitTime : 0;
         }
 
-        MessageList::value_type msg = mEventQueue.waitMessage(timeout);
+        sp<MessageBase> msg = mEventQueue.waitMessage(timeout);
 
         // see if we timed out
         if (isFrozen()) {
@@ -461,9 +461,20 @@
     const_cast<SurfaceFlinger*>(this)->signalEvent();
 }
 
-void SurfaceFlinger::signalDelayedEvent(nsecs_t delay)
+status_t SurfaceFlinger::postMessageAsync(const sp<MessageBase>& msg,
+        nsecs_t reltime, uint32_t flags)
 {
-    mEventQueue.postMessage( new MessageBase(MessageQueue::INVALIDATE), delay);
+    return mEventQueue.postMessage(msg, reltime, flags);
+}
+
+status_t SurfaceFlinger::postMessageSync(const sp<MessageBase>& msg,
+        nsecs_t reltime, uint32_t flags)
+{
+    status_t res = mEventQueue.postMessage(msg, reltime, flags);
+    if (res == NO_ERROR) {
+        msg->wait();
+    }
+    return res;
 }
 
 // ----------------------------------------------------------------------------
@@ -1135,15 +1146,11 @@
     return android_atomic_and(~flags, &mTransactionFlags) & flags;
 }
 
-uint32_t SurfaceFlinger::setTransactionFlags(uint32_t flags, nsecs_t delay)
+uint32_t SurfaceFlinger::setTransactionFlags(uint32_t flags)
 {
     uint32_t old = android_atomic_or(flags, &mTransactionFlags);
     if ((old & flags)==0) { // wake the server up
-        if (delay > 0) {
-            signalDelayedEvent(delay);
-        } else {
-            signalEvent();
-        }
+        signalEvent();
     }
     return old;
 }
@@ -1245,7 +1252,7 @@
 
     //LOGD("createSurface for pid %d (%d x %d)", pid, w, h);
     int32_t id = client->generateId(pid);
-    if (uint32_t(id) >= NUM_LAYERS_MAX) {
+    if (uint32_t(id) >= SharedBufferStack::NUM_LAYERS_MAX) {
         LOGE("createSurface() failed, generateId = %d", id);
         return surfaceHandle;
     }
@@ -1399,7 +1406,7 @@
         }
     };
 
-    mEventQueue.postMessage( new MessageDestroySurface(this, layer) );
+    postMessageAsync( new MessageDestroySurface(this, layer) );
     return NO_ERROR;
 }
 
@@ -1672,7 +1679,7 @@
 int32_t Client::generateId(int pid)
 {
     const uint32_t i = clz( ~mBitmap );
-    if (i >= NUM_LAYERS_MAX) {
+    if (i >= SharedBufferStack::NUM_LAYERS_MAX) {
         return NO_MEMORY;
     }
     mPid = pid;
@@ -1699,7 +1706,8 @@
 }
 
 bool Client::isValid(int32_t i) const {
-    return (uint32_t(i)<NUM_LAYERS_MAX) && (mBitmap & (1<<(31-i)));
+    return (uint32_t(i)<SharedBufferStack::NUM_LAYERS_MAX) &&
+            (mBitmap & (1<<(31-i)));
 }
 
 sp<LayerBaseClient> Client::getLayerUser(int32_t i) const {
diff --git a/libs/surfaceflinger/SurfaceFlinger.h b/libs/surfaceflinger/SurfaceFlinger.h
index 9c8de51..2558324 100644
--- a/libs/surfaceflinger/SurfaceFlinger.h
+++ b/libs/surfaceflinger/SurfaceFlinger.h
@@ -255,8 +255,6 @@
 public:     // hack to work around gcc 4.0.3 bug
             void        signalEvent();
 private:
-            void        signalDelayedEvent(nsecs_t delay);
-
             void        handleConsoleEvents();
             void        handleTransaction(uint32_t transactionFlags);
             void        handleTransactionLocked(
@@ -286,7 +284,7 @@
             void        free_resources_l();
 
             uint32_t    getTransactionFlags(uint32_t flags);
-            uint32_t    setTransactionFlags(uint32_t flags, nsecs_t delay = 0);
+            uint32_t    setTransactionFlags(uint32_t flags);
             void        commitTransaction();
 
 
@@ -310,7 +308,12 @@
            
 
     mutable     MessageQueue    mEventQueue;
-    
+
+    status_t postMessageAsync(const sp<MessageBase>& msg,
+            nsecs_t reltime=0, uint32_t flags = 0);
+
+    status_t postMessageSync(const sp<MessageBase>& msg,
+            nsecs_t reltime=0, uint32_t flags = 0);
                 
                 
                 // access must be protected by mStateLock
diff --git a/libs/surfaceflinger/TextureManager.cpp b/libs/surfaceflinger/TextureManager.cpp
index e5d5302..ee2159b 100644
--- a/libs/surfaceflinger/TextureManager.cpp
+++ b/libs/surfaceflinger/TextureManager.cpp
@@ -68,7 +68,7 @@
     return false;
 }
 
-status_t TextureManager::initEglImage(Texture* texture,
+status_t TextureManager::initEglImage(Image* texture,
         EGLDisplay dpy, const sp<GraphicBuffer>& buffer)
 {
     status_t err = NO_ERROR;
@@ -108,7 +108,6 @@
             err = INVALID_OPERATION;
         } else {
             // Everything went okay!
-            texture->NPOTAdjust = false;
             texture->dirty  = false;
             texture->width  = clientBuf->width;
             texture->height = clientBuf->height;
diff --git a/libs/surfaceflinger/TextureManager.h b/libs/surfaceflinger/TextureManager.h
index 90cb62b..d0acfe9 100644
--- a/libs/surfaceflinger/TextureManager.h
+++ b/libs/surfaceflinger/TextureManager.h
@@ -36,21 +36,24 @@
 
 // ---------------------------------------------------------------------------
 
-struct Texture {
-    Texture() : name(-1U), width(0), height(0),
-        image(EGL_NO_IMAGE_KHR), transform(0),
-        NPOTAdjust(false), dirty(true) { }
+struct Image {
+    Image() : name(-1U), image(EGL_NO_IMAGE_KHR), width(0), height(0),
+        transform(0), dirty(true) { }
     GLuint        name;
+    EGLImageKHR   image;
     GLuint        width;
     GLuint        height;
+    uint32_t      transform;
+    bool          dirty;
+};
+
+struct Texture : public Image {
+    Texture() : Image(), NPOTAdjust(false)  { }
     GLuint        potWidth;
     GLuint        potHeight;
     GLfloat       wScale;
     GLfloat       hScale;
-    EGLImageKHR   image;
-    uint32_t      transform;
     bool          NPOTAdjust;
-    bool          dirty;
 };
 
 // ---------------------------------------------------------------------------
@@ -68,7 +71,7 @@
             const Region& dirty, const GGLSurface& t);
 
     // make active buffer an EGLImage if needed
-    status_t initEglImage(Texture* texture,
+    status_t initEglImage(Image* texture,
             EGLDisplay dpy, const sp<GraphicBuffer>& buffer);
 };
 
diff --git a/libs/surfaceflinger_client/ISurface.cpp b/libs/surfaceflinger_client/ISurface.cpp
index c5d0c0e..7049d9e 100644
--- a/libs/surfaceflinger_client/ISurface.cpp
+++ b/libs/surfaceflinger_client/ISurface.cpp
@@ -71,11 +71,15 @@
     {
     }
 
-    virtual sp<GraphicBuffer> requestBuffer(int bufferIdx, int usage)
+    virtual sp<GraphicBuffer> requestBuffer(int bufferIdx,
+            uint32_t w, uint32_t h, uint32_t format, uint32_t usage)
     {
         Parcel data, reply;
         data.writeInterfaceToken(ISurface::getInterfaceDescriptor());
         data.writeInt32(bufferIdx);
+        data.writeInt32(w);
+        data.writeInt32(h);
+        data.writeInt32(format);
         data.writeInt32(usage);
         remote()->transact(REQUEST_BUFFER, data, &reply);
         sp<GraphicBuffer> buffer = new GraphicBuffer();
@@ -150,8 +154,11 @@
         case REQUEST_BUFFER: {
             CHECK_INTERFACE(ISurface, data, reply);
             int bufferIdx = data.readInt32();
-            int usage = data.readInt32();
-            sp<GraphicBuffer> buffer(requestBuffer(bufferIdx, usage));
+            uint32_t w = data.readInt32();
+            uint32_t h = data.readInt32();
+            uint32_t format = data.readInt32();
+            uint32_t usage = data.readInt32();
+            sp<GraphicBuffer> buffer(requestBuffer(bufferIdx, w, h, format, usage));
             if (buffer == NULL)
                 return BAD_VALUE;
             return reply->write(*buffer);
diff --git a/libs/surfaceflinger_client/SharedBufferStack.cpp b/libs/surfaceflinger_client/SharedBufferStack.cpp
index dab8ed8..2577dc0 100644
--- a/libs/surfaceflinger_client/SharedBufferStack.cpp
+++ b/libs/surfaceflinger_client/SharedBufferStack.cpp
@@ -44,7 +44,7 @@
 
 // these functions are used by the clients
 status_t SharedClient::validate(size_t i) const {
-    if (uint32_t(i) >= uint32_t(NUM_LAYERS_MAX))
+    if (uint32_t(i) >= uint32_t(SharedBufferStack::NUM_LAYERS_MAX))
         return BAD_INDEX;
     return surfaces[i].status;
 }
@@ -144,10 +144,10 @@
 // ----------------------------------------------------------------------------
 
 SharedBufferBase::SharedBufferBase(SharedClient* sharedClient,
-        int surface, int num, int32_t identity)
+        int surface, int32_t identity)
     : mSharedClient(sharedClient), 
       mSharedStack(sharedClient->surfaces + surface),
-      mNumBuffers(num), mIdentity(identity)
+      mIdentity(identity)
 {
 }
 
@@ -155,12 +155,6 @@
 {
 }
 
-uint32_t SharedBufferBase::getIdentity()
-{
-    SharedBufferStack& stack( *mSharedStack );
-    return stack.identity;
-}
-
 status_t SharedBufferBase::getStatus() const
 {
     SharedBufferStack& stack( *mSharedStack );
@@ -179,34 +173,16 @@
     char buffer[SIZE];
     String8 result;
     SharedBufferStack& stack( *mSharedStack );
-    int tail = computeTail();
     snprintf(buffer, SIZE, 
-            "%s[ head=%2d, available=%2d, queued=%2d, tail=%2d ] "
+            "%s[ head=%2d, available=%2d, queued=%2d ] "
             "reallocMask=%08x, inUse=%2d, identity=%d, status=%d",
-            prefix, stack.head, stack.available, stack.queued, tail,
+            prefix, stack.head, stack.available, stack.queued,
             stack.reallocMask, stack.inUse, stack.identity, stack.status);
     result.append(buffer);
-
-    snprintf(buffer, SIZE, " { ");
-    result.append(buffer);
-
-    for (int i=0 ; i<mNumBuffers ; i++) {
-        snprintf(buffer, SIZE, "%d ", stack.index[i]);
-        result.append(buffer);
-    }
-
-    snprintf(buffer, SIZE, " }\n");
-    result.append(buffer);
-
+    result.append("\n");
     return result;
 }
 
-int32_t SharedBufferBase::computeTail() const
-{
-    SharedBufferStack& stack( *mSharedStack );
-    return (mNumBuffers + stack.head - stack.available + 1) % mNumBuffers;
-}
-
 status_t SharedBufferBase::waitForCondition(const ConditionBase& condition)
 {
     const SharedBufferStack& stack( *mSharedStack );
@@ -270,7 +246,7 @@
 }
 bool SharedBufferServer::ReallocateCondition::operator()() const {
     int32_t head = stack.head;
-    if (uint32_t(head) >= NUM_BUFFER_MAX) {
+    if (uint32_t(head) >= SharedBufferStack::NUM_BUFFER_MAX) {
         // if stack.head is messed up, we cannot allow the server to
         // crash (since stack.head is mapped on the client side)
         stack.status = BAD_VALUE;
@@ -318,7 +294,7 @@
 }
 ssize_t SharedBufferServer::RetireUpdate::operator()() {
     int32_t head = stack.head;
-    if (uint32_t(head) >= NUM_BUFFER_MAX)
+    if (uint32_t(head) >= SharedBufferStack::NUM_BUFFER_MAX)
         return BAD_VALUE;
 
     // Preventively lock the current buffer before updating queued.
@@ -361,14 +337,20 @@
 
 SharedBufferClient::SharedBufferClient(SharedClient* sharedClient,
         int surface, int num, int32_t identity)
-    : SharedBufferBase(sharedClient, surface, num, identity),
-      tail(0), undoDequeueTail(0)
+    : SharedBufferBase(sharedClient, surface, identity),
+      mNumBuffers(num), tail(0), undoDequeueTail(0)
 {
     SharedBufferStack& stack( *mSharedStack );
     tail = computeTail();
     queued_head = stack.head;
 }
 
+int32_t SharedBufferClient::computeTail() const
+{
+    SharedBufferStack& stack( *mSharedStack );
+    return (mNumBuffers + stack.head - stack.available + 1) % mNumBuffers;
+}
+
 ssize_t SharedBufferClient::dequeue()
 {
     SharedBufferStack& stack( *mSharedStack );
@@ -377,7 +359,9 @@
         LOGW("dequeue: tail=%d, head=%d, avail=%d, queued=%d",
                 tail, stack.head, stack.available, stack.queued);
     }
-        
+
+    RWLock::AutoRLock _rd(mLock);
+
     const nsecs_t dequeueTime = systemTime(SYSTEM_TIME_THREAD);
 
     //LOGD("[%d] about to dequeue a buffer",
@@ -407,6 +391,8 @@
 
 status_t SharedBufferClient::undoDequeue(int buf)
 {
+    RWLock::AutoRLock _rd(mLock);
+
     // TODO: we can only undo the previous dequeue, we should
     // enforce that in the api
     UndoDequeueUpdate update(this);
@@ -419,6 +405,8 @@
 
 status_t SharedBufferClient::lock(int buf)
 {
+    RWLock::AutoRLock _rd(mLock);
+
     SharedBufferStack& stack( *mSharedStack );
     LockCondition condition(this, buf);
     status_t err = waitForCondition(condition);
@@ -427,6 +415,8 @@
 
 status_t SharedBufferClient::queue(int buf)
 {
+    RWLock::AutoRLock _rd(mLock);
+
     SharedBufferStack& stack( *mSharedStack );
 
     queued_head = (queued_head + 1) % mNumBuffers;
@@ -444,7 +434,7 @@
 bool SharedBufferClient::needNewBuffer(int buf) const
 {
     SharedBufferStack& stack( *mSharedStack );
-    const uint32_t mask = 1<<buf;
+    const uint32_t mask = 1<<(31-buf);
     return (android_atomic_and(~mask, &stack.reallocMask) & mask) != 0;
 }
 
@@ -460,21 +450,32 @@
     return stack.setDirtyRegion(buf, reg);
 }
 
-status_t SharedBufferClient::setBufferCount(int bufferCount)
+status_t SharedBufferClient::setBufferCount(
+        int bufferCount, const SetBufferCountCallback& ipc)
 {
     SharedBufferStack& stack( *mSharedStack );
-    if (uint32_t(bufferCount) >= NUM_BUFFER_MAX)
+    if (uint32_t(bufferCount) >= SharedBufferStack::NUM_BUFFER_MAX)
         return BAD_VALUE;
-    mNumBuffers = bufferCount;
-    queued_head = (stack.head + stack.queued) % mNumBuffers;
-    return NO_ERROR;
+
+    if (uint32_t(bufferCount) < SharedBufferStack::NUM_BUFFER_MIN)
+        return BAD_VALUE;
+
+    RWLock::AutoWLock _wr(mLock);
+
+    status_t err = ipc(bufferCount);
+    if (err == NO_ERROR) {
+        mNumBuffers = bufferCount;
+        queued_head = (stack.head + stack.queued) % mNumBuffers;
+    }
+    return err;
 }
 
 // ----------------------------------------------------------------------------
 
 SharedBufferServer::SharedBufferServer(SharedClient* sharedClient,
         int surface, int num, int32_t identity)
-    : SharedBufferBase(sharedClient, surface, num, identity)
+    : SharedBufferBase(sharedClient, surface, identity),
+      mNumBuffers(num)
 {
     mSharedStack->init(identity);
     mSharedStack->head = num-1;
@@ -490,10 +491,12 @@
 
 ssize_t SharedBufferServer::retireAndLock()
 {
+    RWLock::AutoRLock _l(mLock);
+
     RetireUpdate update(this, mNumBuffers);
     ssize_t buf = updateCondition( update );
     if (buf >= 0) {
-        if (uint32_t(buf) >= NUM_BUFFER_MAX)
+        if (uint32_t(buf) >= SharedBufferStack::NUM_BUFFER_MAX)
             return BAD_VALUE;
         SharedBufferStack& stack( *mSharedStack );
         buf = stack.index[buf];
@@ -518,11 +521,25 @@
     }
 }
 
-status_t SharedBufferServer::reallocate()
+status_t SharedBufferServer::reallocateAll()
 {
+    RWLock::AutoRLock _l(mLock);
+
     SharedBufferStack& stack( *mSharedStack );
-    uint32_t mask = (1<<mNumBuffers)-1;
-    android_atomic_or(mask, &stack.reallocMask); 
+    uint32_t mask = mBufferList.getMask();
+    android_atomic_or(mask, &stack.reallocMask);
+    return NO_ERROR;
+}
+
+status_t SharedBufferServer::reallocateAllExcept(int buffer)
+{
+    RWLock::AutoRLock _l(mLock);
+
+    SharedBufferStack& stack( *mSharedStack );
+    BufferList temp(mBufferList);
+    temp.remove(buffer);
+    uint32_t mask = temp.getMask();
+    android_atomic_or(mask, &stack.reallocMask);
     return NO_ERROR;
 }
 
@@ -534,6 +551,13 @@
 
 status_t SharedBufferServer::assertReallocate(int buf)
 {
+    /*
+     * NOTE: it's safe to hold mLock for read while waiting for
+     * the ReallocateCondition because that condition is not updated
+     * by the thread that holds mLock for write.
+     */
+    RWLock::AutoRLock _l(mLock);
+
     // TODO: need to validate "buf"
     ReallocateCondition condition(this, buf);
     status_t err = waitForCondition(condition);
@@ -546,9 +570,7 @@
     return stack.getDirtyRegion(buf);
 }
 
-
 /*
- *
  * NOTE: this is not thread-safe on the server-side, meaning
  * 'head' cannot move during this operation. The client-side
  * can safely operate an usual.
@@ -556,9 +578,11 @@
  */
 status_t SharedBufferServer::resize(int newNumBuffers)
 {
-    if (uint32_t(newNumBuffers) >= NUM_BUFFER_MAX)
+    if (uint32_t(newNumBuffers) >= SharedBufferStack::NUM_BUFFER_MAX)
         return BAD_VALUE;
 
+    RWLock::AutoWLock _l(mLock);
+
     // for now we're not supporting shrinking
     const int numBuffers = mNumBuffers;
     if (newNumBuffers < numBuffers)
@@ -569,7 +593,7 @@
 
     // read the head, make sure it's valid
     int32_t head = stack.head;
-    if (uint32_t(head) >= NUM_BUFFER_MAX)
+    if (uint32_t(head) >= SharedBufferStack::NUM_BUFFER_MAX)
         return BAD_VALUE;
 
     int base = numBuffers;
diff --git a/libs/surfaceflinger_client/Surface.cpp b/libs/surfaceflinger_client/Surface.cpp
index afbeafb..a26733e 100644
--- a/libs/surfaceflinger_client/Surface.cpp
+++ b/libs/surfaceflinger_client/Surface.cpp
@@ -151,75 +151,75 @@
 }
 
 status_t SurfaceControl::setLayer(int32_t layer) {
-    const sp<SurfaceComposerClient>& client(mClient);
     status_t err = validate();
     if (err < 0) return err;
+    const sp<SurfaceComposerClient>& client(mClient);
     return client->setLayer(mToken, layer);
 }
 status_t SurfaceControl::setPosition(int32_t x, int32_t y) {
-    const sp<SurfaceComposerClient>& client(mClient);
     status_t err = validate();
     if (err < 0) return err;
+    const sp<SurfaceComposerClient>& client(mClient);
     return client->setPosition(mToken, x, y);
 }
 status_t SurfaceControl::setSize(uint32_t w, uint32_t h) {
-    const sp<SurfaceComposerClient>& client(mClient);
     status_t err = validate();
     if (err < 0) return err;
+    const sp<SurfaceComposerClient>& client(mClient);
     return client->setSize(mToken, w, h);
 }
 status_t SurfaceControl::hide() {
-    const sp<SurfaceComposerClient>& client(mClient);
     status_t err = validate();
     if (err < 0) return err;
+    const sp<SurfaceComposerClient>& client(mClient);
     return client->hide(mToken);
 }
 status_t SurfaceControl::show(int32_t layer) {
-    const sp<SurfaceComposerClient>& client(mClient);
     status_t err = validate();
     if (err < 0) return err;
+    const sp<SurfaceComposerClient>& client(mClient);
     return client->show(mToken, layer);
 }
 status_t SurfaceControl::freeze() {
-    const sp<SurfaceComposerClient>& client(mClient);
     status_t err = validate();
     if (err < 0) return err;
+    const sp<SurfaceComposerClient>& client(mClient);
     return client->freeze(mToken);
 }
 status_t SurfaceControl::unfreeze() {
-    const sp<SurfaceComposerClient>& client(mClient);
     status_t err = validate();
     if (err < 0) return err;
+    const sp<SurfaceComposerClient>& client(mClient);
     return client->unfreeze(mToken);
 }
 status_t SurfaceControl::setFlags(uint32_t flags, uint32_t mask) {
-    const sp<SurfaceComposerClient>& client(mClient);
     status_t err = validate();
     if (err < 0) return err;
+    const sp<SurfaceComposerClient>& client(mClient);
     return client->setFlags(mToken, flags, mask);
 }
 status_t SurfaceControl::setTransparentRegionHint(const Region& transparent) {
-    const sp<SurfaceComposerClient>& client(mClient);
     status_t err = validate();
     if (err < 0) return err;
+    const sp<SurfaceComposerClient>& client(mClient);
     return client->setTransparentRegionHint(mToken, transparent);
 }
 status_t SurfaceControl::setAlpha(float alpha) {
-    const sp<SurfaceComposerClient>& client(mClient);
     status_t err = validate();
     if (err < 0) return err;
+    const sp<SurfaceComposerClient>& client(mClient);
     return client->setAlpha(mToken, alpha);
 }
 status_t SurfaceControl::setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
-    const sp<SurfaceComposerClient>& client(mClient);
     status_t err = validate();
     if (err < 0) return err;
+    const sp<SurfaceComposerClient>& client(mClient);
     return client->setMatrix(mToken, dsdx, dtdx, dsdy, dtdy);
 }
 status_t SurfaceControl::setFreezeTint(uint32_t tint) {
-    const sp<SurfaceComposerClient>& client(mClient);
     status_t err = validate();
     if (err < 0) return err;
+    const sp<SurfaceComposerClient>& client(mClient);
     return client->setFreezeTint(mToken, tint);
 }
 
@@ -230,23 +230,6 @@
                 mToken, mIdentity, mClient.get());
         return NO_INIT;
     }
-    SharedClient const* cblk = mClient->mControl;
-    if (cblk == 0) {
-        LOGE("cblk is null (surface id=%d, identity=%u)", mToken, mIdentity);
-        return NO_INIT;
-    }
-    status_t err = cblk->validate(mToken);
-    if (err != NO_ERROR) {
-        LOGE("surface (id=%d, identity=%u) is invalid, err=%d (%s)",
-                mToken, mIdentity, err, strerror(-err));
-        return err;
-    }
-    uint32_t identity = cblk->getIdentity(mToken);
-    if (mIdentity != identity) {
-        LOGE("using an invalid surface id=%d, identity=%u should be %d",
-                mToken, mIdentity, identity);
-        return NO_INIT;
-    }
     return NO_ERROR;
 }
 
@@ -300,16 +283,15 @@
       mToken(surface->mToken), mIdentity(surface->mIdentity),
       mFormat(surface->mFormat), mFlags(surface->mFlags),
       mBufferMapper(GraphicBufferMapper::get()), mSharedBufferClient(NULL),
+      mInitCheck(NO_INIT),
       mWidth(surface->mWidth), mHeight(surface->mHeight)
 {
-    mSharedBufferClient = new SharedBufferClient(
-            mClient->mControl, mToken, 2, mIdentity);
-
     init();
 }
 
 Surface::Surface(const Parcel& parcel)
-    :  mBufferMapper(GraphicBufferMapper::get()), mSharedBufferClient(NULL)
+    :  mBufferMapper(GraphicBufferMapper::get()),
+       mSharedBufferClient(NULL), mInitCheck(NO_INIT)
 {
     sp<IBinder> clientBinder = parcel.readStrongBinder();
     mSurface    = interface_cast<ISurface>(parcel.readStrongBinder());
@@ -323,9 +305,6 @@
     // FIXME: what does that mean if clientBinder is NULL here?
     if (clientBinder != NULL) {
         mClient = SurfaceComposerClient::clientForConnection(clientBinder);
-
-        mSharedBufferClient = new SharedBufferClient(
-                mClient->mControl, mToken, 2, mIdentity);
     }
 
     init();
@@ -339,7 +318,7 @@
     android_native_window_t::queueBuffer      = queueBuffer;
     android_native_window_t::query            = query;
     android_native_window_t::perform          = perform;
-    mSwapRectangle.makeInvalid();
+
     DisplayInfo dinfo;
     SurfaceComposerClient::getDisplayInfo(0, &dinfo);
     const_cast<float&>(android_native_window_t::xdpi) = dinfo.xdpi;
@@ -348,16 +327,27 @@
     const_cast<int&>(android_native_window_t::minSwapInterval) = 1;
     const_cast<int&>(android_native_window_t::maxSwapInterval) = 1;
     const_cast<uint32_t&>(android_native_window_t::flags) = 0;
-    // be default we request a hardware surface
-    mUsage = GRALLOC_USAGE_HW_RENDER;
+
     mConnected = 0;
+    mSwapRectangle.makeInvalid();
+    // two buffers by default
+    mBuffers.setCapacity(2);
+    mBuffers.insertAt(0, 2);
+
+    if (mClient != 0) {
+        mSharedBufferClient = new SharedBufferClient(
+                mClient->getSharedClient(), mToken, 2, mIdentity);
+    }
+
+    mInitCheck = initCheck();
 }
 
 Surface::~Surface()
 {
     // this is a client-side operation, the surface is destroyed, unmap
     // its buffers in this process.
-    for (int i=0 ; i<2 ; i++) {
+    size_t size = mBuffers.size();
+    for (size_t i=0 ; i<size ; i++) {
         if (mBuffers[i] != 0 && mBuffers[i]->handle != 0) {
             getBufferMapper().unregisterBuffer(mBuffers[i]->handle);
         }
@@ -365,62 +355,80 @@
 
     // clear all references and trigger an IPC now, to make sure things
     // happen without delay, since these resources are quite heavy.
+    mBuffers.clear();
     mClient.clear();
     mSurface.clear();
     delete mSharedBufferClient;
     IPCThreadState::self()->flushCommands();
 }
 
-sp<SurfaceComposerClient> Surface::getClient() const {
-    return mClient;
-}
-
-sp<ISurface> Surface::getISurface() const {
-    return mSurface;
-}
-
-bool Surface::isValid() {
-    return mToken>=0 && mClient!=0;
-}
-
-status_t Surface::validate() const
+status_t Surface::initCheck() const
 {
-    sp<SurfaceComposerClient> client(getClient());
     if (mToken<0 || mClient==0) {
-        LOGE("invalid token (%d, identity=%u) or client (%p)", 
-                mToken, mIdentity, client.get());
         return NO_INIT;
     }
-    SharedClient const* cblk = mClient->mControl;
+    SharedClient const* cblk = mClient->getSharedClient();
     if (cblk == 0) {
         LOGE("cblk is null (surface id=%d, identity=%u)", mToken, mIdentity);
         return NO_INIT;
     }
+    return NO_ERROR;
+}
+
+bool Surface::isValid() {
+    return mInitCheck == NO_ERROR;
+}
+
+status_t Surface::validate() const
+{
+    // check that we initialized ourself properly
+    if (mInitCheck != NO_ERROR) {
+        LOGE("invalid token (%d, identity=%u) or client (%p)",
+                mToken, mIdentity, mClient.get());
+        return mInitCheck;
+    }
+
+    // verify the identity of this surface
+    SharedClient const* cblk = mClient->getSharedClient();
+
+    uint32_t identity = cblk->getIdentity(mToken);
+
+    // this is a bit of a (temporary) special case, identity==0 means that
+    // no operation are allowed from the client (eg: dequeue/queue), this
+    // is used with PUSH_BUFFER surfaces for instance
+    if (identity == 0) {
+        LOGE("[Surface] invalid operation (identity=%u)", mIdentity);
+        return INVALID_OPERATION;
+    }
+
+    if (mIdentity != identity) {
+        LOGE("[Surface] using an invalid surface id=%d, "
+                "identity=%u should be %d",
+                mToken, mIdentity, identity);
+        return NO_INIT;
+    }
+
+    // check the surface didn't become invalid
     status_t err = cblk->validate(mToken);
     if (err != NO_ERROR) {
         LOGE("surface (id=%d, identity=%u) is invalid, err=%d (%s)",
                 mToken, mIdentity, err, strerror(-err));
         return err;
     }
-    uint32_t identity = cblk->getIdentity(mToken);
-    if (mIdentity != identity) {
-        LOGE("using an invalid surface id=%d, identity=%u should be %d",
-                mToken, mIdentity, identity);
-        return NO_INIT;
-    }
+
     return NO_ERROR;
 }
 
-
-bool Surface::isSameSurface(
-        const sp<Surface>& lhs, const sp<Surface>& rhs) 
-{
+bool Surface::isSameSurface(const sp<Surface>& lhs, const sp<Surface>& rhs) {
     if (lhs == 0 || rhs == 0)
         return false;
-
     return lhs->mSurface->asBinder() == rhs->mSurface->asBinder();
 }
 
+sp<ISurface> Surface::getISurface() const {
+    return mSurface;
+}
+
 // ----------------------------------------------------------------------------
 
 int Surface::setSwapInterval(android_native_window_t* window, int interval) {
@@ -463,9 +471,24 @@
 
 // ----------------------------------------------------------------------------
 
+bool Surface::needNewBuffer(int bufIdx,
+        uint32_t *pWidth, uint32_t *pHeight,
+        uint32_t *pFormat, uint32_t *pUsage) const
+{
+    Mutex::Autolock _l(mSurfaceLock);
+
+    // Always call needNewBuffer(), since it clears the needed buffers flags
+    bool needNewBuffer = mSharedBufferClient->needNewBuffer(bufIdx);
+    bool validBuffer = mBufferInfo.validateBuffer(mBuffers[bufIdx]);
+    bool newNeewBuffer = needNewBuffer || !validBuffer;
+    if (newNeewBuffer) {
+        mBufferInfo.get(pWidth, pHeight, pFormat, pUsage);
+    }
+    return newNeewBuffer;
+}
+
 int Surface::dequeueBuffer(android_native_buffer_t** buffer)
 {
-    sp<SurfaceComposerClient> client(getClient());
     status_t err = validate();
     if (err != NO_ERROR)
         return err;
@@ -476,27 +499,28 @@
         return bufIdx;
     }
 
-    // below we make sure we AT LEAST have the usage flags we want
-    const uint32_t usage(getUsage());
-    const sp<GraphicBuffer>& backBuffer(mBuffers[bufIdx]);
+    // grow the buffer array if needed
+    const size_t size = mBuffers.size();
+    const size_t needed = bufIdx+1;
+    if (size < needed) {
+        mBuffers.insertAt(size, needed-size);
+    }
 
-    // Always call needNewBuffer(), since it clears the needed buffers flags
-    bool needNewBuffer = mSharedBufferClient->needNewBuffer(bufIdx);
-    if (backBuffer == 0 || 
-        ((uint32_t(backBuffer->usage) & usage) != usage) ||
-        needNewBuffer)
-    {
-        err = getBufferLocked(bufIdx, usage);
-        LOGE_IF(err, "getBufferLocked(%ld, %08x) failed (%s)",
-                bufIdx, usage, strerror(-err));
+    uint32_t w, h, format, usage;
+    if (needNewBuffer(bufIdx, &w, &h, &format, &usage)) {
+        err = getBufferLocked(bufIdx, w, h, format, usage);
+        LOGE_IF(err, "getBufferLocked(%ld, %u, %u, %u, %08x) failed (%s)",
+                bufIdx, w, h, format, usage, strerror(-err));
         if (err == NO_ERROR) {
             // reset the width/height with the what we get from the buffer
+            const sp<GraphicBuffer>& backBuffer(mBuffers[bufIdx]);
             mWidth  = uint32_t(backBuffer->width);
             mHeight = uint32_t(backBuffer->height);
         }
     }
 
     // if we still don't have a buffer here, we probably ran out of memory
+    const sp<GraphicBuffer>& backBuffer(mBuffers[bufIdx]);
     if (!err && backBuffer==0) {
         err = NO_MEMORY;
     }
@@ -513,7 +537,6 @@
 
 int Surface::lockBuffer(android_native_buffer_t* buffer)
 {
-    sp<SurfaceComposerClient> client(getClient());
     status_t err = validate();
     if (err != NO_ERROR)
         return err;
@@ -526,7 +549,6 @@
 
 int Surface::queueBuffer(android_native_buffer_t* buffer)
 {   
-    sp<SurfaceComposerClient> client(getClient());
     status_t err = validate();
     if (err != NO_ERROR)
         return err;
@@ -543,6 +565,7 @@
 
     if (err == NO_ERROR) {
         // FIXME: can we avoid this IPC if we know there is one pending?
+        const sp<SurfaceComposerClient>& client(mClient);
         client->signalServer();
     }
     return err;
@@ -584,6 +607,12 @@
     case NATIVE_WINDOW_SET_CROP:
         res = dispatch_crop( args );
         break;
+    case NATIVE_WINDOW_SET_BUFFER_COUNT:
+        res = dispatch_set_buffer_count( args );
+        break;
+    case NATIVE_WINDOW_SET_BUFFERS_GEOMETRY:
+        res = dispatch_set_buffers_geometry( args );
+        break;
     default:
         res = NAME_NOT_FOUND;
         break;
@@ -607,12 +636,21 @@
     android_native_rect_t const* rect = va_arg(args, android_native_rect_t*);
     return crop( reinterpret_cast<Rect const*>(rect) );
 }
-
+int Surface::dispatch_set_buffer_count(va_list args) {
+    size_t bufferCount = va_arg(args, size_t);
+    return setBufferCount(bufferCount);
+}
+int Surface::dispatch_set_buffers_geometry(va_list args) {
+    int w = va_arg(args, int);
+    int h = va_arg(args, int);
+    int f = va_arg(args, int);
+    return setBuffersGeometry(w, h, f);
+}
 
 void Surface::setUsage(uint32_t reqUsage)
 {
     Mutex::Autolock _l(mSurfaceLock);
-    mUsage = reqUsage;
+    mBufferInfo.set(reqUsage);
 }
 
 int Surface::connect(int api)
@@ -653,18 +691,6 @@
     return err;
 }
 
-uint32_t Surface::getUsage() const
-{
-    Mutex::Autolock _l(mSurfaceLock);
-    return mUsage;
-}
-
-int Surface::getConnectedApi() const
-{
-    Mutex::Autolock _l(mSurfaceLock);
-    return mConnected;
-}
-
 int Surface::crop(Rect const* rect)
 {
     Mutex::Autolock _l(mSurfaceLock);
@@ -678,22 +704,41 @@
     sp<ISurface> s(mSurface);
     if (s == 0) return NO_INIT;
 
-    // FIXME: this needs to be synchronized dequeue/queue
+    class SetBufferCountIPC : public SharedBufferClient::SetBufferCountCallback {
+        sp<ISurface> surface;
+        virtual status_t operator()(int bufferCount) const {
+            return surface->setBufferCount(bufferCount);
+        }
+    public:
+        SetBufferCountIPC(const sp<ISurface>& surface) : surface(surface) { }
+    } ipc(s);
 
-    status_t err = s->setBufferCount(bufferCount);
+    status_t err = mSharedBufferClient->setBufferCount(bufferCount, ipc);
     LOGE_IF(err, "ISurface::setBufferCount(%d) returned %s",
             bufferCount, strerror(-err));
-    if (err == NO_ERROR) {
-        err = mSharedBufferClient->getStatus();
-        LOGE_IF(err,  "Surface (identity=%d) state = %d", mIdentity, err);
-        if (!err) {
-            // update our local copy of the buffer count
-            mSharedBufferClient->setBufferCount(bufferCount);
-        }
-    }
     return err;
 }
 
+int Surface::setBuffersGeometry(int w, int h, int format)
+{
+    if (w<0 || h<0 || format<0)
+        return BAD_VALUE;
+
+    if ((w && !h) || (!w && h))
+        return BAD_VALUE;
+
+    Mutex::Autolock _l(mSurfaceLock);
+    mBufferInfo.set(w, h, format);
+    return NO_ERROR;
+}
+
+// ----------------------------------------------------------------------------
+
+int Surface::getConnectedApi() const
+{
+    Mutex::Autolock _l(mSurfaceLock);
+    return mConnected;
+}
 
 // ----------------------------------------------------------------------------
 
@@ -824,7 +869,8 @@
     return buffer->getIndex();
 }
 
-status_t Surface::getBufferLocked(int index, int usage)
+status_t Surface::getBufferLocked(int index,
+        uint32_t w, uint32_t h, uint32_t format, uint32_t usage)
 {
     sp<ISurface> s(mSurface);
     if (s == 0) return NO_INIT;
@@ -832,20 +878,21 @@
     status_t err = NO_MEMORY;
 
     // free the current buffer
-    sp<GraphicBuffer>& currentBuffer(mBuffers[index]);
+    sp<GraphicBuffer>& currentBuffer(mBuffers.editItemAt(index));
     if (currentBuffer != 0) {
         getBufferMapper().unregisterBuffer(currentBuffer->handle);
         currentBuffer.clear();
     }
 
-    sp<GraphicBuffer> buffer = s->requestBuffer(index, usage);
+    sp<GraphicBuffer> buffer = s->requestBuffer(index, w, h, format, usage);
     LOGE_IF(buffer==0,
             "ISurface::getBuffer(%d, %08x) returned NULL",
             index, usage);
     if (buffer != 0) { // this should never happen by construction
         LOGE_IF(buffer->handle == NULL, 
-                "Surface (identity=%d) requestBuffer(%d, %08x) returned"
-                "a buffer with a null handle", mIdentity, index, usage);
+                "Surface (identity=%d) requestBuffer(%d, %u, %u, %u, %08x) "
+                "returned a buffer with a null handle",
+                mIdentity, index, w, h, format, usage);
         err = mSharedBufferClient->getStatus();
         LOGE_IF(err,  "Surface (identity=%d) state = %d", mIdentity, err);
         if (!err && buffer->handle != NULL) {
@@ -857,11 +904,50 @@
                 currentBuffer->setIndex(index);
             }
         } else {
-            err = err<0 ? err : NO_MEMORY;
+            err = err<0 ? err : status_t(NO_MEMORY);
         }
     }
     return err; 
 }
 
+// ----------------------------------------------------------------------------
+Surface::BufferInfo::BufferInfo()
+    : mWidth(0), mHeight(0), mFormat(0),
+      mUsage(GRALLOC_USAGE_HW_RENDER), mDirty(0)
+{
+}
+
+void Surface::BufferInfo::set(uint32_t w, uint32_t h, uint32_t format) {
+    if ((mWidth != w) || (mHeight != h) || (mFormat != format)) {
+        mWidth = w;
+        mHeight = h;
+        mFormat = format;
+        mDirty |= GEOMETRY;
+    }
+}
+
+void Surface::BufferInfo::set(uint32_t usage) {
+    mUsage = usage;
+}
+
+void Surface::BufferInfo::get(uint32_t *pWidth, uint32_t *pHeight,
+        uint32_t *pFormat, uint32_t *pUsage) const {
+    *pWidth  = mWidth;
+    *pHeight = mHeight;
+    *pFormat = mFormat;
+    *pUsage  = mUsage;
+}
+
+bool Surface::BufferInfo::validateBuffer(const sp<GraphicBuffer>& buffer) const {
+    // make sure we AT LEAST have the usage flags we want
+    if (mDirty || buffer==0 ||
+            ((buffer->usage & mUsage) != mUsage)) {
+        mDirty = 0;
+        return false;
+    }
+    return true;
+}
+
+// ----------------------------------------------------------------------------
 }; // namespace android
 
diff --git a/libs/surfaceflinger_client/SurfaceComposerClient.cpp b/libs/surfaceflinger_client/SurfaceComposerClient.cpp
index 85167da..96ed566 100644
--- a/libs/surfaceflinger_client/SurfaceComposerClient.cpp
+++ b/libs/surfaceflinger_client/SurfaceComposerClient.cpp
@@ -123,11 +123,11 @@
 {
     sp<ISurfaceComposer> sm(getComposerService());
     if (sm == 0) {
-        _init(0, 0);
+        init(0, 0);
         return;
     }
 
-    _init(sm, sm->createConnection());
+    init(sm, sm->createConnection());
 
     if (mClient != 0) {
         Mutex::Autolock _l(gLock);
@@ -139,9 +139,14 @@
 SurfaceComposerClient::SurfaceComposerClient(
         const sp<ISurfaceComposer>& sm, const sp<IBinder>& conn)
 {
-    _init(sm, interface_cast<ISurfaceFlingerClient>(conn));
+    init(sm, interface_cast<ISurfaceFlingerClient>(conn));
 }
 
+SurfaceComposerClient::~SurfaceComposerClient()
+{
+    VERBOSE("Destroying client %p, conn %p", this, mClient.get());
+    dispose();
+}
 
 status_t SurfaceComposerClient::linkToComposerDeath(
         const sp<IBinder::DeathRecipient>& recipient,
@@ -151,7 +156,7 @@
     return sm->asBinder()->linkToDeath(recipient, cookie, flags);    
 }
 
-void SurfaceComposerClient::_init(
+void SurfaceComposerClient::init(
         const sp<ISurfaceComposer>& sm, const sp<ISurfaceFlingerClient>& conn)
 {
     VERBOSE("Creating client %p, conn %p", this, conn.get());
@@ -172,10 +177,9 @@
     mControl = static_cast<SharedClient *>(mControlMemory->getBase());
 }
 
-SurfaceComposerClient::~SurfaceComposerClient()
+SharedClient* SurfaceComposerClient::getSharedClient() const
 {
-    VERBOSE("Destroying client %p, conn %p", this, mClient.get());
-    dispose();
+    return mControl;
 }
 
 status_t SurfaceComposerClient::initCheck() const
@@ -250,7 +254,7 @@
 status_t SurfaceComposerClient::getDisplayInfo(
         DisplayID dpy, DisplayInfo* info)
 {
-    if (uint32_t(dpy)>=NUM_DISPLAY_MAX)
+    if (uint32_t(dpy)>=SharedBufferStack::NUM_DISPLAY_MAX)
         return BAD_VALUE;
 
     volatile surface_flinger_cblk_t const * cblk = get_cblk();
@@ -268,7 +272,7 @@
 
 ssize_t SurfaceComposerClient::getDisplayWidth(DisplayID dpy)
 {
-    if (uint32_t(dpy)>=NUM_DISPLAY_MAX)
+    if (uint32_t(dpy)>=SharedBufferStack::NUM_DISPLAY_MAX)
         return BAD_VALUE;
     volatile surface_flinger_cblk_t const * cblk = get_cblk();
     volatile display_cblk_t const * dcblk = cblk->displays + dpy;
@@ -277,7 +281,7 @@
 
 ssize_t SurfaceComposerClient::getDisplayHeight(DisplayID dpy)
 {
-    if (uint32_t(dpy)>=NUM_DISPLAY_MAX)
+    if (uint32_t(dpy)>=SharedBufferStack::NUM_DISPLAY_MAX)
         return BAD_VALUE;
     volatile surface_flinger_cblk_t const * cblk = get_cblk();
     volatile display_cblk_t const * dcblk = cblk->displays + dpy;
@@ -286,7 +290,7 @@
 
 ssize_t SurfaceComposerClient::getDisplayOrientation(DisplayID dpy)
 {
-    if (uint32_t(dpy)>=NUM_DISPLAY_MAX)
+    if (uint32_t(dpy)>=SharedBufferStack::NUM_DISPLAY_MAX)
         return BAD_VALUE;
     volatile surface_flinger_cblk_t const * cblk = get_cblk();
     volatile display_cblk_t const * dcblk = cblk->displays + dpy;
@@ -345,7 +349,7 @@
         sp<ISurface> surface = mClient->createSurface(&data, pid, name,
                 display, w, h, format, flags);
         if (surface != 0) {
-            if (uint32_t(data.token) < NUM_LAYERS_MAX) {
+            if (uint32_t(data.token) < SharedBufferStack::NUM_LAYERS_MAX) {
                 result = new SurfaceControl(this, surface, data, w, h, format, flags);
             }
         }
@@ -488,7 +492,7 @@
     return NO_ERROR;
 }
 
-layer_state_t* SurfaceComposerClient::_get_state_l(SurfaceID index)
+layer_state_t* SurfaceComposerClient::get_state_l(SurfaceID index)
 {
     // API usage error, do nothing.
     if (mTransactionOpen<=0) {
@@ -508,49 +512,49 @@
     return mStates.editArray() + i;
 }
 
-layer_state_t* SurfaceComposerClient::_lockLayerState(SurfaceID id)
+layer_state_t* SurfaceComposerClient::lockLayerState(SurfaceID id)
 {
     layer_state_t* s;
     mLock.lock();
-    s = _get_state_l(id);
+    s = get_state_l(id);
     if (!s) mLock.unlock();
     return s;
 }
 
-void SurfaceComposerClient::_unlockLayerState()
+void SurfaceComposerClient::unlockLayerState()
 {
     mLock.unlock();
 }
 
 status_t SurfaceComposerClient::setPosition(SurfaceID id, int32_t x, int32_t y)
 {
-    layer_state_t* s = _lockLayerState(id);
+    layer_state_t* s = lockLayerState(id);
     if (!s) return BAD_INDEX;
     s->what |= ISurfaceComposer::ePositionChanged;
     s->x = x;
     s->y = y;
-    _unlockLayerState();
+    unlockLayerState();
     return NO_ERROR;
 }
 
 status_t SurfaceComposerClient::setSize(SurfaceID id, uint32_t w, uint32_t h)
 {
-    layer_state_t* s = _lockLayerState(id);
+    layer_state_t* s = lockLayerState(id);
     if (!s) return BAD_INDEX;
     s->what |= ISurfaceComposer::eSizeChanged;
     s->w = w;
     s->h = h;
-    _unlockLayerState();
+    unlockLayerState();
     return NO_ERROR;
 }
 
 status_t SurfaceComposerClient::setLayer(SurfaceID id, int32_t z)
 {
-    layer_state_t* s = _lockLayerState(id);
+    layer_state_t* s = lockLayerState(id);
     if (!s) return BAD_INDEX;
     s->what |= ISurfaceComposer::eLayerChanged;
     s->z = z;
-    _unlockLayerState();
+    unlockLayerState();
     return NO_ERROR;
 }
 
@@ -579,34 +583,34 @@
 status_t SurfaceComposerClient::setFlags(SurfaceID id,
         uint32_t flags, uint32_t mask)
 {
-    layer_state_t* s = _lockLayerState(id);
+    layer_state_t* s = lockLayerState(id);
     if (!s) return BAD_INDEX;
     s->what |= ISurfaceComposer::eVisibilityChanged;
     s->flags &= ~mask;
     s->flags |= (flags & mask);
     s->mask |= mask;
-    _unlockLayerState();
+    unlockLayerState();
     return NO_ERROR;
 }
 
 status_t SurfaceComposerClient::setTransparentRegionHint(
         SurfaceID id, const Region& transparentRegion)
 {
-    layer_state_t* s = _lockLayerState(id);
+    layer_state_t* s = lockLayerState(id);
     if (!s) return BAD_INDEX;
     s->what |= ISurfaceComposer::eTransparentRegionChanged;
     s->transparentRegion = transparentRegion;
-    _unlockLayerState();
+    unlockLayerState();
     return NO_ERROR;
 }
 
 status_t SurfaceComposerClient::setAlpha(SurfaceID id, float alpha)
 {
-    layer_state_t* s = _lockLayerState(id);
+    layer_state_t* s = lockLayerState(id);
     if (!s) return BAD_INDEX;
     s->what |= ISurfaceComposer::eAlphaChanged;
     s->alpha = alpha;
-    _unlockLayerState();
+    unlockLayerState();
     return NO_ERROR;
 }
 
@@ -615,7 +619,7 @@
         float dsdx, float dtdx,
         float dsdy, float dtdy )
 {
-    layer_state_t* s = _lockLayerState(id);
+    layer_state_t* s = lockLayerState(id);
     if (!s) return BAD_INDEX;
     s->what |= ISurfaceComposer::eMatrixChanged;
     layer_state_t::matrix22_t matrix;
@@ -624,17 +628,17 @@
     matrix.dsdy = dsdy;
     matrix.dtdy = dtdy;
     s->matrix = matrix;
-    _unlockLayerState();
+    unlockLayerState();
     return NO_ERROR;
 }
 
 status_t SurfaceComposerClient::setFreezeTint(SurfaceID id, uint32_t tint)
 {
-    layer_state_t* s = _lockLayerState(id);
+    layer_state_t* s = lockLayerState(id);
     if (!s) return BAD_INDEX;
     s->what |= ISurfaceComposer::eFreezeTintChanged;
     s->tint = tint;
-    _unlockLayerState();
+    unlockLayerState();
     return NO_ERROR;
 }
 
diff --git a/libs/surfaceflinger_client/tests/SharedBufferStack/SharedBufferStackTest.cpp b/libs/surfaceflinger_client/tests/SharedBufferStack/SharedBufferStackTest.cpp
index f490a65..f409f48 100644
--- a/libs/surfaceflinger_client/tests/SharedBufferStack/SharedBufferStackTest.cpp
+++ b/libs/surfaceflinger_client/tests/SharedBufferStack/SharedBufferStackTest.cpp
@@ -54,8 +54,16 @@
 
 
     printf("resize test\n");
-    s.resize(6);
-    c.setBufferCount(6);
+    class SetBufferCountIPC : public SharedBufferClient::SetBufferCountCallback {
+        SharedBufferServer& s;
+        virtual status_t operator()(int bufferCount) const {
+            return s.resize(bufferCount);
+        }
+    public:
+        SetBufferCountIPC(SharedBufferServer& s) : s(s) { }
+    } resize(s);
+
+    c.setBufferCount(6, resize);
     int list3[6] = {3, 2, 1, 4, 5, 0};
     test0(s, c, 6, list3);
 
diff --git a/vcard/java/com/android/vcard/VCardConfig.java b/vcard/java/com/android/vcard/VCardConfig.java
index fc95922..a011d8e 100644
--- a/vcard/java/com/android/vcard/VCardConfig.java
+++ b/vcard/java/com/android/vcard/VCardConfig.java
@@ -43,15 +43,20 @@
      * The charset used during import.
      * </p>
      * <p>
-     * We cannot determine which charset should be used to interpret a given vCard file
-     * at first, while we have to decode sime encoded data (e.g. BASE64) to binary.
-     * In order to avoid "misinterpretation" of charset as much as possible,
-     * "ISO-8859-1" (a.k.a Latin-1) is first used for reading a stream.
-     * When charset is specified in a property (with "CHARSET=..." parameter),
+     * We cannot determine which charset should be used to interpret lines in vCard,
+     * while Java requires us to specify it when InputStream is used.
+     * We need to rely on the mechanism due to some performance reason.
+     * </p>
+     * <p>
+     * In order to avoid "misinterpretation" of charset and lose any data in vCard,
+     * "ISO-8859-1" is first used for reading the stream.
+     * When a charset is specified in a property (with "CHARSET=..." parameter),
      * the string is decoded to raw bytes and encoded into the specific charset,
-     * assuming "ISO-8859-1" is able to map "all" 8bit characters to some unicode,
-     * and it has 1 to 1 mapping in all 8bit characters.
-     * If the assumption is not correct, this setting will cause some bug.
+     * </p>
+     * <p>
+     * Unicode specification there's a one to one mapping between each byte in ISO-8859-1
+     * and a codepoint, and Java specification requires runtime must have the charset.
+     * Thus, ISO-8859-1 is one effective mapping for intermediate mapping.
      * </p>
      */
     public static final String DEFAULT_INTERMEDIATE_CHARSET = "ISO-8859-1";
diff --git a/vcard/java/com/android/vcard/VCardEntryConstructor.java b/vcard/java/com/android/vcard/VCardEntryConstructor.java
index 2679e23..6cee070 100644
--- a/vcard/java/com/android/vcard/VCardEntryConstructor.java
+++ b/vcard/java/com/android/vcard/VCardEntryConstructor.java
@@ -68,7 +68,7 @@
     private final List<VCardEntryHandler> mEntryHandlers = new ArrayList<VCardEntryHandler>();
 
     public VCardEntryConstructor() {
-        this(VCardConfig.VCARD_TYPE_V21_GENERIC, null, null, false);
+        this(VCardConfig.VCARD_TYPE_V21_GENERIC, null);
     }
 
     public VCardEntryConstructor(final int vcardType) {
@@ -85,7 +85,7 @@
     }
 
     /**
-     * @hide
+     * @hide Just for testing.
      */
     public VCardEntryConstructor(final int vcardType, final Account account,
             final String inputCharset, final boolean strictLineBreakParsing) {
diff --git a/vcard/java/com/android/vcard/VCardParserImpl_V21.java b/vcard/java/com/android/vcard/VCardParserImpl_V21.java
index 00ae6c9..b8343ae 100644
--- a/vcard/java/com/android/vcard/VCardParserImpl_V21.java
+++ b/vcard/java/com/android/vcard/VCardParserImpl_V21.java
@@ -15,7 +15,6 @@
  */
 package com.android.vcard;
 
-import android.text.TextUtils;
 import android.util.Log;
 
 import com.android.vcard.exception.VCardAgentNotSupportedException;
@@ -64,12 +63,12 @@
         }
     }
 
-    private static final String sDefaultEncoding = "8BIT";
+    private static final String DEFAULT_ENCODING = "8BIT";
 
     protected boolean mCanceled;
     protected VCardInterpreter mInterpreter;
 
-    protected final String mImportCharset;
+    protected final String mIntermediateCharset;
 
     /**
      * <p>
@@ -136,20 +135,15 @@
     private long mTimeHandleBase64;
 
     public VCardParserImpl_V21() {
-        this(VCardConfig.VCARD_TYPE_DEFAULT, null);
+        this(VCardConfig.VCARD_TYPE_DEFAULT);
     }
 
     public VCardParserImpl_V21(int vcardType) {
-        this(vcardType, null);
-    }
-
-    public VCardParserImpl_V21(int vcardType, String importCharset) {
         if ((vcardType & VCardConfig.FLAG_TORELATE_NEST) != 0) {
             mNestCount = 1;
         }
 
-        mImportCharset = (!TextUtils.isEmpty(importCharset) ? importCharset :
-            VCardConfig.DEFAULT_INTERMEDIATE_CHARSET);
+        mIntermediateCharset =  VCardConfig.DEFAULT_INTERMEDIATE_CHARSET;
     }
 
     /**
@@ -385,7 +379,7 @@
      * "AGENT" [params] ":" vcard CRLF
      */
     protected boolean parseItem() throws IOException, VCardException {
-        mCurrentEncoding = sDefaultEncoding;
+        mCurrentEncoding = DEFAULT_ENCODING;
 
         final String line = getNonEmptyLine();
         long start = System.currentTimeMillis();
@@ -928,7 +922,7 @@
     }
 
     protected String getDefaultEncoding() {
-        return sDefaultEncoding;
+        return DEFAULT_ENCODING;
     }
 
 
@@ -938,7 +932,7 @@
             throw new NullPointerException("InputStream must not be null.");
         }
 
-        final InputStreamReader tmpReader = new InputStreamReader(is, mImportCharset);
+        final InputStreamReader tmpReader = new InputStreamReader(is, mIntermediateCharset);
         if (VCardConfig.showPerformanceLog()) {
             mReader = new CustomBufferedReader(tmpReader);
         } else {
diff --git a/vcard/java/com/android/vcard/VCardParserImpl_V30.java b/vcard/java/com/android/vcard/VCardParserImpl_V30.java
index 61d0455..def1495 100644
--- a/vcard/java/com/android/vcard/VCardParserImpl_V30.java
+++ b/vcard/java/com/android/vcard/VCardParserImpl_V30.java
@@ -46,11 +46,7 @@
     }
 
     public VCardParserImpl_V30(int vcardType) {
-        super(vcardType, null);
-    }
-
-    public VCardParserImpl_V30(int vcardType, String importCharset) {
-        super(vcardType, importCharset);
+        super(vcardType);
     }
 
     @Override
diff --git a/vcard/java/com/android/vcard/VCardParser_V21.java b/vcard/java/com/android/vcard/VCardParser_V21.java
index 2a5e313..7aa7a82 100644
--- a/vcard/java/com/android/vcard/VCardParser_V21.java
+++ b/vcard/java/com/android/vcard/VCardParser_V21.java
@@ -98,10 +98,6 @@
         mVCardParserImpl = new VCardParserImpl_V21(vcardType);
     }
 
-    public VCardParser_V21(int parseType, String inputCharset) {
-        mVCardParserImpl = new VCardParserImpl_V21(parseType, null);
-    }
-
     public void parse(InputStream is, VCardInterpreter interepreter)
             throws IOException, VCardException {
         mVCardParserImpl.parse(is, interepreter);
diff --git a/vcard/java/com/android/vcard/VCardParser_V30.java b/vcard/java/com/android/vcard/VCardParser_V30.java
index 179869b..475534c 100644
--- a/vcard/java/com/android/vcard/VCardParser_V30.java
+++ b/vcard/java/com/android/vcard/VCardParser_V30.java
@@ -76,10 +76,6 @@
         mVCardParserImpl = new VCardParserImpl_V30(vcardType);
     }
 
-    public VCardParser_V30(int vcardType, String importCharset) {
-        mVCardParserImpl = new VCardParserImpl_V30(vcardType, importCharset);
-    }
-
     public void parse(InputStream is, VCardInterpreter interepreter)
             throws IOException, VCardException {
         mVCardParserImpl.parse(is, interepreter);
diff --git a/vcard/tests/src/com/android/vcard/tests/test_utils/ContentValuesVerifier.java b/vcard/tests/src/com/android/vcard/tests/test_utils/ContentValuesVerifier.java
index 7d6db53..2b3e3ab 100644
--- a/vcard/tests/src/com/android/vcard/tests/test_utils/ContentValuesVerifier.java
+++ b/vcard/tests/src/com/android/vcard/tests/test_utils/ContentValuesVerifier.java
@@ -66,8 +66,7 @@
 
     public void verify(InputStream is, int vCardType, final VCardParser vCardParser)
             throws IOException, VCardException {
-        VCardEntryConstructor builder =
-            new VCardEntryConstructor(vCardType, null, null, false);
+        VCardEntryConstructor builder = new VCardEntryConstructor(vCardType, null);
         builder.addEntryHandler(this);
         try {
             vCardParser.parse(is, builder);
diff --git a/vcard/tests/src/com/android/vcard/tests/test_utils/ContentValuesVerifierElem.java b/vcard/tests/src/com/android/vcard/tests/test_utils/ContentValuesVerifierElem.java
index ecf4a2b..6c09693 100644
--- a/vcard/tests/src/com/android/vcard/tests/test_utils/ContentValuesVerifierElem.java
+++ b/vcard/tests/src/com/android/vcard/tests/test_utils/ContentValuesVerifierElem.java
@@ -62,8 +62,7 @@
         } else {
             vCardParser = new VCardParser_V21();
         }
-        VCardEntryConstructor builder =
-                new VCardEntryConstructor(vCardType, null, null, false);
+        final VCardEntryConstructor builder = new VCardEntryConstructor(vCardType, null);
         builder.addEntryHandler(mHandler);
         try {
             vCardParser.parse(is, builder);
diff --git a/vcard/tests/src/com/android/vcard/tests/test_utils/VNodeBuilder.java b/vcard/tests/src/com/android/vcard/tests/test_utils/VNodeBuilder.java
index 9b4fe83..77a28ad 100644
--- a/vcard/tests/src/com/android/vcard/tests/test_utils/VNodeBuilder.java
+++ b/vcard/tests/src/com/android/vcard/tests/test_utils/VNodeBuilder.java
@@ -62,23 +62,11 @@
     private boolean mStrictLineBreakParsing;
     
     public VNodeBuilder() {
-        this(VCardConfig.DEFAULT_INTERMEDIATE_CHARSET, VCardConfig.DEFAULT_IMPORT_CHARSET, false);
+        this(VCardConfig.DEFAULT_IMPORT_CHARSET, false);
     }
 
     public VNodeBuilder(String targetCharset, boolean strictLineBreakParsing) {
-        this(null, targetCharset, strictLineBreakParsing);
-    }
-    
-    /**
-     * @hide sourceCharset is temporal. 
-     */
-    public VNodeBuilder(String sourceCharset, String targetCharset,
-            boolean strictLineBreakParsing) {
-        if (sourceCharset != null) {
-            mSourceCharset = sourceCharset;
-        } else {
-            mSourceCharset = VCardConfig.DEFAULT_INTERMEDIATE_CHARSET;
-        }
+        mSourceCharset = VCardConfig.DEFAULT_INTERMEDIATE_CHARSET;
         if (targetCharset != null) {
             mTargetCharset = targetCharset;
         } else {