make sure to update a surface's usage bits when it changes, instead of only the first time.

also fixed a few locking issues in Surface and commented how each member is protected.
diff --git a/include/ui/Surface.h b/include/ui/Surface.h
index 4ff0e4a..30ab82f 100644
--- a/include/ui/Surface.h
+++ b/include/ui/Surface.h
@@ -146,16 +146,16 @@
     static bool isValid(const sp<Surface>& surface) {
         return (surface != 0) && surface->isValid();
     }
-    bool isValid() {
-        return mToken>=0 && mClient!=0;
-    }
+
     static bool isSameSurface(
             const sp<Surface>& lhs, const sp<Surface>& rhs);
-    SurfaceID   ID() const      { return mToken; }
-    uint32_t    getFlags() const { return mFlags; }
+
+    bool        isValid();
+    SurfaceID   ID() const          { return mToken; }
+    uint32_t    getFlags() const    { return mFlags; }
     uint32_t    getIdentity() const { return mIdentity; }
 
-
+    // the lock/unlock APIs must be used from the same thread
     status_t    lock(SurfaceInfo* info, bool blocking = true);
     status_t    lock(SurfaceInfo* info, Region* dirty, bool blocking = true);
     status_t    unlockAndPost();
@@ -175,14 +175,18 @@
     friend class SurfaceComposerClient;
     friend class SurfaceControl;
 
+    
     // camera and camcorder need access to the ISurface binder interface for preview
     friend class Camera;
     friend class MediaRecorder;
     // mediaplayer needs access to ISurface for display
     friend class MediaPlayer;
-    friend class Test;
     friend class IOMX;
-    const sp<ISurface>& getISurface() const { return mSurface; }
+    // this is just to be able to write some unit tests
+    friend class Test;
+
+    sp<SurfaceComposerClient> getClient() const;
+    sp<ISurface> getISurface() const;
 
     status_t getBufferLocked(int index, int usage);
    
@@ -210,24 +214,38 @@
     status_t queueBuffer(const sp<SurfaceBuffer>& buffer);
 
     
-    alloc_device_t*             mAllocDevice;
+    void setUsage(uint32_t reqUsage);
+    
+    // constants
     sp<SurfaceComposerClient>   mClient;
     sp<ISurface>                mSurface;
-    sp<SurfaceBuffer>           mBuffers[2];
-    sp<SurfaceBuffer>           mLockedBuffer;
     SurfaceID                   mToken;
     uint32_t                    mIdentity;
-    uint32_t                    mWidth;
-    uint32_t                    mHeight;
-    uint32_t                    mUsage;
     PixelFormat                 mFormat;
     uint32_t                    mFlags;
-    mutable Region              mDirtyRegion;
-    mutable Region              mOldDirtyRegion;
-    mutable uint8_t             mBackbufferIndex;
-    mutable Mutex               mSurfaceLock;
-    Rect                        mSwapRectangle;
     BufferMapper&               mBufferMapper;
+
+    // protected by mSurfaceLock
+    Rect                        mSwapRectangle;
+    uint32_t                    mUsage;
+    bool                        mUsageChanged;
+    
+    // protected by mSurfaceLock. These are also used from lock/unlock
+    // but in that case, they must be called form the same thread.
+    sp<SurfaceBuffer>           mBuffers[2];
+    mutable Region              mDirtyRegion;
+    mutable uint8_t             mBackbufferIndex;
+
+    // must be used from the lock/unlock thread
+    sp<SurfaceBuffer>           mLockedBuffer;
+    mutable Region              mOldDirtyRegion;
+
+    // query() must be called from dequeueBuffer() thread
+    uint32_t                    mWidth;
+    uint32_t                    mHeight;
+
+    // Inherently thread-safe
+    mutable Mutex               mSurfaceLock;
 };
 
 }; // namespace android
diff --git a/libs/ui/Surface.cpp b/libs/ui/Surface.cpp
index 2b6905f..f6792c4 100644
--- a/libs/ui/Surface.cpp
+++ b/libs/ui/Surface.cpp
@@ -382,9 +382,9 @@
 Surface::Surface(const sp<SurfaceControl>& surface)
     : mClient(surface->mClient), mSurface(surface->mSurface),
       mToken(surface->mToken), mIdentity(surface->mIdentity),
-      mWidth(surface->mWidth), mHeight(surface->mHeight),
       mFormat(surface->mFormat), mFlags(surface->mFlags),
-      mBufferMapper(BufferMapper::get())
+      mBufferMapper(BufferMapper::get()),
+      mWidth(surface->mWidth), mHeight(surface->mHeight)
 {
     init();
 }
@@ -426,9 +426,9 @@
     const_cast<uint32_t&>(android_native_window_t::flags) = 0;
     // be default we request a hardware surface
     mUsage = GRALLOC_USAGE_HW_RENDER;
+    mUsageChanged = true;
 }
 
-
 Surface::~Surface()
 {
     // this is a client-side operation, the surface is destroyed, unmap
@@ -446,11 +446,24 @@
     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(per_client_cblk_t const* cblk) const
 {
+    sp<SurfaceComposerClient> client(getClient());
     if (mToken<0 || mClient==0) {
         LOGE("invalid token (%d, identity=%u) or client (%p)", 
-                mToken, mIdentity, mClient.get());
+                mToken, mIdentity, client.get());
         return NO_INIT;
     }
     if (cblk == 0) {
@@ -477,6 +490,7 @@
 {
     if (lhs == 0 || rhs == 0)
         return false;
+
     return lhs->mSurface->asBinder() == rhs->mSurface->asBinder();
 }
 
@@ -532,10 +546,9 @@
 {
     android_native_buffer_t* out;
     status_t err = dequeueBuffer(&out);
-    *buffer = SurfaceBuffer::getSelf(out);
-    // reset the width/height with the what we get from the buffer
-    mWidth  = uint32_t(out->width);
-    mHeight = uint32_t(out->height);
+    if (err == NO_ERROR) {
+        *buffer = SurfaceBuffer::getSelf(out);
+    }
     return err;
 }
 
@@ -557,7 +570,8 @@
 
     Mutex::Autolock _l(mSurfaceLock);
 
-    per_client_cblk_t* const cblk = mClient->mControl;
+    sp<SurfaceComposerClient> client(getClient());
+    per_client_cblk_t* const cblk = client->mControl;
     status_t err = validate(cblk);
     if (err != NO_ERROR)
         return err;
@@ -572,14 +586,17 @@
 
     mBackbufferIndex = backIdx;
     layer_cblk_t* const lcblk = &(cblk->layers[index]);
-
     volatile const surface_info_t* const back = lcblk->surface + backIdx;
-    if (back->flags & surface_info_t::eNeedNewBuffer) {
+    if ((back->flags & surface_info_t::eNeedNewBuffer) || mUsageChanged) {
+        mUsageChanged = false;
         err = getBufferLocked(backIdx, mUsage);
     }
 
     if (err == NO_ERROR) {
         const sp<SurfaceBuffer>& backBuffer(mBuffers[backIdx]);
+        // reset the width/height with the what we get from the buffer
+        mWidth  = uint32_t(backBuffer->width);
+        mHeight = uint32_t(backBuffer->height);
         mDirtyRegion.set(backBuffer->width, backBuffer->height);
         *buffer = backBuffer.get();
     }
@@ -591,7 +608,8 @@
 {
     Mutex::Autolock _l(mSurfaceLock);
 
-    per_client_cblk_t* const cblk = mClient->mControl;
+    sp<SurfaceComposerClient> client(getClient());
+    per_client_cblk_t* const cblk = client->mControl;
     status_t err = validate(cblk);
     if (err != NO_ERROR)
         return err;
@@ -604,7 +622,8 @@
 {   
     Mutex::Autolock _l(mSurfaceLock);
 
-    per_client_cblk_t* const cblk = mClient->mControl;
+    sp<SurfaceComposerClient> client(getClient());
+    per_client_cblk_t* const cblk = client->mControl;
     status_t err = validate(cblk);
     if (err != NO_ERROR)
         return err;
@@ -620,7 +639,7 @@
 
     uint32_t newstate = cblk->unlock_layer_and_post(size_t(index));
     if (!(newstate & eNextFlipPending))
-        mClient->signalServer();
+        client->signalServer();
 
     return NO_ERROR;
 }
@@ -646,7 +665,7 @@
     int res = NO_ERROR;
     switch (operation) {
         case NATIVE_WINDOW_SET_USAGE:
-            mUsage = va_arg(args, int);
+            setUsage( va_arg(args, int) );
             break;
         default:
             res = NAME_NOT_FOUND;
@@ -655,6 +674,15 @@
     return res;
 }
 
+void Surface::setUsage(uint32_t reqUsage)
+{
+    Mutex::Autolock _l(mSurfaceLock);
+    if (mUsage != reqUsage) {
+        mUsageChanged = true;
+        mUsage = reqUsage;
+    }
+}
+
 // ----------------------------------------------------------------------------
 
 status_t Surface::lock(SurfaceInfo* info, bool blocking) {
@@ -663,11 +691,9 @@
 
 status_t Surface::lock(SurfaceInfo* other, Region* dirtyIn, bool blocking) 
 {
-    // FIXME: needs some locking here
-
     // we're intending to do software rendering from this point
-    mUsage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN;
-    
+    setUsage(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
+
     sp<SurfaceBuffer> backBuffer;
     status_t err = dequeueBuffer(&backBuffer);
     if (err == NO_ERROR) {
@@ -679,7 +705,8 @@
             Region scratch(bounds);
             Region& newDirtyRegion(dirtyIn ? *dirtyIn : scratch);
 
-            per_client_cblk_t* const cblk = mClient->mControl;
+            sp<SurfaceComposerClient> client(getClient());
+            per_client_cblk_t* const cblk = client->mControl;
             layer_cblk_t* const lcblk = &(cblk->layers[SurfaceID(mToken)]);
             volatile const surface_info_t* const back = lcblk->surface + mBackbufferIndex;
             if (back->flags & surface_info_t::eBufferDirty) {
@@ -725,8 +752,6 @@
     
 status_t Surface::unlockAndPost() 
 {
-    // FIXME: needs some locking here
-
     if (mLockedBuffer == 0)
         return BAD_VALUE;
 
@@ -753,13 +778,17 @@
 }
 
 void Surface::setSwapRectangle(const Rect& r) {
+    Mutex::Autolock _l(mSurfaceLock);
     mSwapRectangle = r;
 }
 
 status_t Surface::getBufferLocked(int index, int usage)
 {
+    sp<ISurface> s(mSurface);
+    if (s == 0) return NO_INIT;
+
     status_t err = NO_MEMORY;
-    sp<SurfaceBuffer> buffer = mSurface->getBuffer(usage);
+    sp<SurfaceBuffer> buffer = s->getBuffer(usage);
     LOGE_IF(buffer==0, "ISurface::getBuffer() returned NULL");
     if (buffer != 0) {
         sp<SurfaceBuffer>& currentBuffer(mBuffers[index]);