Merge change 25523 into eclair

* changes:
  Add additional error checking, exit early if errors occur.
diff --git a/cmds/keystore/netkeystore.c b/cmds/keystore/netkeystore.c
index 83c7871..87fdc80 100644
--- a/cmds/keystore/netkeystore.c
+++ b/cmds/keystore/netkeystore.c
@@ -116,10 +116,13 @@
 
 static int is_alnum_string(char *s)
 {
+    char *s0 = s;
     while (*s != 0) {
-        if (!isalnum(*s++)) return 0;
+        if (!isalnum(*s++)) {
+            LOGE("The string '%s' is not an alphanumeric string\n", s0);
+            return 0;
+        }
     }
-    LOGE("The string %s is not an alphanumeric string\n", s);
     return 1;
 }
 
@@ -159,7 +162,9 @@
 // no argument
 static void do_get_state(LPC_MARSHAL *cmd, LPC_MARSHAL *reply)
 {
-    reply->retcode = get_state();
+    int s = get_state();
+    if (DBG) LOGD("keystore state = %d\n", s);
+    reply->retcode = s;
 }
 
 // args of listkeys():
@@ -413,12 +418,10 @@
 
         // read the command, execute and send the result back.
         if(read_marshal(s, &cmd)) goto err;
-        if (DBG) LOGD("new connection\n");
         execute(&cmd, &reply);
         write_marshal(s, &reply);
 err:
         memset(&reply, 0, sizeof(LPC_MARSHAL));
-        if (DBG) LOGD("closing connection\n");
         close(s);
     }
 
diff --git a/include/private/ui/SharedBufferStack.h b/include/private/ui/SharedBufferStack.h
index 8b0f154..c02b2e7 100644
--- a/include/private/ui/SharedBufferStack.h
+++ b/include/private/ui/SharedBufferStack.h
@@ -69,12 +69,6 @@
 
 // ----------------------------------------------------------------------------
 
-struct FlatRegion { // 12 bytes
-    static const unsigned int NUM_RECT_MAX = 1;
-    uint32_t    count;
-    uint16_t    rects[4*NUM_RECT_MAX];
-};
-
 // should be 128 bytes (32 longs)
 class SharedBufferStack
 {
@@ -84,6 +78,18 @@
     friend class SharedBufferServer;
 
 public:
+    struct FlatRegion { // 12 bytes
+        static const unsigned int NUM_RECT_MAX = 1;
+        uint32_t    count;
+        uint16_t    rects[4*NUM_RECT_MAX];
+    };
+    
+    struct Statistics { // 4 longs
+        typedef int32_t usecs_t;
+        usecs_t  totalTime;
+        usecs_t  reserved[3];
+    };
+    
     SharedBufferStack();
     void init(int32_t identity);
     status_t setDirtyRegion(int buffer, const Region& reg);
@@ -100,7 +106,8 @@
     volatile int32_t reallocMask;
 
     int32_t     identity;       // surface's identity (const)
-    int32_t     reserved32[13];
+    int32_t     reserved32[9];
+    Statistics  stats;
     FlatRegion  dirtyRegion[NUM_BUFFER_MAX];    // 12*4=48 bytes
 };
 
@@ -223,7 +230,7 @@
     status_t queue(int buf);
     bool needNewBuffer(int buffer) const;
     status_t setDirtyRegion(int buffer, const Region& reg);
-
+    
 private:
     friend struct Condition;
     friend struct DequeueCondition;
@@ -257,6 +264,8 @@
     };
 
     int32_t tail;
+    // statistics...
+    nsecs_t mDequeueTime[NUM_BUFFER_MAX];
 };
 
 // ----------------------------------------------------------------------------
@@ -275,6 +284,9 @@
     
     Region getDirtyRegion(int buffer) const;
 
+    SharedBufferStack::Statistics getStats() const;
+    
+
 private:
     struct UnlockUpdate : public UpdateBase {
         const int lockedBuffer;
diff --git a/include/ui/Surface.h b/include/ui/Surface.h
index 118fb83..2cedeb6 100644
--- a/include/ui/Surface.h
+++ b/include/ui/Surface.h
@@ -212,7 +212,7 @@
 
     
     void setUsage(uint32_t reqUsage);
-    bool getUsage(uint32_t* usage);
+    uint32_t getUsage() const;
     
     // constants
     sp<SurfaceComposerClient>   mClient;
@@ -227,7 +227,6 @@
     // protected by mSurfaceLock
     Rect                        mSwapRectangle;
     uint32_t                    mUsage;
-    int32_t                     mUsageChanged;
     
     // protected by mSurfaceLock. These are also used from lock/unlock
     // but in that case, they must be called form the same thread.
diff --git a/include/utils/ResourceTypes.h b/include/utils/ResourceTypes.h
index e524e2a..17ccad6 100644
--- a/include/utils/ResourceTypes.h
+++ b/include/utils/ResourceTypes.h
@@ -864,6 +864,13 @@
         KEYSHIDDEN_SOFT = 0x0003,
     };
     
+    enum {
+        MASK_NAVHIDDEN = 0x000c,
+        NAVHIDDEN_ANY = 0x0000,
+        NAVHIDDEN_NO = 0x0004,
+        NAVHIDDEN_YES = 0x0008,
+    };
+    
     union {
         struct {
             uint8_t keyboard;
@@ -1011,7 +1018,8 @@
         if (orientation != o.orientation) diffs |= CONFIG_ORIENTATION;
         if (density != o.density) diffs |= CONFIG_DENSITY;
         if (touchscreen != o.touchscreen) diffs |= CONFIG_TOUCHSCREEN;
-        if (((inputFlags^o.inputFlags)&MASK_KEYSHIDDEN) != 0) diffs |= CONFIG_KEYBOARD_HIDDEN;
+        if (((inputFlags^o.inputFlags)&(MASK_KEYSHIDDEN|MASK_NAVHIDDEN)) != 0)
+                diffs |= CONFIG_KEYBOARD_HIDDEN;
         if (keyboard != o.keyboard) diffs |= CONFIG_KEYBOARD;
         if (navigation != o.navigation) diffs |= CONFIG_NAVIGATION;
         if (screenSize != o.screenSize) diffs |= CONFIG_SCREEN_SIZE;
@@ -1082,6 +1090,11 @@
                 if (!(o.inputFlags & MASK_KEYSHIDDEN)) return true;
             }
 
+            if (((inputFlags^o.inputFlags) & MASK_NAVHIDDEN) != 0) {
+                if (!(inputFlags & MASK_NAVHIDDEN)) return false;
+                if (!(o.inputFlags & MASK_NAVHIDDEN)) return true;
+            }
+
             if (keyboard != o.keyboard) {
                 if (!keyboard) return false;
                 if (!o.keyboard) return true;
@@ -1225,6 +1238,18 @@
                     }
                 }
 
+                const int navHidden = inputFlags & MASK_NAVHIDDEN;
+                const int oNavHidden = o.inputFlags & MASK_NAVHIDDEN;
+                if (navHidden != oNavHidden) {
+                    const int reqNavHidden =
+                            requested->inputFlags & MASK_NAVHIDDEN;
+                    if (reqNavHidden) {
+
+                        if (!navHidden) return false;
+                        if (!oNavHidden) return true;
+                    }
+                }
+
                 if ((keyboard != o.keyboard) && requested->keyboard) {
                     return (keyboard);
                 }
@@ -1332,6 +1357,12 @@
                     return false;
                 }
             }
+            const int navHidden = inputFlags&MASK_NAVHIDDEN;
+            const int setNavHidden = settings.inputFlags&MASK_NAVHIDDEN;
+            if (setNavHidden != 0 && navHidden != 0
+                && navHidden != setNavHidden) {
+                return false;
+            }
             if (settings.keyboard != 0 && keyboard != 0
                 && keyboard != settings.keyboard) {
                 return false;
diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp
index 4f7500f..add358b 100644
--- a/libs/audioflinger/AudioFlinger.cpp
+++ b/libs/audioflinger/AudioFlinger.cpp
@@ -2069,7 +2069,7 @@
    }
 }
 
-AudioFlinger::PlaybackThread::TrackBase::~TrackBase()
+AudioFlinger::ThreadBase::TrackBase::~TrackBase()
 {
     if (mCblk) {
         mCblk->~audio_track_cblk_t();   // destroy our shared-structure.
@@ -2081,7 +2081,7 @@
     mClient.clear();
 }
 
-void AudioFlinger::PlaybackThread::TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer)
+void AudioFlinger::ThreadBase::TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer)
 {
     buffer->raw = 0;
     mFrameCount = buffer->frameCount;
@@ -2089,7 +2089,7 @@
     buffer->frameCount = 0;
 }
 
-bool AudioFlinger::PlaybackThread::TrackBase::step() {
+bool AudioFlinger::ThreadBase::TrackBase::step() {
     bool result;
     audio_track_cblk_t* cblk = this->cblk();
 
@@ -2101,7 +2101,7 @@
     return result;
 }
 
-void AudioFlinger::PlaybackThread::TrackBase::reset() {
+void AudioFlinger::ThreadBase::TrackBase::reset() {
     audio_track_cblk_t* cblk = this->cblk();
 
     cblk->user = 0;
@@ -2112,20 +2112,20 @@
     LOGV("TrackBase::reset");
 }
 
-sp<IMemory> AudioFlinger::PlaybackThread::TrackBase::getCblk() const
+sp<IMemory> AudioFlinger::ThreadBase::TrackBase::getCblk() const
 {
     return mCblkMemory;
 }
 
-int AudioFlinger::PlaybackThread::TrackBase::sampleRate() const {
+int AudioFlinger::ThreadBase::TrackBase::sampleRate() const {
     return (int)mCblk->sampleRate;
 }
 
-int AudioFlinger::PlaybackThread::TrackBase::channelCount() const {
+int AudioFlinger::ThreadBase::TrackBase::channelCount() const {
     return (int)mCblk->channels;
 }
 
-void* AudioFlinger::PlaybackThread::TrackBase::getBuffer(uint32_t offset, uint32_t frames) const {
+void* AudioFlinger::ThreadBase::TrackBase::getBuffer(uint32_t offset, uint32_t frames) const {
     audio_track_cblk_t* cblk = this->cblk();
     int8_t *bufferStart = (int8_t *)mBuffer + (offset-cblk->serverBase)*cblk->frameSize;
     int8_t *bufferEnd = bufferStart + frames * cblk->frameSize;
diff --git a/libs/surfaceflinger/BlurFilter.cpp b/libs/surfaceflinger/BlurFilter.cpp
index 5dc0ba0..1ffbd5b 100644
--- a/libs/surfaceflinger/BlurFilter.cpp
+++ b/libs/surfaceflinger/BlurFilter.cpp
@@ -111,6 +111,50 @@
     }
 };
 
+template <int FACTOR = 0>
+struct BlurColor888X
+{
+    typedef uint32_t type;
+    int r, g, b;    
+    inline BlurColor888X() { }
+    inline BlurColor888X(uint32_t v) {
+        v = BLUR_RGBA_TO_HOST(v);
+        r = v & 0xFF;
+        g = (v >>  8) & 0xFF;
+        b = (v >> 16) & 0xFF;
+    }
+    inline void clear() { r=g=b=0; }
+    inline uint32_t to(int shift, int last, int dither) const {
+        int R = r;
+        int G = g;
+        int B = b;
+        if  (UNLIKELY(last)) {
+            if (FACTOR>0) {
+                int L = (R+G+G+B)>>2;
+                R += ((L - R) * FACTOR) >> 8;
+                G += ((L - G) * FACTOR) >> 8;
+                B += ((L - B) * FACTOR) >> 8;
+            }
+        }
+        R >>= shift;
+        G >>= shift;
+        B >>= shift;
+        return BLUR_HOST_TO_RGBA((0xFF<<24) | (B<<16) | (G<<8) | R);
+    }    
+    inline BlurColor888X& operator += (const BlurColor888X& rhs) {
+        r += rhs.r;
+        g += rhs.g;
+        b += rhs.b;
+        return *this;
+    }
+    inline BlurColor888X& operator -= (const BlurColor888X& rhs) {
+        r -= rhs.r;
+        g -= rhs.g;
+        b -= rhs.b;
+        return *this;
+    }
+};
+
 struct BlurGray565
 {
     typedef uint16_t type;
@@ -316,7 +360,13 @@
         int kernelSizeUser,
         int repeat)
 {
-    return blurFilter< BlurColor565<0x80> >(image, image, kernelSizeUser, repeat);
+    status_t err = BAD_VALUE;
+    if (image->format == GGL_PIXEL_FORMAT_RGB_565) {
+        err = blurFilter< BlurColor565<0x80> >(image, image, kernelSizeUser, repeat);
+    } else if (image->format == GGL_PIXEL_FORMAT_RGBX_8888) {
+        err = blurFilter< BlurColor888X<0x80> >(image, image, kernelSizeUser, repeat);
+    }
+    return err;
 }
 
 } // namespace android
diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
index d893f0a..cc913cb 100644
--- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
+++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
@@ -174,6 +174,13 @@
 
     surface = eglCreateWindowSurface(display, config, mNativeWindow.get(), NULL);
 
+    if (mFlags & UPDATE_ON_DEMAND) {
+        // if we have update on demand, we definitely don't need to
+        // preserve the backbuffer, which is usually costly.
+        eglSurfaceAttrib(display, surface,
+                EGL_SWAP_BEHAVIOR, EGL_BUFFER_DESTROYED);
+    }
+
     if (eglQuerySurface(display, surface, EGL_SWAP_BEHAVIOR, &dummy) == EGL_TRUE) {
         if (dummy == EGL_BUFFER_PRESERVED) {
             mFlags |= BUFFER_PRESERVED;
diff --git a/libs/surfaceflinger/Layer.cpp b/libs/surfaceflinger/Layer.cpp
index 1e7f1e6..7387c85 100644
--- a/libs/surfaceflinger/Layer.cpp
+++ b/libs/surfaceflinger/Layer.cpp
@@ -303,7 +303,6 @@
 
     // Index of the back buffer
     const bool backbufferChanged = (front.w != temp.w) || (front.h != temp.h);
-
     if (backbufferChanged) {
         // the size changed, we need to ask our client to request a new buffer
         LOGD_IF(DEBUG_RESIZE,
@@ -318,17 +317,6 @@
         // buffer, it'll get the new size.
         setDrawingSize(temp.w, temp.h);
 
-        // all buffers need reallocation
-        lcblk->reallocate();
-
-        // recompute the visible region
-        // FIXME: ideally we would do that only when we have received
-        // a buffer of the right size
-        flags |= Layer::eVisibleRegion;
-        this->contentDirty = true;
-        
-#if 0 
-        // FIXME: handle freeze lock
         // 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
@@ -340,7 +328,12 @@
                 mFreezeLock = mFlinger->getFreezeLock();
             }
         }
-#endif
+
+        // recompute the visible region
+        flags |= Layer::eVisibleRegion;
+        this->contentDirty = true;
+        // all buffers need reallocation
+        lcblk->reallocate();
     }
 
     if (temp.sequence != front.sequence) {
@@ -382,6 +375,13 @@
     const Region dirty(lcblk->getDirtyRegion(buf));
     mPostedDirtyRegion = dirty.intersect( newFrontBuffer->getBounds() );
 
+
+    const Layer::State& front(drawingState());
+    if (newFrontBuffer->getWidth() == front.w &&
+        newFrontBuffer->getHeight() ==front.h) {
+        mFreezeLock.clear();
+    }
+
     // FIXME: signal an event if we have more buffers waiting
     // mFlinger->signalEvent();
 
diff --git a/libs/surfaceflinger/LayerBlur.cpp b/libs/surfaceflinger/LayerBlur.cpp
index e14f35b..0ef663f 100644
--- a/libs/surfaceflinger/LayerBlur.cpp
+++ b/libs/surfaceflinger/LayerBlur.cpp
@@ -40,9 +40,9 @@
 
 LayerBlur::LayerBlur(SurfaceFlinger* flinger, DisplayID display,
         const sp<Client>& client, int32_t i)
-     : LayerBaseClient(flinger, display, client, i), mCacheDirty(true),
-     mRefreshCache(true), mCacheAge(0), mTextureName(-1U), 
-     mWidthScale(1.0f), mHeightScale(1.0f)
+: LayerBaseClient(flinger, display, client, i), mCacheDirty(true),
+mRefreshCache(true), mCacheAge(0), mTextureName(-1U), 
+mWidthScale(1.0f), mHeightScale(1.0f)
 {
 }
 
@@ -136,6 +136,13 @@
         // create the texture name the first time
         // can't do that in the ctor, because it runs in another thread.
         glGenTextures(1, &mTextureName);
+        glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES, &mReadFormat);
+        glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE_OES, &mReadType);
+        if (mReadFormat != GL_RGB || mReadType != GL_UNSIGNED_SHORT_5_6_5) {
+            mReadFormat = GL_RGBA;
+            mReadType = GL_UNSIGNED_BYTE;
+            mBlurFormat = GGL_PIXEL_FORMAT_RGBX_8888;
+        }
     }
 
     Region::const_iterator it = clip.begin();
@@ -143,33 +150,39 @@
     if (it != end) {
         glEnable(GL_TEXTURE_2D);
         glBindTexture(GL_TEXTURE_2D, mTextureName);
-    
+
         if (mRefreshCache) {
             mRefreshCache = false;
             mAutoRefreshPending = false;
-            
-            // allocate enough memory for 4-bytes (2 pixels) aligned data
-            const int32_t s = (w + 1) & ~1;
-            uint16_t* const pixels = (uint16_t*)malloc(s*h*2);
+
+            int32_t pixelSize = 4;
+            int32_t s = w;
+            if (mReadType == GL_UNSIGNED_SHORT_5_6_5) {
+                // allocate enough memory for 4-bytes (2 pixels) aligned data
+                s = (w + 1) & ~1;
+                pixelSize = 2;
+            }
+
+            uint16_t* const pixels = (uint16_t*)malloc(s*h*pixelSize);
 
             // This reads the frame-buffer, so a h/w GL would have to
             // finish() its rendering first. we don't want to do that
             // too often. Read data is 4-bytes aligned.
-            glReadPixels(X, Y, w, h, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pixels);
-            
+            glReadPixels(X, Y, w, h, mReadFormat, mReadType, pixels);
+
             // blur that texture.
             GGLSurface bl;
             bl.version = sizeof(GGLSurface);
             bl.width = w;
             bl.height = h;
             bl.stride = s;
-            bl.format = GGL_PIXEL_FORMAT_RGB_565;
+            bl.format = mBlurFormat;
             bl.data = (GGLubyte*)pixels;            
             blurFilter(&bl, 8, 2);
 
             if (mFlags & (DisplayHardware::NPOT_EXTENSION)) {
-                glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0,
-                        GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pixels);
+                glTexImage2D(GL_TEXTURE_2D, 0, mReadFormat, w, h, 0,
+                        mReadFormat, mReadType, pixels);
                 mWidthScale  = 1.0f / w;
                 mHeightScale =-1.0f / h;
                 mYOffset = 0;
@@ -178,10 +191,10 @@
                 GLuint th = 1 << (31 - clz(h));
                 if (tw < w) tw <<= 1;
                 if (th < h) th <<= 1;
-                glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tw, th, 0,
-                        GL_RGB, GL_UNSIGNED_SHORT_5_6_5, NULL);
+                glTexImage2D(GL_TEXTURE_2D, 0, mReadFormat, tw, th, 0,
+                        mReadFormat, mReadType, NULL);
                 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, 
-                        GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pixels);
+                        mReadFormat, mReadType, pixels);
                 mWidthScale  = 1.0f / tw;
                 mHeightScale =-1.0f / th;
                 mYOffset = th-h;
@@ -189,7 +202,7 @@
 
             free((void*)pixels);
         }
-        
+
         const State& s = drawingState();
         if (UNLIKELY(s.alpha < 0xFF)) {
             const GGLfixed alpha = (s.alpha << 16)/255;
diff --git a/libs/surfaceflinger/LayerBlur.h b/libs/surfaceflinger/LayerBlur.h
index bf36ae4..2e9d7c6 100644
--- a/libs/surfaceflinger/LayerBlur.h
+++ b/libs/surfaceflinger/LayerBlur.h
@@ -59,6 +59,9 @@
     mutable GLfloat mWidthScale;
     mutable GLfloat mHeightScale;
     mutable GLfloat mYOffset;
+    mutable GLint   mReadFormat;
+    mutable GLint   mReadType;
+    mutable uint32_t mBlurFormat;
 };
 
 // ---------------------------------------------------------------------------
diff --git a/libs/surfaceflinger/LayerBuffer.cpp b/libs/surfaceflinger/LayerBuffer.cpp
index bbfc54b..667571b 100644
--- a/libs/surfaceflinger/LayerBuffer.cpp
+++ b/libs/surfaceflinger/LayerBuffer.cpp
@@ -595,6 +595,7 @@
 
     *overlayRef = new OverlayRef(mOverlayHandle, channel,
             mWidth, mHeight, mFormat, mWidthStride, mHeightStride);
+    mLayer.mFlinger->signalEvent();
 }
 
 LayerBuffer::OverlaySource::~OverlaySource()
@@ -607,9 +608,10 @@
 
 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 = 0x1818;
+    GLclampx blue = 0;
     mLayer.clearWithOpenGL(clip, red, green, blue, 0);
 }
 
diff --git a/libs/surfaceflinger/SurfaceFlinger.cpp b/libs/surfaceflinger/SurfaceFlinger.cpp
index a352431..31b5128 100644
--- a/libs/surfaceflinger/SurfaceFlinger.cpp
+++ b/libs/surfaceflinger/SurfaceFlinger.cpp
@@ -1521,6 +1521,7 @@
             /*** Layer ***/
             sp<Layer> l = LayerBase::dynamicCast< Layer* >(layer.get());
             if (l != 0) {
+                SharedBufferStack::Statistics stats = l->lcblk->getStats();
                 result.append( l->lcblk->dump("      ") );
                 sp<const Buffer> buf0(l->getBuffer(0));
                 sp<const Buffer> buf1(l->getBuffer(1));
@@ -1539,10 +1540,10 @@
                 snprintf(buffer, SIZE,
                         "      "
                         "format=%2d, [%3ux%3u:%3u] [%3ux%3u:%3u],"
-                        " freezeLock=%p\n",
+                        " freezeLock=%p, dq-q-time=%u us\n",
                         l->pixelFormat(),
                         w0, h0, s0, w1, h1, s1,
-                        l->getFreezeLock().get());
+                        l->getFreezeLock().get(), stats.totalTime);
                 result.append(buffer);
                 buffer[0] = 0;
             }
diff --git a/libs/ui/SharedBufferStack.cpp b/libs/ui/SharedBufferStack.cpp
index 7789a3f..9ad4349 100644
--- a/libs/ui/SharedBufferStack.cpp
+++ b/libs/ui/SharedBufferStack.cpp
@@ -276,6 +276,8 @@
         LOGW("dequeue: tail=%d, head=%d, avail=%d, queued=%d",
                 tail, stack.head, stack.available, stack.queued);
     }
+        
+    const nsecs_t dequeueTime = systemTime(SYSTEM_TIME_THREAD);
 
     //LOGD("[%d] about to dequeue a buffer",
     //        mSharedStack->identity);
@@ -296,6 +298,8 @@
     LOGD_IF(DEBUG_ATOMICS, "dequeued=%d, tail=%d, %s",
             dequeued, tail, dump("").string());
 
+    mDequeueTime[dequeued] = dequeueTime; 
+
     return dequeued;
 }
 
@@ -312,7 +316,7 @@
 status_t SharedBufferClient::lock(int buf)
 {
     LockCondition condition(this, buf);
-    status_t err = waitForCondition(condition);    
+    status_t err = waitForCondition(condition);
     return err;
 }
 
@@ -321,6 +325,9 @@
     QueueUpdate update(this);
     status_t err = updateCondition( update );
     LOGD_IF(DEBUG_ATOMICS, "queued=%d, %s", buf, dump("").string());
+    SharedBufferStack& stack( *mSharedStack );
+    const nsecs_t now = systemTime(SYSTEM_TIME_THREAD);
+    stack.stats.totalTime = ns2us(now - mDequeueTime[buf]);
     return err;
 }
 
@@ -393,5 +400,12 @@
     return stack.getDirtyRegion(buffer);
 }
 
+SharedBufferStack::Statistics SharedBufferServer::getStats() const
+{
+    SharedBufferStack& stack( *mSharedStack );
+    return stack.stats;
+}
+
+
 // ---------------------------------------------------------------------------
 }; // namespace android
diff --git a/libs/ui/Surface.cpp b/libs/ui/Surface.cpp
index c3fbea2..64522fb 100644
--- a/libs/ui/Surface.cpp
+++ b/libs/ui/Surface.cpp
@@ -361,7 +361,6 @@
     const_cast<uint32_t&>(android_native_window_t::flags) = 0;
     // be default we request a hardware surface
     mUsage = GRALLOC_USAGE_HW_RENDER;
-    mUsageChanged = true;
     mNeedFullUpdate = false;
 }
 
@@ -498,14 +497,14 @@
         LOGE("error dequeuing a buffer (%s)", strerror(bufIdx));
         return bufIdx;
     }
-    
-    // FIXME: in case of failure below, we need to undo the dequeue
-    
-    uint32_t usage;
-    const bool usageChanged = getUsage(&usage);
+
+    // below we make sure we AT LEAST have the usage flags we want
+    const uint32_t usage(getUsage());
     const sp<SurfaceBuffer>& backBuffer(mBuffers[bufIdx]);
-    if ((backBuffer == 0) || usageChanged || 
-            mSharedBufferClient->needNewBuffer(bufIdx)) {
+    if (backBuffer == 0 || 
+        ((uint32_t(backBuffer->usage) & usage) != usage) ||
+        mSharedBufferClient->needNewBuffer(bufIdx)) 
+    {
         err = getBufferLocked(bufIdx, usage);
         LOGE_IF(err, "getBufferLocked(%ld, %08x) failed (%s)",
                 bufIdx, usage, strerror(-err));
@@ -600,21 +599,13 @@
 void Surface::setUsage(uint32_t reqUsage)
 {
     Mutex::Autolock _l(mSurfaceLock);
-    if (mUsage != reqUsage) {
-        mUsageChanged = true;
-        mUsage = reqUsage;
-    }
+    mUsage = reqUsage;
 }
 
-bool Surface::getUsage(uint32_t* usage)
+uint32_t Surface::getUsage() const
 {
     Mutex::Autolock _l(mSurfaceLock);
-    *usage = mUsage;
-    if (mUsageChanged) {
-        mUsageChanged = false;
-        return true;
-    }
-    return false;
+    return mUsage;
 }
 
 // ----------------------------------------------------------------------------