Merge change 24288 into eclair

* changes:
  Do not cache POST response as Cache is indexed with url.
diff --git a/cmds/keystore/certtool.h b/cmds/keystore/certtool.h
index aefad66..9b72bf7 100644
--- a/cmds/keystore/certtool.h
+++ b/cmds/keystore/certtool.h
@@ -38,9 +38,9 @@
     int count, fd, ret = -1;
     LPC_MARSHAL cmd;
     char delimiter[] = "_";
-    char *namespace, *keyname;
+    char *p = NULL;
     char *context = NULL;
-    char cname[CERT_NAME_LEN];
+    char *cname = (char*)cmd.data;
 
     if ((certname == NULL) || (value == NULL)) {
         LOGE("get_cert: certname or value is null\n");
@@ -61,12 +61,10 @@
     }
 
     cmd.opcode = GET;
-    if (((namespace = strtok_r(cname, delimiter, &context)) == NULL) ||
-        ((keyname = strtok_r(NULL, delimiter, &context)) == NULL)) {
-        goto err;
-    }
-    if ((cmd.len = snprintf((char*)cmd.data, BUFFER_MAX, "%s %s", namespace, keyname))
-        > (2 * MAX_KEY_NAME_LENGTH + 1)) goto err;
+    p = strstr(cname, delimiter);
+    cmd.len = strlen(certname) + 1;
+    if (p == NULL) goto err;
+    *p = 0; // replace the delimiter with \0 .
 
     if (write_marshal(fd, &cmd)) {
         LOGE("Incorrect command or command line is too long.\n");
diff --git a/cmds/keystore/keymgmt.c b/cmds/keystore/keymgmt.c
index 9a1f845..69e0380 100644
--- a/cmds/keystore/keymgmt.c
+++ b/cmds/keystore/keymgmt.c
@@ -192,21 +192,15 @@
     return ret;
 }
 
-static int change_passwd(char *data)
+int change_passwd(char *old_pass, char *new_pass)
 {
     unsigned char master_key[USER_KEY_LEN];
-    char *old_pass, *new_pass = NULL, *p, *delimiter=" ";
-    int ret, count = 0;
-    char *context = NULL;
+    int ret;
 
-    old_pass = p = strtok_r(data, delimiter, &context);
-    while (p != NULL) {
-        count++;
-        new_pass = p;
-        p = strtok_r(NULL, delimiter, &context);
-    }
-    if (count != 2) return -1;
-    if (strlen(new_pass) < MIN_PASSWD_LENGTH) return -1;
+    if (state == UNINITIALIZED) return -1;
+    if ((strlen(old_pass) < MIN_PASSWD_LENGTH) ||
+        (strlen(new_pass) < MIN_PASSWD_LENGTH)) return -1;
+
     if ((ret = get_master_key(old_pass, master_key)) == 0) {
         ret = store_master_key(new_pass, master_key);
         retry_count = 0;
@@ -336,14 +330,12 @@
     return 0;
 }
 
-int passwd(char *data)
+int new_passwd(char *password)
 {
-    if (state == UNINITIALIZED) {
-        if (strchr(data, ' ')) return -1;
-        if (strlen(data) < MIN_PASSWD_LENGTH) return -1;
-        return create_master_key(data);
-    }
-    return change_passwd(data);
+    int passwdlen = strlen(password);
+
+    if ((state != UNINITIALIZED) || (passwdlen < MIN_PASSWD_LENGTH)) return -1;
+    return create_master_key(password);
 }
 
 int lock()
diff --git a/cmds/keystore/keymgmt.h b/cmds/keystore/keymgmt.h
index 0e928db..116d7a3 100644
--- a/cmds/keystore/keymgmt.h
+++ b/cmds/keystore/keymgmt.h
@@ -72,7 +72,8 @@
             unsigned char *data, int *size);
 int remove_key(const char *namespace, const char *keyname);
 int list_keys(const char *namespace, char reply[BUFFER_MAX]);
-int passwd(char *data);
+int new_passwd(char *password);
+int change_passwd(char *old_pass, char *new_pass);
 int lock();
 int unlock(char *passwd);
 KEYSTORE_STATE get_state();
diff --git a/cmds/keystore/netkeystore.c b/cmds/keystore/netkeystore.c
index bdd5960..82a92c3 100644
--- a/cmds/keystore/netkeystore.c
+++ b/cmds/keystore/netkeystore.c
@@ -85,28 +85,44 @@
     return -1;
 }
 
-static int parse_keyname(char *name, uint32_t len,
-                         char *namespace, char *keyname)
+/**
+ * The function parse_strings() only handle two or three tokens just for
+ * keystore's need.
+ */
+static int parse_strings(char *data, int data_len, int ntokens, ...)
 {
     int count = 0;
-    char *c = namespace, *p = namespace, *t = name;
+    va_list args;
+    char *p = data, **q;
 
-    if (!name || !namespace || !keyname) return -1;
-    while (t < name + len && (*t != 0)) {
-        if (*t == ' ') {
-            if (c == keyname) return -1;
-            *p = count = 0;
-            c = p = keyname;
-            t++;
-        } else {
-            if (!isalnum(*t)) return -1;
-            *p++ = *t++;
-            // also check if the keyname/namespace is too long.
-            if (count++ == MAX_KEY_NAME_LENGTH) return -1;
+    va_start(args, ntokens);
+    q = va_arg(args, char**);
+    *q = p;
+    while (p < (data + data_len)) {
+        if (*(p++) == 0) {
+            if (++count == ntokens) break;
+            if ((q = va_arg(args, char**)) == NULL) break;
+            *q = p;
         }
     }
-    *p = 0;
-    return 0;
+    va_end(args);
+    // the first two strings should be null-terminated and the third could
+    // ignore the delimiter.
+    if (count >= 2) {
+        if ((ntokens == 3) || ((ntokens == 2) && (p == (data + data_len)))) {
+            return 0;
+        }
+    }
+    return -1;
+}
+
+static int is_alnum_string(char *s)
+{
+    while (*s != 0) {
+        if (!isalnum(*s++)) return 0;
+    }
+    LOGE("The string %s is not an alphanumeric string\n", s);
+    return 1;
 }
 
 // args of passwd():
@@ -114,7 +130,17 @@
 // oldPassword newPassword - for changing the password
 static void do_passwd(LPC_MARSHAL *cmd, LPC_MARSHAL *reply)
 {
-    reply->retcode = passwd((char*)cmd->data);
+    char *p1 = NULL, *p2 = NULL;
+
+    if (strlen((char*)cmd->data) == (cmd->len - 1)) {
+        reply->retcode = new_passwd((char*)cmd->data);
+    } else {
+        if (parse_strings((char *)cmd->data, cmd->len, 2, &p1, &p2) != 0) {
+            reply->retcode = -1;
+        } else {
+            reply->retcode = change_passwd(p1, p2);
+        }
+    }
 }
 
 // args of lock():
@@ -150,8 +176,7 @@
 // namespace keyname
 static void do_get_key(LPC_MARSHAL *cmd, LPC_MARSHAL *reply)
 {
-    char namespace[MAX_KEY_NAME_LENGTH];
-    char keyname[MAX_KEY_NAME_LENGTH];
+    char *namespace = NULL, *keyname = NULL;
 
     if (check_get_perm(cr.uid)) {
         LOGE("uid %d doesn't have the permission to get key value\n", cr.uid);
@@ -159,7 +184,8 @@
         return;
     }
 
-    if (parse_keyname((char*)cmd->data, cmd->len, namespace, keyname)) {
+    if (parse_strings((char*)cmd->data, cmd->len, 2, &namespace, &keyname) ||
+        !is_alnum_string(namespace) || !is_alnum_string(keyname)) {
         reply->retcode = -1;
     } else {
         reply->retcode = get_key(namespace, keyname, reply->data,
@@ -182,31 +208,26 @@
 // namespace keyname keyvalue
 static void do_put_key(LPC_MARSHAL *cmd, LPC_MARSHAL *reply)
 {
-    char namespace[MAX_KEY_NAME_LENGTH];
-    char keyname[MAX_KEY_NAME_LENGTH];
+    char *namespace = NULL, *keyname = NULL;
+    char *value = NULL;
 
-    int p = get_value_index(cmd);
-    if (p == -1) {
+    if (parse_strings((char*)cmd->data, cmd->len, 3, &namespace, &keyname, &value) ||
+        !is_alnum_string(namespace) || !is_alnum_string(keyname)) {
         reply->retcode = -1;
-    } else {
-        unsigned char *value;
-        if (parse_keyname((char*)cmd->data, p - 1, namespace, keyname)) {
-            reply->retcode = -1;
-            return;
-        }
-        value = &cmd->data[p];
-        int len = cmd->len - p;
-        reply->retcode = put_key(namespace, keyname, value, len);
+        return;
     }
+    int len = cmd->len - (value - namespace);
+    reply->retcode = put_key(namespace, keyname, (unsigned char *)value, len);
 }
 
 // args of remove_key():
 // namespace keyname
 static void do_remove_key(LPC_MARSHAL *cmd, LPC_MARSHAL *reply)
 {
-    char namespace[MAX_KEY_NAME_LENGTH];
-    char keyname[MAX_KEY_NAME_LENGTH];
-    if (parse_keyname((char*)cmd->data, cmd->len, namespace, keyname)) {
+    char *namespace = NULL, *keyname = NULL;
+
+    if (parse_strings((char*)cmd->data, cmd->len, 2, &namespace, &keyname) ||
+        !is_alnum_string(namespace) || !is_alnum_string(keyname)) {
         reply->retcode = -1;
         return;
     }
@@ -260,8 +281,6 @@
         fprintf(stderr, "Can not open file %s\n", filename);
         return -1;
     }
-    cmd->data[cmd->len] = ' ';
-    cmd->len++;
     len = read(fd, cmd->data + cmd->len, BUFFER_MAX - cmd->len);
     if (len < 0 || (len == (int)(BUFFER_MAX - cmd->len))) {
         ret = -1;
@@ -278,14 +297,15 @@
     char *buf = (char*)cmd->data;
     buf[0] = 0;
     for (i = 0 ; i < argc ; ++i) {
+        // we also include the \0 character in the input.
         if (i == 0) {
-            len = strlcpy(buf, argv[i], BUFFER_MAX);
+            len = (strlcpy(buf, argv[i], BUFFER_MAX) + 1);
         } else {
-            len += snprintf(buf + len, BUFFER_MAX - len, " %s", argv[i]);
+            len += (snprintf(buf + len, BUFFER_MAX - len, "%s", argv[i]) + 1);
         }
         if (len >= BUFFER_MAX) return -1;
     }
-    if (len) cmd->len = len;
+    if (len) cmd->len = len ;
     return 0;
 }
 
diff --git a/cmds/keystore/tests/netkeystore_test.c b/cmds/keystore/tests/netkeystore_test.c
index e7e686b..00390e0 100644
--- a/cmds/keystore/tests/netkeystore_test.c
+++ b/cmds/keystore/tests/netkeystore_test.c
@@ -43,7 +43,7 @@
 #define FUNC_BODY(x) int test_##x()
 
 #define TEST_PASSWD        "12345678"
-#define TEST_NPASSWD    "11111111"
+#define TEST_NPASSWD    "hello world"
 #define TEST_DIR        "/data/local/tmp/keystore"
 #define READONLY_DIR    "/proc/keystore"
 #define TEST_NAMESPACE    "test"
@@ -83,7 +83,7 @@
 FUNC_BODY(get_state)
 {
     if (get_state() != UNINITIALIZED) return -1;
-    passwd(TEST_PASSWD);
+    new_passwd(TEST_PASSWD);
     if (get_state() != UNLOCKED) return -1;
     lock();
     if (get_state() != LOCKED) return -1;
@@ -96,19 +96,17 @@
 {
     char buf[512];
 
-    if (passwd(" 23432dsfsdf") == 0) return -1;
-    if (passwd("dsfsdf") == 0) return -1;
-    passwd(TEST_PASSWD);
+    if (new_passwd("2d fsdf") == 0) return -1;
+    if (new_passwd("dsfsdf") == 0) return -1;
+    new_passwd(TEST_PASSWD);
     lock();
     if (unlock("55555555") == 0) return -1;
     if (unlock(TEST_PASSWD) != 0) return -1;
 
     // change the password
-    sprintf(buf, "%s %s", "klfdjdsklfjg", "abcdefghi");
-    if (passwd(buf) == 0) return -1;
+    if (change_passwd("klfdjdsklfjg", "abcdefghi") == 0) return -1;
 
-    sprintf(buf, "%s %s", TEST_PASSWD, TEST_NPASSWD);
-    if (passwd(buf) != 0) return -1;
+    if (change_passwd(TEST_PASSWD, TEST_NPASSWD) != 0) return -1;
     lock();
 
     if (unlock(TEST_PASSWD) == 0) return -1;
@@ -120,7 +118,7 @@
 FUNC_BODY(lock)
 {
     if (lock() == 0) return -1;
-    passwd(TEST_PASSWD);
+    new_passwd(TEST_PASSWD);
     if (lock() != 0) return -1;
     if (lock() != 0) return -1;
     return EXIT_SUCCESS;
@@ -129,7 +127,7 @@
 FUNC_BODY(unlock)
 {
     int i = MAX_RETRY_COUNT;
-    passwd(TEST_PASSWD);
+    new_passwd(TEST_PASSWD);
     lock();
     while (i > 1) {
         if (unlock(TEST_NPASSWD) != --i) return -1;
@@ -145,7 +143,7 @@
 
     if (put_key(TEST_NAMESPACE, TEST_KEYNAME, (unsigned char *)TEST_KEYVALUE,
                 strlen(TEST_KEYVALUE)) == 0) return -1;
-    passwd(TEST_PASSWD);
+    new_passwd(TEST_PASSWD);
     if (put_key(TEST_NAMESPACE, TEST_KEYNAME, (unsigned char *)TEST_KEYVALUE,
                 strlen(TEST_KEYVALUE)) != 0) return -1;
 
@@ -165,7 +163,7 @@
 
     if (get_key(TEST_NAMESPACE, TEST_KEYNAME, data, &size) == 0) return -1;
 
-    passwd(TEST_PASSWD);
+    new_passwd(TEST_PASSWD);
     put_key(TEST_NAMESPACE, TEST_KEYNAME, (unsigned char *)TEST_KEYVALUE,
             strlen(TEST_KEYVALUE));
     if (get_key(TEST_NAMESPACE, TEST_KEYNAME, data, &size) != 0) return -1;
@@ -178,7 +176,7 @@
 {
     if (remove_key(TEST_NAMESPACE, TEST_KEYNAME) == 0) return -1;
 
-    passwd(TEST_PASSWD);
+    new_passwd(TEST_PASSWD);
     if (remove_key(TEST_NAMESPACE, TEST_KEYNAME) == 0) return -1;
 
     put_key(TEST_NAMESPACE, TEST_KEYNAME, (unsigned char *)TEST_KEYVALUE,
@@ -199,7 +197,7 @@
 
     if (list_keys(TEST_NAMESPACE, reply) == 0) return -1;
 
-    passwd(TEST_PASSWD);
+    new_passwd(TEST_PASSWD);
     if (list_keys(buf, reply) == 0) return -1;
 
     if (list_keys(TEST_NAMESPACE, reply) != 0) return -1;
diff --git a/include/utils/threads.h b/include/utils/threads.h
index e9b0788..0fc533f 100644
--- a/include/utils/threads.h
+++ b/include/utils/threads.h
@@ -408,6 +408,9 @@
     volatile bool           mExitPending;
     volatile bool           mRunning;
             sp<Thread>      mHoldSelf;
+#if HAVE_ANDROID_OS
+            int             mTid;
+#endif
 };
 
 
diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp
index 8cb89c3..e2b6b51 100644
--- a/libs/audioflinger/AudioFlinger.cpp
+++ b/libs/audioflinger/AudioFlinger.cpp
@@ -1160,7 +1160,7 @@
 
 bool AudioFlinger::MixerThread::threadLoop()
 {
-    unsigned long sleepTime = kBufferRecoveryInUsecs;
+    unsigned long sleepTime = 0;
     int16_t* curBuf = mMixBuffer;
     Vector< sp<Track> > tracksToRemove;
     size_t enabledTracks = 0;
@@ -1215,6 +1215,7 @@
                     }
 
                     standbyTime = systemTime() + kStandbyTimeInNsecs;
+                    sleepTime = 0;
                     continue;
                 }
             }
@@ -1222,14 +1223,31 @@
             enabledTracks = prepareTracks_l(activeTracks, &tracksToRemove);
        }
 
-        if (LIKELY(enabledTracks)) {
-            // mix buffers...
-            mAudioMixer->process(curBuf);
 
-            // output audio to hardware
-            if (mSuspended) {
-                usleep(kMaxBufferRecoveryInUsecs);
+        // output audio to hardware
+        if (mSuspended) {
+            usleep(kMaxBufferRecoveryInUsecs);
+        } else {
+            if (LIKELY(enabledTracks)) {
+                // mix buffers...
+                mAudioMixer->process(curBuf);
+                sleepTime = 0;
+                standbyTime = systemTime() + kStandbyTimeInNsecs;
             } else {
+                sleepTime += kBufferRecoveryInUsecs;
+                // There was nothing to mix this round, which means all
+                // active tracks were late. Sleep a little bit to give
+                // them another chance. If we're too late, write 0s to audio
+                // hardware to avoid underrun.
+                if (sleepTime < kMaxBufferRecoveryInUsecs) {
+                    usleep(kBufferRecoveryInUsecs);
+                } else {
+                    memset (curBuf, 0, mixBufferSize);
+                    sleepTime = 0;
+                }
+            }
+            // sleepTime == 0 means PCM data were written to mMixBuffer[]
+            if (sleepTime == 0) {
                 mLastWriteTime = systemTime();
                 mInWrite = true;
                 int bytesWritten = (int)mOutput->write(curBuf, mixBufferSize);
@@ -1237,24 +1255,11 @@
                 mNumWrites++;
                 mInWrite = false;
                 mStandby = false;
-                nsecs_t temp = systemTime();
-                standbyTime = temp + kStandbyTimeInNsecs;
-                nsecs_t delta = temp - mLastWriteTime;
+                nsecs_t delta = systemTime() - mLastWriteTime;
                 if (delta > maxPeriod) {
                     LOGW("write blocked for %llu msecs", ns2ms(delta));
                     mNumDelayedWrites++;
                 }
-                sleepTime = kBufferRecoveryInUsecs;
-            }
-        } else {
-            // There was nothing to mix this round, which means all
-            // active tracks were late. Sleep a little bit to give
-            // them another chance. If we're too late, the audio
-            // hardware will zero-fill for us.
-            // LOGV("thread %p no buffers - usleep(%lu)", this, sleepTime);
-            usleep(sleepTime);
-            if (sleepTime < kMaxBufferRecoveryInUsecs) {
-                sleepTime += kBufferRecoveryInUsecs;
             }
         }
 
@@ -1568,7 +1573,7 @@
 
 bool AudioFlinger::DirectOutputThread::threadLoop()
 {
-    unsigned long sleepTime = kBufferRecoveryInUsecs;
+    unsigned long sleepTime = 0;
     sp<Track> trackToRemove;
     sp<Track> activeTrack;
     nsecs_t standbyTime = systemTime();
@@ -1618,6 +1623,7 @@
                     }
 
                     standbyTime = systemTime() + kStandbyTimeInNsecs;
+                    sleepTime = 0;
                     continue;
                 }
             }
@@ -1710,46 +1716,48 @@
             }
        }
 
-        if (activeTrack != 0) {
-            AudioBufferProvider::Buffer buffer;
-            size_t frameCount = mFrameCount;
-            curBuf = (int8_t *)mMixBuffer;
-            // output audio to hardware
-            mLastWriteTime = systemTime();
-            mInWrite = true;
-            while(frameCount) {
-                buffer.frameCount = frameCount;
-                activeTrack->getNextBuffer(&buffer);
-                if (UNLIKELY(buffer.raw == 0)) {
-                    memset(curBuf, 0, frameCount * mFrameSize);
-                    break;
+        // output audio to hardware
+        if (mSuspended) {
+            usleep(kMaxBufferRecoveryInUsecs);
+        } else {
+            if (activeTrack != 0) {
+                AudioBufferProvider::Buffer buffer;
+                size_t frameCount = mFrameCount;
+                curBuf = (int8_t *)mMixBuffer;
+                // output audio to hardware
+                while(frameCount) {
+                    buffer.frameCount = frameCount;
+                    activeTrack->getNextBuffer(&buffer);
+                    if (UNLIKELY(buffer.raw == 0)) {
+                        memset(curBuf, 0, frameCount * mFrameSize);
+                        break;
+                    }
+                    memcpy(curBuf, buffer.raw, buffer.frameCount * mFrameSize);
+                    frameCount -= buffer.frameCount;
+                    curBuf += buffer.frameCount * mFrameSize;
+                    activeTrack->releaseBuffer(&buffer);
                 }
-                memcpy(curBuf, buffer.raw, buffer.frameCount * mFrameSize);
-                frameCount -= buffer.frameCount;
-                curBuf += buffer.frameCount * mFrameSize;
-                activeTrack->releaseBuffer(&buffer);
-            }
-            if (mSuspended) {
-                usleep(kMaxBufferRecoveryInUsecs);
+                sleepTime = 0;
+                standbyTime = systemTime() + kStandbyTimeInNsecs;
             } else {
+                sleepTime += kBufferRecoveryInUsecs;
+                if (sleepTime < kMaxBufferRecoveryInUsecs) {
+                    usleep(kBufferRecoveryInUsecs);
+                } else {
+                    memset (mMixBuffer, 0, mFrameCount * mFrameSize);
+                    sleepTime = 0;
+                }
+            }
+
+            // sleepTime == 0 means PCM data were written to mMixBuffer[]
+            if (sleepTime == 0) {
+                mLastWriteTime = systemTime();
+                mInWrite = true;
                 int bytesWritten = (int)mOutput->write(mMixBuffer, mixBufferSize);
                 if (bytesWritten) mBytesWritten += bytesWritten;
                 mNumWrites++;
                 mInWrite = false;
                 mStandby = false;
-                nsecs_t temp = systemTime();
-                standbyTime = temp + kStandbyTimeInNsecs;
-                sleepTime = kBufferRecoveryInUsecs;
-            }
-        } else {
-            // There was nothing to mix this round, which means all
-            // active tracks were late. Sleep a little bit to give
-            // them another chance. If we're too late, the audio
-            // hardware will zero-fill for us.
-            //LOGV("no buffers - usleep(%lu)", sleepTime);
-            usleep(sleepTime);
-            if (sleepTime < kMaxBufferRecoveryInUsecs) {
-                sleepTime += kBufferRecoveryInUsecs;
             }
         }
 
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/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/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);