Merge changes I1c5b075b,I4bf5b314

* changes:
  Fix BINDER_LIB_TEST_NOP_CALL_BACK.
  Add test for async transaction queueing.
diff --git a/cmds/lshal/Lshal.cpp b/cmds/lshal/Lshal.cpp
index e2d5f6d..0d4a1d1 100644
--- a/cmds/lshal/Lshal.cpp
+++ b/cmds/lshal/Lshal.cpp
@@ -69,7 +69,7 @@
             "    lshal [list] [--interface|-i] [--transport|-t] [-r|--arch] [-e|--threads]\n"
             "            [--pid|-p] [--address|-a] [--clients|-c] [--cmdline|-m]\n"
             "            [--sort={interface|i|pid|p}] [--init-vintf[=<output file>]]\n"
-            "            [--debug|-d[=<output file>]]\n"
+            "            [--debug|-d[=<output file>]] [--neat]\n"
             "        -i, --interface: print the interface name column\n"
             "        -n, --instance: print the instance name column\n"
             "        -t, --transport: print the transport mode column\n"
@@ -84,7 +84,8 @@
             "                IBase::debug with empty options\n"
             "        --sort=i, --sort=interface: sort by interface name\n"
             "        --sort=p, --sort=pid: sort by server pid\n"
-            "        --init-vintf=<output file>: form a skeleton HAL manifest to specified\n"
+            "        --neat: output is machine parsable (no explanatory text)\n"
+            "        --init-vintf[=<output file>]: form a skeleton HAL manifest to specified\n"
             "                      file, or stdout if no file specified.\n";
 
     static const std::string debug =
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index d0cd8f2..90c96a2 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -465,22 +465,33 @@
 void IPCThreadState::processPendingDerefs()
 {
     if (mIn.dataPosition() >= mIn.dataSize()) {
-        size_t numPending = mPendingWeakDerefs.size();
-        if (numPending > 0) {
-            for (size_t i = 0; i < numPending; i++) {
-                RefBase::weakref_type* refs = mPendingWeakDerefs[i];
+        /*
+         * The decWeak()/decStrong() calls may cause a destructor to run,
+         * which in turn could have initiated an outgoing transaction,
+         * which in turn could cause us to add to the pending refs
+         * vectors; so instead of simply iterating, loop until they're empty.
+         *
+         * We do this in an outer loop, because calling decStrong()
+         * may result in something being added to mPendingWeakDerefs,
+         * which could be delayed until the next incoming command
+         * from the driver if we don't process it now.
+         */
+        while (mPendingWeakDerefs.size() > 0 || mPendingStrongDerefs.size() > 0) {
+            while (mPendingWeakDerefs.size() > 0) {
+                RefBase::weakref_type* refs = mPendingWeakDerefs[0];
+                mPendingWeakDerefs.removeAt(0);
                 refs->decWeak(mProcess.get());
             }
-            mPendingWeakDerefs.clear();
-        }
 
-        numPending = mPendingStrongDerefs.size();
-        if (numPending > 0) {
-            for (size_t i = 0; i < numPending; i++) {
-                BBinder* obj = mPendingStrongDerefs[i];
+            if (mPendingStrongDerefs.size() > 0) {
+                // We don't use while() here because we don't want to re-order
+                // strong and weak decs at all; if this decStrong() causes both a
+                // decWeak() and a decStrong() to be queued, we want to process
+                // the decWeak() first.
+                BBinder* obj = mPendingStrongDerefs[0];
+                mPendingStrongDerefs.removeAt(0);
                 obj->decStrong(mProcess.get());
             }
-            mPendingStrongDerefs.clear();
         }
     }
 }
diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp
index 1425940..1611e11 100644
--- a/libs/binder/tests/binderLibTest.cpp
+++ b/libs/binder/tests/binderLibTest.cpp
@@ -800,10 +800,10 @@
 
     const flat_binder_object *fb = reply.readObject(false);
     ASSERT_TRUE(fb != NULL);
-    EXPECT_EQ(fb->hdr.type, BINDER_TYPE_HANDLE);
-    EXPECT_EQ(ProcessState::self()->getStrongProxyForHandle(fb->handle), m_server);
-    EXPECT_EQ(fb->cookie, (binder_uintptr_t)0);
-    EXPECT_EQ(fb->binder >> 32, (binder_uintptr_t)0);
+    EXPECT_EQ(BINDER_TYPE_HANDLE, fb->hdr.type);
+    EXPECT_EQ(m_server, ProcessState::self()->getStrongProxyForHandle(fb->handle));
+    EXPECT_EQ((binder_uintptr_t)0, fb->cookie);
+    EXPECT_EQ((uint64_t)0, (uint64_t)fb->binder >> 32);
 }
 
 TEST_F(BinderLibTest, FreedBinder) {