Merge change 21221 into eclair

* changes:
  Modify svc power command so it pokes the wake lock when called. This will ensure screen is not asleep if stayon is requested.
diff --git a/include/binder/Parcel.h b/include/binder/Parcel.h
index 58c2d9a..ba6c711 100644
--- a/include/binder/Parcel.h
+++ b/include/binder/Parcel.h
@@ -74,6 +74,7 @@
     status_t            writeInt64(int64_t val);
     status_t            writeFloat(float val);
     status_t            writeDouble(double val);
+    status_t            writeIntPtr(intptr_t val);
     status_t            writeCString(const char* str);
     status_t            writeString8(const String8& str);
     status_t            writeString16(const String16& str);
@@ -109,6 +110,8 @@
     status_t            readFloat(float *pArg) const;
     double              readDouble() const;
     status_t            readDouble(double *pArg) const;
+    intptr_t            readIntPtr() const;
+    status_t            readIntPtr(intptr_t *pArg) const;
 
     const char*         readCString() const;
     String8             readString8() const;
@@ -163,6 +166,14 @@
     void                initState();
     void                scanForFds() const;
                         
+    template<class T>
+    status_t            readAligned(T *pArg) const;
+
+    template<class T>   T readAligned() const;
+
+    template<class T>
+    status_t            writeAligned(T val);
+
     status_t            mError;
     uint8_t*            mData;
     size_t              mDataSize;
diff --git a/include/private/ui/android_natives_priv.h b/include/private/ui/android_natives_priv.h
index ee843e9..9c92af8 100644
--- a/include/private/ui/android_natives_priv.h
+++ b/include/private/ui/android_natives_priv.h
@@ -25,7 +25,7 @@
 
 /*****************************************************************************/
 
-struct android_native_buffer_t
+typedef struct android_native_buffer_t
 {
 #ifdef __cplusplus
     android_native_buffer_t() { 
@@ -48,7 +48,7 @@
     buffer_handle_t handle;
 
     void* reserved_proc[8];
-};
+} android_native_buffer_t;
 
 
 /*****************************************************************************/
diff --git a/include/ui/ISurfaceComposer.h b/include/ui/ISurfaceComposer.h
index 1788265..25d954c 100644
--- a/include/ui/ISurfaceComposer.h
+++ b/include/ui/ISurfaceComposer.h
@@ -40,8 +40,6 @@
 
     enum { // (keep in sync with Surface.java)
         eHidden             = 0x00000004,
-        eGPU                = 0x00000008,
-        eHardware           = 0x00000010,
         eDestroyBackbuffer  = 0x00000020,
         eSecure             = 0x00000080,
         eNonPremultiplied   = 0x00000100,
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/include/ui/egl/android_natives.h b/include/ui/egl/android_natives.h
index 4c58e47..3740db5 100644
--- a/include/ui/egl/android_natives.h
+++ b/include/ui/egl/android_natives.h
@@ -43,7 +43,7 @@
 
 // ---------------------------------------------------------------------------
 
-struct android_native_base_t
+typedef struct android_native_base_t
 {
     /* a magic value defined by the actual EGL native type */
     int magic;
@@ -56,7 +56,7 @@
     /* reference-counting interface */
     void (*incRef)(struct android_native_base_t* base);
     void (*decRef)(struct android_native_base_t* base);
-};
+} android_native_base_t;
 
 // ---------------------------------------------------------------------------
 
@@ -72,7 +72,7 @@
     NATIVE_WINDOW_SET_USAGE = 0
 };
 
-struct android_native_window_t 
+typedef struct android_native_window_t 
 {
 #ifdef __cplusplus
     android_native_window_t()
@@ -166,7 +166,7 @@
                 int operation, ... );
     
     void* reserved_proc[3];
-};
+} android_native_window_t;
 
 
 /*
@@ -179,8 +179,8 @@
  *  reallocated.
  */
 
-inline int native_window_set_usage(
-        struct android_native_window_t* window, int usage)
+static inline int native_window_set_usage(
+        android_native_window_t* window, int usage)
 {
     return window->perform(window, NATIVE_WINDOW_SET_USAGE, usage);
 }
@@ -189,7 +189,7 @@
 // ---------------------------------------------------------------------------
 
 /* FIXME: this is legacy for pixmaps */
-struct egl_native_pixmap_t
+typedef struct egl_native_pixmap_t
 {
     int32_t     version;    /* must be 32 */
     int32_t     width;
@@ -203,7 +203,7 @@
         int32_t     vstride;
     };
     int32_t     reserved;
-};
+} egl_native_pixmap_t;
 
 /*****************************************************************************/
 
diff --git a/include/utils/Debug.h b/include/utils/Debug.h
index 21d04bd..d9ed32d 100644
--- a/include/utils/Debug.h
+++ b/include/utils/Debug.h
@@ -29,6 +29,8 @@
 #define COMPILE_TIME_ASSERT(_exp) \
     template class CompileTimeAssert< (_exp) >;
 #endif
+#define COMPILE_TIME_ASSERT_FUNCTION_SCOPE(_exp) \
+    CompileTimeAssert<( _exp )>();
 
 // ---------------------------------------------------------------------------
 
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 785a3c5..e397bce 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -562,54 +562,27 @@
 
 status_t Parcel::writeInt32(int32_t val)
 {
-    if ((mDataPos+sizeof(val)) <= mDataCapacity) {
-restart_write:
-        *reinterpret_cast<int32_t*>(mData+mDataPos) = val;
-        return finishWrite(sizeof(val));
-    }
-
-    status_t err = growData(sizeof(val));
-    if (err == NO_ERROR) goto restart_write;
-    return err;
+    return writeAligned(val);
 }
 
 status_t Parcel::writeInt64(int64_t val)
 {
-    if ((mDataPos+sizeof(val)) <= mDataCapacity) {
-restart_write:
-        *reinterpret_cast<int64_t*>(mData+mDataPos) = val;
-        return finishWrite(sizeof(val));
-    }
-
-    status_t err = growData(sizeof(val));
-    if (err == NO_ERROR) goto restart_write;
-    return err;
+    return writeAligned(val);
 }
 
 status_t Parcel::writeFloat(float val)
 {
-    if ((mDataPos+sizeof(val)) <= mDataCapacity) {
-restart_write:
-        *reinterpret_cast<float*>(mData+mDataPos) = val;
-        return finishWrite(sizeof(val));
-    }
-
-    status_t err = growData(sizeof(val));
-    if (err == NO_ERROR) goto restart_write;
-    return err;
+    return writeAligned(val);
 }
 
 status_t Parcel::writeDouble(double val)
 {
-    if ((mDataPos+sizeof(val)) <= mDataCapacity) {
-restart_write:
-        *reinterpret_cast<double*>(mData+mDataPos) = val;
-        return finishWrite(sizeof(val));
-    }
+    return writeAligned(val);
+}
 
-    status_t err = growData(sizeof(val));
-    if (err == NO_ERROR) goto restart_write;
-    return err;
+status_t Parcel::writeIntPtr(intptr_t val)
+{
+    return writeAligned(val);
 }
 
 status_t Parcel::writeCString(const char* str)
@@ -768,103 +741,98 @@
     return NULL;
 }
 
-status_t Parcel::readInt32(int32_t *pArg) const
-{
-    if ((mDataPos+sizeof(int32_t)) <= mDataSize) {
+template<class T>
+status_t Parcel::readAligned(T *pArg) const {
+    COMPILE_TIME_ASSERT_FUNCTION_SCOPE(PAD_SIZE(sizeof(T)) == sizeof(T));
+
+    if ((mDataPos+sizeof(T)) <= mDataSize) {
         const void* data = mData+mDataPos;
-        mDataPos += sizeof(int32_t);
-        *pArg =  *reinterpret_cast<const int32_t*>(data);
+        mDataPos += sizeof(T);
+        *pArg =  *reinterpret_cast<const T*>(data);
         return NO_ERROR;
     } else {
         return NOT_ENOUGH_DATA;
     }
 }
 
+template<class T>
+T Parcel::readAligned() const {
+    T result;
+    if (readAligned(&result) != NO_ERROR) {
+        result = 0;
+    }
+
+    return result;
+}
+
+template<class T>
+status_t Parcel::writeAligned(T val) {
+    COMPILE_TIME_ASSERT_FUNCTION_SCOPE(PAD_SIZE(sizeof(T)) == sizeof(T));
+
+    if ((mDataPos+sizeof(val)) <= mDataCapacity) {
+restart_write:
+        *reinterpret_cast<T*>(mData+mDataPos) = val;
+        return finishWrite(sizeof(val));
+    }
+
+    status_t err = growData(sizeof(val));
+    if (err == NO_ERROR) goto restart_write;
+    return err;
+}
+
+status_t Parcel::readInt32(int32_t *pArg) const
+{
+    return readAligned(pArg);
+}
+
 int32_t Parcel::readInt32() const
 {
-    if ((mDataPos+sizeof(int32_t)) <= mDataSize) {
-        const void* data = mData+mDataPos;
-        mDataPos += sizeof(int32_t);
-        LOGV("readInt32 Setting data pos of %p to %d\n", this, mDataPos);
-        return *reinterpret_cast<const int32_t*>(data);
-    }
-    return 0;
+    return readAligned<int32_t>();
 }
 
 
 status_t Parcel::readInt64(int64_t *pArg) const
 {
-    if ((mDataPos+sizeof(int64_t)) <= mDataSize) {
-        const void* data = mData+mDataPos;
-        mDataPos += sizeof(int64_t);
-        *pArg = *reinterpret_cast<const int64_t*>(data);
-        LOGV("readInt64 Setting data pos of %p to %d\n", this, mDataPos);
-        return NO_ERROR;
-    } else {
-        return NOT_ENOUGH_DATA;
-    }
+    return readAligned(pArg);
 }
 
 
 int64_t Parcel::readInt64() const
 {
-    if ((mDataPos+sizeof(int64_t)) <= mDataSize) {
-        const void* data = mData+mDataPos;
-        mDataPos += sizeof(int64_t);
-        LOGV("readInt64 Setting data pos of %p to %d\n", this, mDataPos);
-        return *reinterpret_cast<const int64_t*>(data);
-    }
-    return 0;
+    return readAligned<int64_t>();
 }
 
 status_t Parcel::readFloat(float *pArg) const
 {
-    if ((mDataPos+sizeof(float)) <= mDataSize) {
-        const void* data = mData+mDataPos;
-        mDataPos += sizeof(float);
-        LOGV("readFloat Setting data pos of %p to %d\n", this, mDataPos);
-        *pArg = *reinterpret_cast<const float*>(data);
-        return NO_ERROR;
-    } else {
-        return NOT_ENOUGH_DATA;
-    }
+    return readAligned(pArg);
 }
 
 
 float Parcel::readFloat() const
 {
-    if ((mDataPos+sizeof(float)) <= mDataSize) {
-        const void* data = mData+mDataPos;
-        mDataPos += sizeof(float);
-        LOGV("readFloat Setting data pos of %p to %d\n", this, mDataPos);
-        return *reinterpret_cast<const float*>(data);
-    }
-    return 0;
+    return readAligned<float>();
 }
 
 status_t Parcel::readDouble(double *pArg) const
 {
-    if ((mDataPos+sizeof(double)) <= mDataSize) {
-        const void* data = mData+mDataPos;
-        mDataPos += sizeof(double);
-        LOGV("readDouble Setting data pos of %p to %d\n", this, mDataPos);
-        *pArg = *reinterpret_cast<const double*>(data);
-        return NO_ERROR;
-    } else {
-        return NOT_ENOUGH_DATA;
-    }
+    return readAligned(pArg);
 }
 
 
 double Parcel::readDouble() const
 {
-    if ((mDataPos+sizeof(double)) <= mDataSize) {
-        const void* data = mData+mDataPos;
-        mDataPos += sizeof(double);
-        LOGV("readDouble Setting data pos of %p to %d\n", this, mDataPos);
-        return *reinterpret_cast<const double*>(data);
-    }
-    return 0;
+    return readAligned<double>();
+}
+
+status_t Parcel::readIntPtr(intptr_t *pArg) const
+{
+    return readAligned(pArg);
+}
+
+
+intptr_t Parcel::readIntPtr() const
+{
+    return readAligned<intptr_t>();
 }
 
 
diff --git a/libs/surfaceflinger/Layer.cpp b/libs/surfaceflinger/Layer.cpp
index 8c0b40d..6f92515 100644
--- a/libs/surfaceflinger/Layer.cpp
+++ b/libs/surfaceflinger/Layer.cpp
@@ -109,9 +109,6 @@
     if (err) return err;
 
     uint32_t bufferFlags = 0;
-    if (flags & ISurfaceComposer::eGPU)
-        bufferFlags |= Buffer::GPU;
-
     if (flags & ISurfaceComposer::eSecure)
         bufferFlags |= Buffer::SECURE;
 
@@ -599,7 +596,12 @@
 Point Layer::getPhysicalSize() const
 {
     sp<const Buffer> front(frontBuffer().getBuffer());
-    return Point(front->getWidth(), front->getHeight());
+    Point size(front->getWidth(), front->getHeight());
+    if ((size.x | size.y) == 0) {
+        // if we don't have a buffer yet, just use the state's size.
+        size = LayerBase::getPhysicalSize();
+    }
+    return size;
 }
 
 void Layer::unlockPageFlip(
diff --git a/libs/surfaceflinger/LayerBitmap.h b/libs/surfaceflinger/LayerBitmap.h
index 48ee553..87e8f42 100644
--- a/libs/surfaceflinger/LayerBitmap.h
+++ b/libs/surfaceflinger/LayerBitmap.h
@@ -53,7 +53,6 @@
 public:
     enum {
         DONT_CLEAR  = 0x00000001,
-        GPU         = 0x00000002,
         SECURE      = 0x00000004
     };
 
@@ -98,7 +97,6 @@
 public:
     enum {
         DONT_CLEAR  = Buffer::DONT_CLEAR,
-        GPU         = Buffer::GPU,
         SECURE      = Buffer::SECURE
     };
     LayerBitmap();
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]);
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index 64b82eb..03e764c 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -50,7 +50,7 @@
 #define VERSION_MAJOR 1
 #define VERSION_MINOR 4
 static char const * const gVendorString     = "Android";
-static char const * const gVersionString    = "1.31 Android META-EGL";
+static char const * const gVersionString    = "1.4 Android META-EGL";
 static char const * const gClientApiString  = "OpenGL ES";
 static char const * const gExtensionString  = 
         "EGL_KHR_image "
@@ -326,32 +326,6 @@
 
 // ----------------------------------------------------------------------------
 
-/*
- * To "loose" the GPU, use something like
- *    gEGLImpl[IMPL_HARDWARE].hooks = &gHooks[IMPL_CONTEXT_LOST];
- * 
- */
-
-static int gl_context_lost() {
-    setGlThreadSpecific(&gHooks[IMPL_CONTEXT_LOST]);
-    return 0;
-}
-static int egl_context_lost() {
-    setGlThreadSpecific(&gHooks[IMPL_CONTEXT_LOST]);
-    return EGL_FALSE;
-}
-static EGLBoolean egl_context_lost_swap_buffers(void*, void*) {
-    usleep(100000); // don't use all the CPU
-    setGlThreadSpecific(&gHooks[IMPL_CONTEXT_LOST]);
-    return EGL_FALSE;
-}
-static GLint egl_context_lost_get_error() {
-    return EGL_CONTEXT_LOST;
-}
-static int ext_context_lost() {
-    return 0;
-}
-
 static void gl_no_context() {
     tls_t* tls = getTLS();
     if (tls->logCallWithNoContext == EGL_TRUE) {
@@ -471,87 +445,82 @@
     return i->images[c->impl];
 }
 
+// ----------------------------------------------------------------------------
 
-EGLDisplay egl_init_displays(NativeDisplayType display)
+// this mutex protects:
+//    d->dpys[]
+//    egl_init_drivers_locked()
+//
+static pthread_mutex_t gInitDriverMutex = PTHREAD_MUTEX_INITIALIZER;
+
+EGLBoolean egl_init_drivers_locked()
 {
     if (sEarlyInitState) {
-        return EGL_NO_DISPLAY;
+        // initialized by static ctor. should be set here.
+        return EGL_FALSE;
     }
 
-    uint32_t index = uint32_t(display);
-    if (index >= NUM_DISPLAYS) {
-        return EGL_NO_DISPLAY;
-    }
-    
-    EGLDisplay dpy = EGLDisplay(uintptr_t(display) + 1LU);
-    egl_display_t* d = &gDisplay[index];
-
     // get our driver loader
-    Loader& loader(Loader::getInstance());    
+    Loader& loader(Loader::getInstance());
     
-    // dynamically load all our EGL implementations for that display
-    // and call into the real eglGetGisplay()
-    egl_connection_t* cnx = &gEGLImpl[IMPL_SOFTWARE];
+    // dynamically load all our EGL implementations for all displays
+    // and retrieve the corresponding EGLDisplay
+    // if that fails, don't use this driver.
+    // TODO: currently we only deal with EGL_DEFAULT_DISPLAY
+    egl_connection_t* cnx;
+    egl_display_t* d = &gDisplay[0];
+
+    cnx = &gEGLImpl[IMPL_SOFTWARE];
     if (cnx->dso == 0) {
         cnx->hooks = &gHooks[IMPL_SOFTWARE];
-        cnx->dso = loader.open(display, 0, cnx->hooks);
-    }
-    if (cnx->dso && d->dpys[IMPL_SOFTWARE]==EGL_NO_DISPLAY) {
-        d->dpys[IMPL_SOFTWARE] = cnx->hooks->egl.eglGetDisplay(display);
-        LOGE_IF(d->dpys[IMPL_SOFTWARE]==EGL_NO_DISPLAY,
-                "No EGLDisplay for software EGL!");
+        cnx->dso = loader.open(EGL_DEFAULT_DISPLAY, 0, cnx->hooks);
+        if (cnx->dso) {
+            EGLDisplay dpy = cnx->hooks->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
+            LOGE_IF(dpy==EGL_NO_DISPLAY, "No EGLDisplay for software EGL!");
+            d->dpys[IMPL_SOFTWARE] = dpy; 
+            if (dpy == EGL_NO_DISPLAY) {
+                loader.close(cnx->dso);
+                cnx->dso = NULL;
+            }
+        }
     }
 
     cnx = &gEGLImpl[IMPL_HARDWARE];
-    if (cnx->dso == 0 && cnx->unavailable == 0) {
+    if (cnx->dso == 0) {
         char value[PROPERTY_VALUE_MAX];
         property_get("debug.egl.hw", value, "1");
         if (atoi(value) != 0) {
             cnx->hooks = &gHooks[IMPL_HARDWARE];
-            cnx->dso = loader.open(display, 1, cnx->hooks);
+            cnx->dso = loader.open(EGL_DEFAULT_DISPLAY, 1, cnx->hooks);
+            if (cnx->dso) {
+                EGLDisplay dpy = cnx->hooks->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
+                LOGE_IF(dpy==EGL_NO_DISPLAY, "No EGLDisplay for hardware EGL!");
+                d->dpys[IMPL_HARDWARE] = dpy; 
+                if (dpy == EGL_NO_DISPLAY) {
+                    loader.close(cnx->dso);
+                    cnx->dso = NULL;
+                }
+            }
         } else {
             LOGD("3D hardware acceleration is disabled");
         }
     }
-    if (cnx->dso && d->dpys[IMPL_HARDWARE]==EGL_NO_DISPLAY) {
-        android_memset32(
-                (uint32_t*)(void*)&gHooks[IMPL_CONTEXT_LOST].gl,
-                (uint32_t)((void*)gl_context_lost),
-                sizeof(gHooks[IMPL_CONTEXT_LOST].gl));
-        android_memset32(
-                (uint32_t*)(void*)&gHooks[IMPL_CONTEXT_LOST].egl,
-                (uint32_t)((void*)egl_context_lost),
-                sizeof(gHooks[IMPL_CONTEXT_LOST].egl));
-        android_memset32(
-                (uint32_t*)(void*)&gHooks[IMPL_CONTEXT_LOST].ext,
-                (uint32_t)((void*)ext_context_lost),
-                sizeof(gHooks[IMPL_CONTEXT_LOST].ext));
-
-        gHooks[IMPL_CONTEXT_LOST].egl.eglSwapBuffers =
-                egl_context_lost_swap_buffers;
-        
-        gHooks[IMPL_CONTEXT_LOST].egl.eglGetError =
-                egl_context_lost_get_error;
-
-        gHooks[IMPL_CONTEXT_LOST].egl.eglTerminate =
-                gHooks[IMPL_HARDWARE].egl.eglTerminate;
-        
-        d->dpys[IMPL_HARDWARE] = cnx->hooks->egl.eglGetDisplay(display);
-        if (d->dpys[IMPL_HARDWARE] == EGL_NO_DISPLAY) {
-            LOGE("h/w accelerated eglGetDisplay() failed (%s)",
-                    egl_strerror(cnx->hooks->egl.eglGetError()));
-            
-            loader.close(cnx->dso);
-            cnx->dso = 0;
-            // in case of failure, we want to make sure we don't try again
-            // as it's expensive.
-            cnx->unavailable = 1;
-        }
+    
+    if (!gEGLImpl[IMPL_SOFTWARE].dso && !gEGLImpl[IMPL_HARDWARE].dso) {
+        return EGL_FALSE;
     }
 
-    return dpy;
+    return EGL_TRUE;
 }
 
+EGLBoolean egl_init_drivers()
+{
+    EGLBoolean res;
+    pthread_mutex_lock(&gInitDriverMutex);
+    res = egl_init_drivers_locked();
+    pthread_mutex_unlock(&gInitDriverMutex);
+    return res;
+}
 
 // ----------------------------------------------------------------------------
 }; // namespace android
@@ -561,7 +530,17 @@
 
 EGLDisplay eglGetDisplay(NativeDisplayType display)
 {
-    return egl_init_displays(display);
+    uint32_t index = uint32_t(display);
+    if (index >= NUM_DISPLAYS) {
+        return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
+    }
+
+    if (egl_init_drivers() == EGL_FALSE) {
+        return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
+    }
+    
+    EGLDisplay dpy = EGLDisplay(uintptr_t(display) + 1LU);
+    return dpy;
 }
 
 // ----------------------------------------------------------------------------
@@ -648,31 +627,25 @@
 
 EGLBoolean eglTerminate(EGLDisplay dpy)
 {
+    // NOTE: don't unload the drivers b/c some APIs can be called
+    // after eglTerminate() has been called. eglTerminate() only
+    // terminates an EGLDisplay, not a EGL itself.
+
     egl_display_t* const dp = get_display(dpy);
     if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
     if (android_atomic_dec(&dp->refs) != 1)
         return EGL_TRUE;
-        
-    Loader& loader(Loader::getInstance());    
 
     EGLBoolean res = EGL_FALSE;
     for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
         egl_connection_t* const cnx = &gEGLImpl[i];
         if (cnx->dso) {
             cnx->hooks->egl.eglTerminate(dp->dpys[i]);
-            
-            /* REVISIT: it's unclear what to do if eglTerminate() fails,
-             * on one end we shouldn't care, on the other end if it fails
-             * it might not be safe to call dlclose() (there could be some
-             * threads around). */
-            
+            // REVISIT: it's unclear what to do if eglTerminate() fails
             free(dp->configs[i]);
             free((void*)dp->queryString[i].extensions);
             dp->numConfigs[i] = 0;
             dp->dpys[i] = EGL_NO_DISPLAY;
-
-            loader.close(cnx->dso);
-            cnx->dso = 0;
             res = EGL_TRUE;
         }
     }
@@ -1022,12 +995,18 @@
 
 EGLContext eglGetCurrentContext(void)
 {
+    // could be called before eglInitialize(), but we wouldn't have a context
+    // then, and this function would correctly return EGL_NO_CONTEXT.
+
     EGLContext ctx = getContext();
     return ctx;
 }
 
 EGLSurface eglGetCurrentSurface(EGLint readdraw)
 {
+    // could be called before eglInitialize(), but we wouldn't have a context
+    // then, and this function would correctly return EGL_NO_SURFACE.
+
     EGLContext ctx = getContext();
     if (ctx) {
         egl_context_t const * const c = get_context(ctx);
@@ -1043,6 +1022,9 @@
 
 EGLDisplay eglGetCurrentDisplay(void)
 {
+    // could be called before eglInitialize(), but we wouldn't have a context
+    // then, and this function would correctly return EGL_NO_DISPLAY.
+
     EGLContext ctx = getContext();
     if (ctx) {
         egl_context_t const * const c = get_context(ctx);
@@ -1054,6 +1036,9 @@
 
 EGLBoolean eglWaitGL(void)
 {
+    // could be called before eglInitialize(), but we wouldn't have a context
+    // then, and this function would return GL_TRUE, which isn't wrong.
+
     EGLBoolean res = EGL_TRUE;
     EGLContext ctx = getContext();
     if (ctx) {
@@ -1071,6 +1056,9 @@
 
 EGLBoolean eglWaitNative(EGLint engine)
 {
+    // could be called before eglInitialize(), but we wouldn't have a context
+    // then, and this function would return GL_TRUE, which isn't wrong.
+    
     EGLBoolean res = EGL_TRUE;
     EGLContext ctx = getContext();
     if (ctx) {
@@ -1107,9 +1095,11 @@
     // eglGetProcAddress() could be the very first function called
     // in which case we must make sure we've initialized ourselves, this
     // happens the first time egl_get_display() is called.
-    
-    if (egl_init_displays(EGL_DEFAULT_DISPLAY) == EGL_NO_DISPLAY)
-        return NULL;
+
+    if (egl_init_drivers() == EGL_FALSE) {
+        setError(EGL_BAD_PARAMETER, NULL);
+        return  NULL;
+    }
 
     __eglMustCastToProperFunctionPointerType addr;
     addr = findProcAddress(procname, gExtentionMap, NELEM(gExtentionMap));
@@ -1275,6 +1265,8 @@
 
 EGLBoolean eglWaitClient(void)
 {
+    // could be called before eglInitialize(), but we wouldn't have a context
+    // then, and this function would return GL_TRUE, which isn't wrong.
     EGLBoolean res = EGL_TRUE;
     EGLContext ctx = getContext();
     if (ctx) {
@@ -1296,6 +1288,10 @@
 
 EGLBoolean eglBindAPI(EGLenum api)
 {
+    if (egl_init_drivers() == EGL_FALSE) {
+        return setError(EGL_BAD_PARAMETER, EGL_FALSE);
+    }
+
     // bind this API on all EGLs
     EGLBoolean res = EGL_TRUE;
     for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
@@ -1313,6 +1309,10 @@
 
 EGLenum eglQueryAPI(void)
 {
+    if (egl_init_drivers() == EGL_FALSE) {
+        return setError(EGL_BAD_PARAMETER, EGL_FALSE);
+    }
+
     for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
         egl_connection_t* const cnx = &gEGLImpl[i];
         if (cnx->dso) {
diff --git a/opengl/libs/egl_impl.h b/opengl/libs/egl_impl.h
index c5f753d..ac286cb 100644
--- a/opengl/libs/egl_impl.h
+++ b/opengl/libs/egl_impl.h
@@ -35,7 +35,6 @@
     gl_hooks_t *        hooks;
     EGLint              major;
     EGLint              minor;
-    int                 unavailable;
 };
 
 EGLAPI EGLImageKHR egl_get_image_for_current_context(EGLImageKHR image);
diff --git a/opengl/libs/hooks.h b/opengl/libs/hooks.h
index 37292ee..8c0357e 100644
--- a/opengl/libs/hooks.h
+++ b/opengl/libs/hooks.h
@@ -60,12 +60,8 @@
 enum {
     IMPL_HARDWARE = 0,
     IMPL_SOFTWARE,
-    
     IMPL_NUM_DRIVERS_IMPLEMENTATIONS,
-
-    IMPL_CONTEXT_LOST = IMPL_NUM_DRIVERS_IMPLEMENTATIONS,
-    IMPL_NO_CONTEXT,
-    
+    IMPL_NO_CONTEXT = IMPL_NUM_DRIVERS_IMPLEMENTATIONS,
     IMPL_NUM_IMPLEMENTATIONS
 };