Merge change 24337 into eclair

* changes:
  Fix issue 2107584: media server crash when AudioFlinger fails to allocate memory for track control block.
diff --git a/camera/libcameraservice/CameraService.cpp b/camera/libcameraservice/CameraService.cpp
index e66b00f..f425f6b 100644
--- a/camera/libcameraservice/CameraService.cpp
+++ b/camera/libcameraservice/CameraService.cpp
@@ -552,17 +552,6 @@
     CameraParameters params(mHardware->getParameters());
     params.getPreviewSize(&w, &h);
 
-    const char *format = params.getPreviewFormat();
-    int fmt;
-    if (!strcmp(format, "yuv422i-yuyv"))
-        fmt = OVERLAY_FORMAT_YCbYCr_422_I;
-    else if (!strcmp(format, "rgb565"))
-        fmt = OVERLAY_FORMAT_RGB_565;
-    else {
-        LOGE("Invalid preview format for overlays");
-        return -EINVAL;
-    }
-
     if ( w != mOverlayW || h != mOverlayH )
     {
         // Force the destruction of any previous overlay
@@ -574,7 +563,7 @@
     status_t ret = NO_ERROR;
     if (mSurface != 0) {
         if (mOverlayRef.get() == NULL) {
-            mOverlayRef = mSurface->createOverlay(w, h, fmt);
+            mOverlayRef = mSurface->createOverlay(w, h, OVERLAY_FORMAT_DEFAULT);
             if ( mOverlayRef.get() == NULL )
             {
                 LOGE("Overlay Creation Failed!");
@@ -1112,8 +1101,7 @@
     }
 
     CameraParameters p(params);
-    mHardware->setParameters(p);
-    return NO_ERROR;
+    return mHardware->setParameters(p);
 }
 
 // get preview/capture parameters - key/value pairs
diff --git a/cmds/keystore/Android.mk b/cmds/keystore/Android.mk
index 3daf44e..8804636 100644
--- a/cmds/keystore/Android.mk
+++ b/cmds/keystore/Android.mk
@@ -4,7 +4,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:= \
-    netkeystore.c keymgmt.c
+    netkeystore.c netkeystore_main.c keymgmt.c
 
 LOCAL_C_INCLUDES := \
     $(call include-path-for, system-core)/cutils \
diff --git a/cmds/keystore/keymgmt.c b/cmds/keystore/keymgmt.c
index 69e0380..b5ace86 100644
--- a/cmds/keystore/keymgmt.c
+++ b/cmds/keystore/keymgmt.c
@@ -385,7 +385,10 @@
         return -1;
     }
     while ((de = readdir(d))) {
-        if (unlink(de->d_name) != 0) ret = -1;
+        char *dirname = de->d_name;
+        if (strcmp(".", dirname) == 0) continue;
+        if (strcmp("..", dirname) == 0) continue;
+        if (unlink(dirname) != 0) ret = -1;
     }
     closedir(d);
     state = UNINITIALIZED;
diff --git a/cmds/keystore/netkeystore.c b/cmds/keystore/netkeystore.c
index 82a92c3..83c7871 100644
--- a/cmds/keystore/netkeystore.c
+++ b/cmds/keystore/netkeystore.c
@@ -14,8 +14,6 @@
 ** limitations under the License.
 */
 
-#define LOG_TAG "keystore"
-
 #include <stdio.h>
 #include <stdlib.h>
 #include <sys/stat.h>
@@ -247,7 +245,7 @@
     reply->retcode = reset_keystore();
 }
 
-static void execute(LPC_MARSHAL *cmd, LPC_MARSHAL *reply)
+void execute(LPC_MARSHAL *cmd, LPC_MARSHAL *reply)
 {
     uint32_t cmd_max = sizeof(cmds)/sizeof(struct cmdinfo);
 
@@ -309,7 +307,7 @@
     return 0;
 }
 
-static int parse_cmd(int argc, const char **argv, LPC_MARSHAL *cmd)
+int parse_cmd(int argc, const char **argv, LPC_MARSHAL *cmd)
 {
     uint32_t i, len = 0;
     uint32_t cmd_max = sizeof(cmds)/sizeof(cmds[0]);
@@ -335,30 +333,30 @@
     }
 }
 
-static int shell_command(const int argc, const char **argv)
+int shell_command(const int argc, const char **argv)
 {
     int fd, i;
     LPC_MARSHAL  cmd;
 
-    if (parse_cmd(argc, argv , &cmd)) {
+    if (parse_cmd(argc, argv, &cmd)) {
         fprintf(stderr, "Incorrect command or command line is too long.\n");
-        exit(1);
+        return -1;
     }
     fd = socket_local_client(SOCKET_PATH,
                              ANDROID_SOCKET_NAMESPACE_RESERVED,
                              SOCK_STREAM);
     if (fd == -1) {
         fprintf(stderr, "Keystore service is not up and running.\n");
-        exit(1);
+        return -1;
     }
 
     if (write_marshal(fd, &cmd)) {
         fprintf(stderr, "Incorrect command or command line is too long.\n");
-        exit(1);
+        return -1;
     }
     if (read_marshal(fd, &cmd)) {
         fprintf(stderr, "Failed to read the result.\n");
-        exit(1);
+        return -1;
     }
     cmd.data[cmd.len] = 0;
     fprintf(stdout, "%s\n", (cmd.retcode == 0) ? "Succeeded!" : "Failed!");
@@ -367,30 +365,26 @@
     return 0;
 }
 
-int main(const int argc, const char *argv[])
+int server_main(const int argc, const char *argv[])
 {
     struct sockaddr addr;
     socklen_t alen;
     int lsocket, s;
     LPC_MARSHAL  cmd, reply;
 
-    if (argc > 1) {
-        return shell_command(argc - 1, argv + 1);
-    }
-
     if (init_keystore(KEYSTORE_DIR)) {
         LOGE("Can not initialize the keystore, the directory exist?\n");
-        exit(1);
+        return -1;
     }
 
     lsocket = android_get_control_socket(SOCKET_PATH);
     if (lsocket < 0) {
         LOGE("Failed to get socket from environment: %s\n", strerror(errno));
-        exit(1);
+        return -1;
     }
     if (listen(lsocket, 5)) {
         LOGE("Listen on socket failed: %s\n", strerror(errno));
-        exit(1);
+        return -1;
     }
     fcntl(lsocket, F_SETFD, FD_CLOEXEC);
     memset(&reply, 0, sizeof(LPC_MARSHAL));
diff --git a/cmds/keystore/netkeystore.h b/cmds/keystore/netkeystore.h
index d80ddae..e2ffd8b 100644
--- a/cmds/keystore/netkeystore.h
+++ b/cmds/keystore/netkeystore.h
@@ -25,6 +25,10 @@
 
 #include "common.h"
 
+// for testing
+int parse_cmd(int argc, const char **argv, LPC_MARSHAL *cmd);
+void execute(LPC_MARSHAL *cmd, LPC_MARSHAL *reply);
+
 static inline int readx(int s, void *_buf, int count)
 {
     char *buf = _buf;
diff --git a/cmds/keystore/netkeystore_main.c b/cmds/keystore/netkeystore_main.c
new file mode 100644
index 0000000..606e67a
--- /dev/null
+++ b/cmds/keystore/netkeystore_main.c
@@ -0,0 +1,29 @@
+/*
+** Copyright 2009, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#define LOG_TAG "keystore"
+
+int shell_command(const int argc, const char **argv);
+int server_main(const int argc, const char *argv[]);
+
+int main(const int argc, const char *argv[])
+{
+    if (argc > 1) {
+        return shell_command(argc - 1, argv + 1);
+    } else {
+        return server_main(argc, argv);
+    }
+}
diff --git a/cmds/keystore/tests/Android.mk b/cmds/keystore/tests/Android.mk
index 33541cc..e0a776a 100644
--- a/cmds/keystore/tests/Android.mk
+++ b/cmds/keystore/tests/Android.mk
@@ -16,7 +16,7 @@
 ifdef KEYSTORE_TESTS
 LOCAL_PATH:= $(call my-dir)
 include $(CLEAR_VARS)
-LOCAL_SRC_FILES:= netkeystore_test.c ../keymgmt.c
+LOCAL_SRC_FILES:= netkeystore_test.c ../keymgmt.c ../netkeystore.c
 LOCAL_SHARED_LIBRARIES := libcutils libssl
 LOCAL_MODULE:= netkeystore_test
 LOCAL_MODULE_TAGS := optional
diff --git a/cmds/keystore/tests/netkeystore_test.c b/cmds/keystore/tests/netkeystore_test.c
index 00390e0..ce79503 100644
--- a/cmds/keystore/tests/netkeystore_test.c
+++ b/cmds/keystore/tests/netkeystore_test.c
@@ -29,9 +29,13 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
+#include <cutils/log.h>
 
 #include "common.h"
 #include "keymgmt.h"
+#include "netkeystore.h"
+
+#define LOG_TAG "keystore_test"
 
 typedef int FUNC_PTR();
 typedef struct {
@@ -61,7 +65,9 @@
 
 void teardown()
 {
-    reset_keystore();
+    if (reset_keystore() != 0) {
+        fprintf(stderr, "Can not reset the test directory %s\n", TEST_DIR);
+    }
     rmdir(TEST_DIR);
 }
 
@@ -74,7 +80,7 @@
 
 FUNC_BODY(reset_keystore)
 {
-    chdir("/procx");
+    int ret = chdir("/proc");
     if (reset_keystore() == 0) return -1;
     chdir(TEST_DIR);
     return EXIT_SUCCESS;
@@ -87,7 +93,8 @@
     if (get_state() != UNLOCKED) return -1;
     lock();
     if (get_state() != LOCKED) return -1;
-    reset_keystore();
+
+    if (reset_keystore() != 0) return -1;
     if (get_state() != UNINITIALIZED) return -1;
     return EXIT_SUCCESS;
 }
@@ -218,6 +225,37 @@
     return EXIT_SUCCESS;
 }
 
+static int execute_cmd(int argc, const char *argv[], LPC_MARSHAL *cmd,
+        LPC_MARSHAL *reply)
+{
+    memset(cmd, 0, sizeof(LPC_MARSHAL));
+    memset(reply, 0, sizeof(LPC_MARSHAL));
+    if (parse_cmd(argc, argv, cmd)) return -1;
+    execute(cmd, reply);
+    return (reply->retcode ? -1 : 0);
+}
+
+FUNC_BODY(client_passwd)
+{
+    LPC_MARSHAL cmd, reply;
+    const char *set_passwd_cmds[2] = {"passwd", TEST_PASSWD};
+    const char *change_passwd_cmds[3] = {"passwd", TEST_PASSWD, TEST_NPASSWD};
+
+    if (execute_cmd(2, set_passwd_cmds, &cmd, &reply)) return -1;
+
+    lock();
+    if (unlock("55555555") == 0) return -1;
+    if (unlock(TEST_PASSWD) != 0) return -1;
+
+    if (execute_cmd(3, change_passwd_cmds, &cmd, &reply)) return -1;
+
+    lock();
+    if (unlock(TEST_PASSWD) == 0) return -1;
+    if (unlock(TEST_NPASSWD) != 0) return -1;
+
+    return EXIT_SUCCESS;
+}
+
 TESTFUNC all_tests[] = {
     FUNC_NAME(init_keystore),
     FUNC_NAME(reset_keystore),
@@ -229,11 +267,13 @@
     FUNC_NAME(get_key),
     FUNC_NAME(remove_key),
     FUNC_NAME(list_keys),
+    FUNC_NAME(client_passwd),
 };
 
 int main(int argc, char **argv) {
     int i, ret;
     for (i = 0 ; i < (int)(sizeof(all_tests)/sizeof(TESTFUNC)) ; ++i) {
+        LOGD("run %s...\n", all_tests[i].name);
         setup();
         if ((ret = all_tests[i].func()) != EXIT_SUCCESS) {
             fprintf(stderr, "ERROR in function %s\n", all_tests[i].name);
diff --git a/include/private/ui/SharedBufferStack.h b/include/private/ui/SharedBufferStack.h
index 2bd5344..6181f55 100644
--- a/include/private/ui/SharedBufferStack.h
+++ b/include/private/ui/SharedBufferStack.h
@@ -85,6 +85,7 @@
 
 public:
     SharedBufferStack();
+    void init(int32_t identity);
     status_t setDirtyRegion(int buffer, const Region& reg);
     Region getDirtyRegion(int buffer) const;
 
@@ -93,12 +94,12 @@
     volatile int32_t available; // number of dequeue-able buffers
     volatile int32_t queued;    // number of buffers waiting for post
     volatile int32_t inUse;     // buffer currently in use by SF
+    volatile status_t status;   // surface's status code
 
     // not part of the conditions
     volatile int32_t reallocMask;
 
     int32_t     identity;       // surface's identity (const)
-    status_t    status;         // surface's status code
     int32_t     reserved32[13];
     FlatRegion  dirtyRegion[NUM_BUFFER_MAX];    // 12*4=48 bytes
 };
@@ -114,7 +115,6 @@
 
     status_t validate(size_t token) const;
     uint32_t getIdentity(size_t token) const;
-    status_t setIdentity(size_t token, uint32_t identity);
 
 private:
     friend class SharedBufferBase;
@@ -168,10 +168,11 @@
 template <typename T>
 status_t SharedBufferBase::waitForCondition(T condition) 
 {
+    const SharedBufferStack& stack( *mSharedStack );
     SharedClient& client( *mSharedClient );
     const nsecs_t TIMEOUT = s2ns(1); 
     Mutex::Autolock _l(client.lock);
-    while (!condition()) {
+    while ((condition()==false) && (stack.status == NO_ERROR)) {
         status_t err = client.cv.waitRelative(client.lock, TIMEOUT);
         
         // handle errors and timeouts
@@ -195,7 +196,7 @@
             }
         }
     }
-    return NO_ERROR;
+    return stack.status;
 }
 
 
@@ -261,13 +262,15 @@
 class SharedBufferServer : public SharedBufferBase
 {
 public:
-    SharedBufferServer(SharedClient* sharedClient, int surface, int num);
+    SharedBufferServer(SharedClient* sharedClient, int surface, int num,
+            int32_t identity);
 
     ssize_t retireAndLock();
     status_t unlock(int buffer);
+    void setStatus(status_t status);
     status_t reallocate();
     status_t assertReallocate(int buffer);
-
+    
     Region getDirtyRegion(int buffer) const;
 
 private:
@@ -283,6 +286,12 @@
         inline ssize_t operator()();
     };
 
+    struct StatusUpdate : public UpdateBase {
+        const status_t status;
+        inline StatusUpdate(SharedBufferBase* sbb, status_t status);
+        inline ssize_t operator()();
+    };
+
     struct ReallocateCondition : public ConditionBase {
         int buf;
         inline ReallocateCondition(SharedBufferBase* sbb, int buf);
diff --git a/include/utils/threads.h b/include/utils/threads.h
index e9b0788..f5304f7 100644
--- a/include/utils/threads.h
+++ b/include/utils/threads.h
@@ -90,6 +90,11 @@
     ANDROID_TGROUP_MAX              = ANDROID_TGROUP_FG_BOOST,
 };
 
+typedef enum {
+    SP_BACKGROUND = 0,
+    SP_FOREGROUND = 1,
+} SchedPolicy;
+
 // Create and run a new thread.
 extern int androidCreateThread(android_thread_func_t, void *);
 
@@ -408,6 +413,9 @@
     volatile bool           mExitPending;
     volatile bool           mRunning;
             sp<Thread>      mHoldSelf;
+#if HAVE_ANDROID_OS
+            int             mTid;
+#endif
 };
 
 
diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
index 651e7cf..d893f0a 100644
--- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
+++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
@@ -103,10 +103,22 @@
     }
 
     // initialize EGL
-    const EGLint attribs[] = {
+    EGLint attribs[] = {
             EGL_SURFACE_TYPE,   EGL_WINDOW_BIT,
+            EGL_NONE,           0,
             EGL_NONE
     };
+
+    // debug: disable h/w rendering
+    char property[PROPERTY_VALUE_MAX];
+    if (property_get("debug.sf.hw", property, NULL) > 0) {
+        if (atoi(property) == 0) {
+            LOGW("H/W composition disabled");
+            attribs[2] = EGL_CONFIG_CAVEAT;
+            attribs[3] = EGL_SLOW_CONFIG;
+        }
+    }
+
     EGLint w, h, dummy;
     EGLint numConfigs=0;
     EGLSurface surface;
@@ -193,7 +205,6 @@
     mDpiY = mNativeWindow->ydpi;
     mRefreshRate = fbDev->fps; 
     
-    char property[PROPERTY_VALUE_MAX];
     /* Read density from build-specific ro.sf.lcd_density property
      * except if it is overridden by qemu.sf.lcd_density.
      */
diff --git a/libs/surfaceflinger/Layer.cpp b/libs/surfaceflinger/Layer.cpp
index ecb6b32..6275910 100644
--- a/libs/surfaceflinger/Layer.cpp
+++ b/libs/surfaceflinger/Layer.cpp
@@ -49,13 +49,12 @@
 
 Layer::Layer(SurfaceFlinger* flinger, DisplayID display, 
         const sp<Client>& c, int32_t i)
-    :   LayerBaseClient(flinger, display, c, i), lcblk(NULL),
+    :   LayerBaseClient(flinger, display, c, i),
         mSecure(false),
         mNeedsBlending(true)
 {
     // no OpenGL operation is possible here, since we might not be
     // in the OpenGL thread.
-    lcblk = new SharedBufferServer(c->ctrlblk, i, NUM_BUFFERS);
     mFrontBufferIndex = lcblk->getFrontBuffer();
 }
 
@@ -63,8 +62,14 @@
 {
     destroy();
     // the actual buffers will be destroyed here
-    delete lcblk;
+}
 
+// called with SurfaceFlinger::mStateLock as soon as the layer is entered
+// in the purgatory list
+void Layer::onRemoved()
+{
+    // wake up the condition
+    lcblk->setStatus(NO_INIT);
 }
 
 void Layer::destroy()
@@ -79,7 +84,9 @@
             eglDestroyImageKHR(dpy, mTextures[i].image);
             mTextures[i].image = EGL_NO_IMAGE_KHR;
         }
+        Mutex::Autolock _l(mLock);
         mBuffers[i].clear();
+        mWidth = mHeight = 0;
     }
     mSurface.clear();
 }
@@ -213,6 +220,16 @@
 
 sp<SurfaceBuffer> Layer::requestBuffer(int index, int usage)
 {
+    sp<Buffer> buffer;
+
+    // this ensures our client doesn't go away while we're accessing
+    // the shared area.
+    sp<Client> ourClient(client.promote());
+    if (ourClient == 0) {
+        // oops, the client is already gone
+        return buffer;
+    }
+
     /*
      * 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
@@ -225,12 +242,21 @@
      */
     status_t err = lcblk->assertReallocate(index);
     LOGE_IF(err, "assertReallocate(%d) failed (%s)", index, strerror(-err));
+    if (err != NO_ERROR) {
+        // the surface may have died
+        return buffer;
+    }
 
-    Mutex::Autolock _l(mLock);
-    uint32_t w = mWidth;
-    uint32_t h = mHeight;
-    
-    sp<Buffer>& buffer(mBuffers[index]);
+    uint32_t w, h;
+    { // scope for the lock
+        Mutex::Autolock _l(mLock);
+        w = mWidth;
+        h = mHeight;
+        buffer = mBuffers[index];
+        mBuffers[index].clear();
+    }
+
+
     if (buffer->getStrongCount() == 1) {
         err = buffer->reallocate(w, h, mFormat, usage, mBufferFlags);
     } else {
@@ -253,8 +279,16 @@
     }
 
     if (err == NO_ERROR && buffer->handle != 0) {
-        // texture is now dirty...
-        mTextures[index].dirty = true;
+        Mutex::Autolock _l(mLock);
+        if (mWidth && mHeight) {
+            // and we have new buffer
+            mBuffers[index] = buffer;
+            // texture is now dirty...
+            mTextures[index].dirty = true;
+        } else {
+            // oops we got killed while we were allocating the buffer
+            buffer.clear();
+        }
     }
     return buffer;
 }
diff --git a/libs/surfaceflinger/Layer.h b/libs/surfaceflinger/Layer.h
index 3b4489e..2e8173d 100644
--- a/libs/surfaceflinger/Layer.h
+++ b/libs/surfaceflinger/Layer.h
@@ -51,10 +51,6 @@
     static const char* const typeID;
     virtual char const* getTypeID() const { return typeID; }
     virtual uint32_t getTypeInfo() const { return typeInfo; }
-
-    
-    SharedBufferServer*     lcblk;
-
     
                  Layer(SurfaceFlinger* flinger, DisplayID display,
                          const sp<Client>& client, int32_t i);
@@ -88,6 +84,8 @@
         return mBuffers[mFrontBufferIndex];
     }
  
+    virtual void onRemoved();
+
     void reloadTexture(const Region& dirty);
 
     sp<SurfaceBuffer> requestBuffer(int index, int usage);
diff --git a/libs/surfaceflinger/LayerBase.cpp b/libs/surfaceflinger/LayerBase.cpp
index 62e41b0..1f22488 100644
--- a/libs/surfaceflinger/LayerBase.cpp
+++ b/libs/surfaceflinger/LayerBase.cpp
@@ -642,9 +642,12 @@
 
 LayerBaseClient::LayerBaseClient(SurfaceFlinger* flinger, DisplayID display,
         const sp<Client>& client, int32_t i)
-    : LayerBase(flinger, display), client(client),
+    : LayerBase(flinger, display), lcblk(NULL), client(client),
       mIndex(i), mIdentity(uint32_t(android_atomic_inc(&sIdentity)))
 {
+    lcblk = new SharedBufferServer(
+            client->ctrlblk, i, NUM_BUFFERS,
+            mIdentity);
 }
 
 void LayerBaseClient::onFirstRef()
@@ -652,8 +655,6 @@
     sp<Client> client(this->client.promote());
     if (client != 0) {
         client->bindLayer(this, mIndex);
-        // Initialize this layer's identity
-        client->ctrlblk->setIdentity(mIndex, mIdentity);
     }
 }
 
@@ -663,6 +664,7 @@
     if (client != 0) {
         client->free(mIndex);
     }
+    delete lcblk;
 }
 
 int32_t LayerBaseClient::serverIndex() const 
diff --git a/libs/surfaceflinger/LayerBase.h b/libs/surfaceflinger/LayerBase.h
index 78bb4bf..3a52240 100644
--- a/libs/surfaceflinger/LayerBase.h
+++ b/libs/surfaceflinger/LayerBase.h
@@ -292,13 +292,16 @@
     virtual char const* getTypeID() const { return typeID; }
     virtual uint32_t getTypeInfo() const { return typeInfo; }
 
+    // lcblk is (almost) only accessed from the main SF thread, in the places
+    // where it's not, a reference to Client must be held
+    SharedBufferServer*     lcblk;
+
     LayerBaseClient(SurfaceFlinger* flinger, DisplayID display, 
             const sp<Client>& client, int32_t i);
     virtual ~LayerBaseClient();
     virtual void onFirstRef();
 
-    wp<Client>              client;
-//    SharedBufferServer*     lcblk;
+    const wp<Client>    client;
 
     inline  uint32_t    getIdentity() const { return mIdentity; }
     inline  int32_t     clientIndex() const { return mIndex; }
@@ -308,6 +311,7 @@
             sp<Surface> getSurface();
     virtual sp<Surface> createSurface() const;
     
+    virtual void onRemoved() { }
 
     class Surface : public BnSurface 
     {
diff --git a/libs/surfaceflinger/LayerBlur.cpp b/libs/surfaceflinger/LayerBlur.cpp
index 00abd5a..e14f35b 100644
--- a/libs/surfaceflinger/LayerBlur.cpp
+++ b/libs/surfaceflinger/LayerBlur.cpp
@@ -24,6 +24,7 @@
 #include <GLES/gl.h>
 #include <GLES/glext.h>
 
+#include "clz.h"
 #include "BlurFilter.h"
 #include "LayerBlur.h"
 #include "SurfaceFlinger.h"
@@ -40,7 +41,8 @@
 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)
+     mRefreshCache(true), mCacheAge(0), mTextureName(-1U), 
+     mWidthScale(1.0f), mHeightScale(1.0f)
 {
 }
 
@@ -164,11 +166,26 @@
             bl.format = GGL_PIXEL_FORMAT_RGB_565;
             bl.data = (GGLubyte*)pixels;            
             blurFilter(&bl, 8, 2);
-            
-            // NOTE: this works only because we have POT. we'd have to round the
-            // texture size up, otherwise.
-            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0,
-                    GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pixels);
+
+            if (mFlags & (DisplayHardware::NPOT_EXTENSION)) {
+                glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0,
+                        GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pixels);
+                mWidthScale  = 1.0f / w;
+                mHeightScale =-1.0f / h;
+                mYOffset = 0;
+            } else {
+                GLuint tw = 1 << (31 - clz(w));
+                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);
+                glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, 
+                        GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pixels);
+                mWidthScale  = 1.0f / tw;
+                mHeightScale =-1.0f / th;
+                mYOffset = th-h;
+            }
 
             free((void*)pixels);
         }
@@ -184,7 +201,12 @@
             glDisable(GL_BLEND);
         }
 
-        glDisable(GL_DITHER);
+        if (mFlags & DisplayHardware::SLOW_CONFIG) {
+            glDisable(GL_DITHER);
+        } else {
+            glEnable(GL_DITHER);
+        }
+
         glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
         glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
         glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
@@ -194,8 +216,8 @@
             // This is a very rare scenario.
             glMatrixMode(GL_TEXTURE);
             glLoadIdentity();
-            glScalef(1.0f/w, -1.0f/h, 1);
-            glTranslatef(-x, -y, 0);
+            glScalef(mWidthScale, mHeightScale, 1);
+            glTranslatef(-x, mYOffset - y, 0);
             glEnableClientState(GL_TEXTURE_COORD_ARRAY);
             glVertexPointer(2, GL_FIXED, 0, mVertices);
             glTexCoordPointer(2, GL_FIXED, 0, mVertices);
@@ -205,6 +227,7 @@
                 glScissor(r.left, sy, r.width(), r.height());
                 glDrawArrays(GL_TRIANGLE_FAN, 0, 4); 
             }       
+            glDisableClientState(GL_TEXTURE_COORD_ARRAY);
         } else {
             // NOTE: this is marginally faster with the software gl, because
             // glReadPixels() reads the fb bottom-to-top, however we'll
@@ -221,8 +244,6 @@
             }
         }
     }
-
-    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
 }
 
 // ---------------------------------------------------------------------------
diff --git a/libs/surfaceflinger/LayerBlur.h b/libs/surfaceflinger/LayerBlur.h
index 0c3e6eb..bf36ae4 100644
--- a/libs/surfaceflinger/LayerBlur.h
+++ b/libs/surfaceflinger/LayerBlur.h
@@ -56,6 +56,9 @@
     mutable bool    mAutoRefreshPending;
             nsecs_t mCacheAge;
     mutable GLuint  mTextureName;
+    mutable GLfloat mWidthScale;
+    mutable GLfloat mHeightScale;
+    mutable GLfloat mYOffset;
 };
 
 // ---------------------------------------------------------------------------
diff --git a/libs/surfaceflinger/LayerBuffer.cpp b/libs/surfaceflinger/LayerBuffer.cpp
index 433b48e..bbfc54b 100644
--- a/libs/surfaceflinger/LayerBuffer.cpp
+++ b/libs/surfaceflinger/LayerBuffer.cpp
@@ -133,6 +133,14 @@
     return false;
 }
 
+void LayerBuffer::serverDestroy()
+{
+    sp<Source> source(clearSource());
+    if (source != 0) {
+        source->destroy();
+    }
+}
+
 /**
  * This creates a "buffer" source for this surface
  */
@@ -354,7 +362,7 @@
 {    
     ISurface::BufferHeap buffers;
     { // scope for the lock
-        Mutex::Autolock _l(mLock);
+        Mutex::Autolock _l(mBufferSourceLock);
         buffers = mBufferHeap;
         if (buffers.heap != 0) {
             const size_t memorySize = buffers.heap->getSize();
@@ -379,7 +387,7 @@
 
 void LayerBuffer::BufferSource::unregisterBuffers()
 {
-    Mutex::Autolock _l(mLock);
+    Mutex::Autolock _l(mBufferSourceLock);
     mBufferHeap.heap.clear();
     mBuffer.clear();
     mLayer.invalidate();
@@ -387,13 +395,13 @@
 
 sp<LayerBuffer::Buffer> LayerBuffer::BufferSource::getBuffer() const
 {
-    Mutex::Autolock _l(mLock);
+    Mutex::Autolock _l(mBufferSourceLock);
     return mBuffer;
 }
 
 void LayerBuffer::BufferSource::setBuffer(const sp<LayerBuffer::Buffer>& buffer)
 {
-    Mutex::Autolock _l(mLock);
+    Mutex::Autolock _l(mBufferSourceLock);
     mBuffer = buffer;
 }
 
@@ -413,7 +421,7 @@
 
     status_t err = NO_ERROR;
     NativeBuffer src(ourBuffer->getBuffer());
-    const Rect& transformedBounds = mLayer.getTransformedBounds();
+    const Rect transformedBounds(mLayer.getTransformedBounds());
     copybit_device_t* copybit = mBlitEngine;
 
     if (copybit)  {
@@ -493,7 +501,7 @@
                 }
             }
 
-            const Rect& transformedBounds = mLayer.getTransformedBounds();
+            const Rect transformedBounds(mLayer.getTransformedBounds());
             const copybit_rect_t& drect =
                 reinterpret_cast<const copybit_rect_t&>(transformedBounds);
             const State& s(mLayer.drawingState());
@@ -583,9 +591,7 @@
 
     mOverlayHandle = overlay->getHandleRef(overlay);
     
-    // NOTE: here it's okay to acquire a reference to "this"m as long as
-    // the reference is not released before we leave the ctor.
-    sp<OverlayChannel> channel = new OverlayChannel(this);
+    sp<OverlayChannel> channel = new OverlayChannel( &layer );
 
     *overlayRef = new OverlayRef(mOverlayHandle, channel,
             mWidth, mHeight, mFormat, mWidthStride, mHeightStride);
@@ -601,7 +607,6 @@
 
 void LayerBuffer::OverlaySource::onDraw(const Region& clip) const
 {
-    GLclampx color = 0x000018; //dark blue
     GLclampx red = 0;
     GLclampx green = 0;
     GLclampx blue = 0x1818;
@@ -626,14 +631,14 @@
         if (mVisibilityChanged || !mInitialized) {
             mVisibilityChanged = false;
             mInitialized = true;
-            const Rect& bounds = mLayer.getTransformedBounds();
+            const Rect bounds(mLayer.getTransformedBounds());
             int x = bounds.left;
             int y = bounds.top;
             int w = bounds.width();
             int h = bounds.height();
             
             // we need a lock here to protect "destroy"
-            Mutex::Autolock _l(mLock);
+            Mutex::Autolock _l(mOverlaySourceLock);
             if (mOverlay) {
                 overlay_control_device_t* overlay_dev = mOverlayDevice;
                 overlay_dev->setPosition(overlay_dev, mOverlay, x,y,w,h);
@@ -645,17 +650,11 @@
     }
 }
 
-void LayerBuffer::OverlaySource::serverDestroy() 
-{
-    mLayer.clearSource();
-    destroyOverlay();
-}
-
-void LayerBuffer::OverlaySource::destroyOverlay() 
+void LayerBuffer::OverlaySource::destroy()
 {
     // we need a lock here to protect "onVisibilityResolved"
-    Mutex::Autolock _l(mLock);
-    if (mOverlay) {
+    Mutex::Autolock _l(mOverlaySourceLock);
+    if (mOverlay && mOverlayDevice) {
         overlay_control_device_t* overlay_dev = mOverlayDevice;
         overlay_dev->destroyOverlay(overlay_dev, mOverlay);
         mOverlay = 0;
diff --git a/libs/surfaceflinger/LayerBuffer.h b/libs/surfaceflinger/LayerBuffer.h
index e539f68..0452818 100644
--- a/libs/surfaceflinger/LayerBuffer.h
+++ b/libs/surfaceflinger/LayerBuffer.h
@@ -49,6 +49,7 @@
         virtual void postBuffer(ssize_t offset);
         virtual void unregisterBuffers();
         virtual bool transformed() const;
+        virtual void destroy() { }
     protected:
         LayerBuffer& mLayer;
     };
@@ -81,10 +82,12 @@
     sp<Source> getSource() const;
     sp<Source> clearSource();
     void setNeedsBlending(bool blending);
-    const Rect& getTransformedBounds() const {
+    Rect getTransformedBounds() const {
         return mTransformedBounds;
     }
 
+    void serverDestroy();
+
 private:
     struct NativeBuffer {
         copybit_image_t   img;
@@ -123,8 +126,9 @@
         virtual void postBuffer(ssize_t offset);
         virtual void unregisterBuffers();
         virtual bool transformed() const;
+        virtual void destroy() { }
     private:
-        mutable Mutex                   mLock;
+        mutable Mutex                   mBufferSourceLock;
         sp<Buffer>                      mBuffer;
         status_t                        mStatus;
         ISurface::BufferHeap            mBufferHeap;
@@ -143,28 +147,23 @@
         virtual void onDraw(const Region& clip) const;
         virtual void onTransaction(uint32_t flags);
         virtual void onVisibilityResolved(const Transform& planeTransform);
+        virtual void destroy();
     private:
-        void serverDestroy(); 
-        void destroyOverlay(); 
+
         class OverlayChannel : public BnOverlay {
-            mutable Mutex mLock;
-            sp<OverlaySource> mSource;
+            wp<LayerBuffer> mLayer;
             virtual void destroy() {
-                sp<OverlaySource> source;
-                { // scope for the lock;
-                    Mutex::Autolock _l(mLock);
-                    source = mSource;
-                    mSource.clear();
-                }
-                if (source != 0) {
-                    source->serverDestroy();
+                sp<LayerBuffer> layer(mLayer.promote());
+                if (layer != 0) {
+                    layer->serverDestroy();
                 }
             }
         public:
-            OverlayChannel(const sp<OverlaySource>& source)
-                : mSource(source) {
+            OverlayChannel(const sp<LayerBuffer>& layer)
+                : mLayer(layer) {
             }
         };
+        
         friend class OverlayChannel;
         bool mVisibilityChanged;
 
@@ -176,7 +175,7 @@
         int32_t mFormat;
         int32_t mWidthStride;
         int32_t mHeightStride;
-        mutable Mutex mLock;
+        mutable Mutex mOverlaySourceLock;
         bool mInitialized;
     };
 
@@ -199,7 +198,7 @@
             return static_cast<LayerBuffer*>(Surface::getOwner().get());
         }
     };
-    
+
     mutable Mutex   mLock;
     sp<Source>      mSource;
     sp<Surface>     mSurface;
diff --git a/libs/surfaceflinger/SurfaceFlinger.cpp b/libs/surfaceflinger/SurfaceFlinger.cpp
index b368db6..8685f99 100644
--- a/libs/surfaceflinger/SurfaceFlinger.cpp
+++ b/libs/surfaceflinger/SurfaceFlinger.cpp
@@ -654,6 +654,7 @@
         // some layers might have been removed, so
         // we need to update the regions they're exposing.
         if (mLayersRemoved) {
+            mLayersRemoved = false;
             mVisibleRegionsDirty = true;
             const LayerVector& previousLayers(mDrawingState.layersSortedByZ);
             const size_t count = previousLayers.size();
@@ -1093,9 +1094,6 @@
 
 void SurfaceFlinger::free_resources_l()
 {
-    // Destroy layers that were removed
-    mLayersRemoved = false;
-    
     // free resources associated with disconnected clients
     Vector< sp<Client> >& disconnectedClients(mDisconnectedClients);
     const size_t count = disconnectedClients.size();
@@ -1321,11 +1319,15 @@
      * to wait for all client's references to go away first).
      */
 
+    status_t err = NAME_NOT_FOUND;
     Mutex::Autolock _l(mStateLock);
     sp<LayerBaseClient> layer = getLayerUser_l(index);
-    status_t err = purgatorizeLayer_l(layer);
-    if (err == NO_ERROR) {
-        setTransactionFlags(eTransactionNeeded);
+    if (layer != 0) {
+        err = purgatorizeLayer_l(layer);
+        if (err == NO_ERROR) {
+            layer->onRemoved();
+            setTransactionFlags(eTransactionNeeded);
+        }
     }
     return err;
 }
diff --git a/libs/ui/Android.mk b/libs/ui/Android.mk
index 348dd68..9577044 100644
--- a/libs/ui/Android.mk
+++ b/libs/ui/Android.mk
@@ -40,4 +40,8 @@
 
 LOCAL_MODULE:= libui
 
+ifeq ($(TARGET_SIMULATOR),true)
+    LOCAL_LDLIBS += -lpthread
+endif
+
 include $(BUILD_SHARED_LIBRARY)
diff --git a/libs/ui/SharedBufferStack.cpp b/libs/ui/SharedBufferStack.cpp
index 5995af5..436d793 100644
--- a/libs/ui/SharedBufferStack.cpp
+++ b/libs/ui/SharedBufferStack.cpp
@@ -53,21 +53,20 @@
     return uint32_t(surfaces[token].identity);
 }
 
-status_t SharedClient::setIdentity(size_t token, uint32_t identity) {
-    if (token >= NUM_LAYERS_MAX)
-        return BAD_INDEX;
-    surfaces[token].identity = identity;
-    return NO_ERROR;
-}
-
 // ----------------------------------------------------------------------------
 
 
 SharedBufferStack::SharedBufferStack()
-    : inUse(-1), identity(-1), status(NO_ERROR)
 {
 }
 
+void SharedBufferStack::init(int32_t i)
+{
+    inUse = -1;
+    status = NO_ERROR;
+    identity = i;
+}
+
 status_t SharedBufferStack::setDirtyRegion(int buffer, const Region& dirty)
 {
     if (uint32_t(buffer) >= NUM_BUFFER_MAX)
@@ -231,16 +230,46 @@
     return head;
 }
 
+SharedBufferServer::StatusUpdate::StatusUpdate(
+        SharedBufferBase* sbb, status_t status)
+    : UpdateBase(sbb), status(status) {
+}
+
+ssize_t SharedBufferServer::StatusUpdate::operator()() {
+    android_atomic_write(status, &stack.status);
+    return NO_ERROR;
+}
+
 // ============================================================================
 
 SharedBufferClient::SharedBufferClient(SharedClient* sharedClient,
         int surface, int num)
     : SharedBufferBase(sharedClient, surface, num), tail(0)
 {
+    SharedBufferStack& stack( *mSharedStack );
+    int32_t avail;
+    int32_t head;
+    // we need to make sure we read available and head coherently,
+    // w.r.t RetireUpdate.
+    do {
+        avail = stack.available;
+        head = stack.head;
+    } while (stack.available != avail);
+    tail = head - avail + 1;
+    if (tail < 0) {
+        tail += num;
+    }
 }
 
 ssize_t SharedBufferClient::dequeue()
 {
+    SharedBufferStack& stack( *mSharedStack );
+
+    if (stack.head == tail && stack.available == 2) {
+        LOGW("dequeue: tail=%d, head=%d, avail=%d, queued=%d",
+                tail, stack.head, stack.available, stack.queued);
+    }
+
     //LOGD("[%d] about to dequeue a buffer",
     //        mSharedStack->identity);
     DequeueCondition condition(this);
@@ -248,8 +277,6 @@
     if (err != NO_ERROR)
         return ssize_t(err);
 
-
-    SharedBufferStack& stack( *mSharedStack );
     // NOTE: 'stack.available' is part of the conditions, however
     // decrementing it, never changes any conditions, so we don't need
     // to do this as part of an update.
@@ -261,6 +288,7 @@
     tail = ((tail+1 >= mNumBuffers) ? 0 : tail+1);
     LOGD_IF(DEBUG_ATOMICS, "dequeued=%d, tail=%d, %s",
             dequeued, tail, dump("").string());
+
     return dequeued;
 }
 
@@ -302,9 +330,10 @@
 // ----------------------------------------------------------------------------
 
 SharedBufferServer::SharedBufferServer(SharedClient* sharedClient,
-        int surface, int num)
+        int surface, int num, int32_t identity)
     : SharedBufferBase(sharedClient, surface, num)
 {
+    mSharedStack->init(identity);
     mSharedStack->head = num-1;
     mSharedStack->available = num;
     mSharedStack->queued = 0;
@@ -316,7 +345,7 @@
 {
     RetireUpdate update(this, mNumBuffers);
     ssize_t buf = updateCondition( update );
-    LOGD_IF(DEBUG_ATOMICS, "retire=%d, %s", int(buf), dump("").string());
+    LOGD_IF(DEBUG_ATOMICS && buf>=0, "retire=%d, %s", int(buf), dump("").string());
     return buf;
 }
 
@@ -327,6 +356,12 @@
     return err;
 }
 
+void SharedBufferServer::setStatus(status_t status)
+{
+    StatusUpdate update(this, status);
+    updateCondition( update );
+}
+
 status_t SharedBufferServer::reallocate()
 {
     SharedBufferStack& stack( *mSharedStack );
diff --git a/libs/utils/Threads.cpp b/libs/utils/Threads.cpp
index 6be372c..ec3db09 100644
--- a/libs/utils/Threads.cpp
+++ b/libs/utils/Threads.cpp
@@ -655,6 +655,11 @@
     wp<Thread> weak(strong);
     self->mHoldSelf.clear();
 
+#if HAVE_ANDROID_OS
+    // this is very useful for debugging with gdb
+    self->mTid = gettid();
+#endif
+
     bool first = true;
 
     do {
@@ -685,7 +690,7 @@
             self->mExitPending = true;
             self->mLock.lock();
             self->mRunning = false;
-            self->mThreadExitedCondition.signal();
+            self->mThreadExitedCondition.broadcast();
             self->mLock.unlock();
             break;
         }
@@ -693,7 +698,7 @@
         // Release our strong reference, to let a chance to the thread
         // to die a peaceful death.
         strong.clear();
-        // And immediately, reacquire a strong reference for the next loop
+        // And immediately, re-acquire a strong reference for the next loop
         strong = weak.promote();
     } while(strong != 0);
     
diff --git a/opengl/libagl/texture.cpp b/opengl/libagl/texture.cpp
index 4d3c2f4..90e6d29 100644
--- a/opengl/libagl/texture.cpp
+++ b/opengl/libagl/texture.cpp
@@ -118,10 +118,10 @@
 
 /*
  * If the active textures are EGLImage, they need to be locked before
- * they can be used. 
- * 
+ * they can be used.
+ *
  * FIXME: code below is far from being optimal
- * 
+ *
  */
 
 void ogles_lock_textures(ogles_context_t* c)
@@ -409,6 +409,49 @@
     return 0;
 }
 
+static size_t dataSizePalette4(int numLevels, int width, int height, int format)
+{
+    int indexBits = 8;
+    int entrySize = 0;
+    switch (format) {
+    case GL_PALETTE4_RGB8_OES:
+        indexBits = 4;
+        /* FALLTHROUGH */
+    case GL_PALETTE8_RGB8_OES:
+        entrySize = 3;
+        break;
+
+    case GL_PALETTE4_RGBA8_OES:
+        indexBits = 4;
+        /* FALLTHROUGH */
+    case GL_PALETTE8_RGBA8_OES:
+        entrySize = 4;
+        break;
+
+    case GL_PALETTE4_R5_G6_B5_OES:
+    case GL_PALETTE4_RGBA4_OES:
+    case GL_PALETTE4_RGB5_A1_OES:
+        indexBits = 4;
+        /* FALLTHROUGH */
+    case GL_PALETTE8_R5_G6_B5_OES:
+    case GL_PALETTE8_RGBA4_OES:
+    case GL_PALETTE8_RGB5_A1_OES:
+        entrySize = 2;
+        break;
+    }
+
+    size_t size = (1 << indexBits) * entrySize; // palette size
+
+    for (int i=0 ; i< numLevels ; i++) {
+        int w = (width  >> i) ? : 1;
+        int h = (height >> i) ? : 1;
+        int levelSize = h * ((w * indexBits) / 8) ? : 1;
+        size += levelSize;
+    }
+
+    return size;
+}
+
 static void decodePalette4(const GLvoid *data, int level, int width, int height,
                            void *surface, int stride, int format)
 
@@ -443,6 +486,7 @@
     }
 
     const int paletteSize = (1 << indexBits) * entrySize;
+
     uint8_t const* pixels = (uint8_t *)data + paletteSize;
     for (int i=0 ; i<level ; i++) {
         int w = (width  >> i) ? : 1;
@@ -652,7 +696,7 @@
         ogles_context_t* c)
 {
     ogles_lock_textures(c);
-    
+
     const GGLSurface& cbSurface = c->rasterizer.state.buffers.color.s;
     y = gglIntToFixed(cbSurface.height) - (y + h);
     w >>= FIXED_BITS;
@@ -799,7 +843,7 @@
             c->rasterizer.procs.disable(c, GGL_AA);
             c->rasterizer.procs.shadeModel(c, GL_FLAT);
             c->rasterizer.procs.recti(c, x, y, x+w, y+h);
-            
+
             ogles_unlock_textures(c);
 
             return;
@@ -1091,6 +1135,12 @@
     GGLSurface* surface;
     // all mipmap levels are specified at once.
     const int numLevels = level<0 ? -level : 1;
+
+    if (dataSizePalette4(numLevels, width, height, format) > imageSize) {
+        ogles_error(c, GL_INVALID_VALUE);
+        return;
+    }
+
     for (int i=0 ; i<numLevels ; i++) {
         int lod_w = (width  >> i) ? : 1;
         int lod_h = (height >> i) ? : 1;